diff --git a/.Rbuildignore b/.Rbuildignore index db69196..cb1ce54 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -1,4 +1,5 @@ ^.*\.Rproj$ ^\.Rproj\.user$ -README.html +man-roxygen +inst\tests README.md diff --git a/.gitignore b/.gitignore index 2562982..904c456 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .Rproj.user .Rhistory .RData -README.html \ No newline at end of file +README.html +docs/Alerts2.html \ No newline at end of file diff --git a/DESCRIPTION b/DESCRIPTION index 3a826ea..5d8df8a 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,13 +1,14 @@ Package: shinyBS Type: Package -Title: Twitter Bootstrap Components for Shiny -Version: 0.25 -Date: 2014-03-13 +Title: Extra Twitter Bootstrap Components for Shiny +Version: 0.62 +Date: 2015-03-31 Author: Eric Bailey -Maintainer: Eric Bailey -Description: Adds more Twitter Bootstrap components to the shiny interface -Depends: methods -Imports: shiny (>= 0.8.0) -URL: https://github.com/ebailey78/shinyBS +Maintainer: Eric Bailey +Description: Adds easy access to additional Twitter Bootstrap components to Shiny. +Imports: + shiny (>= 0.13.2), + htmltools +URL: https://ebailey78.github.io/shinyBS BugReports: https://github.com/ebailey78/shinyBS/issues -License: GPL-3 +License: GPL-3 \ No newline at end of file diff --git a/NAMESPACE b/NAMESPACE index c0aaf43..f3c7843 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,47 +1,23 @@ -export(bsAlert, -createAlert, -closeAlert, -bsDemo, -bsNavDemo, -bsGlyph, -bsNavBar, -updateNavBar, -bsNavLink, -bsNavToggleLink, -updateToggleLink, -pageWithNavBar, -bsNavDivider, -bsNavButton, -bsNavTextInput, -bsNavDateInput, -bsNavDateRangeInput, -bsNavDropDown, -updateDropDown, -bsNavTextOutput, -bsPopover, -addPopover, -bsProgressBar, -updateProgressBar, -bsTooltip, -addTooltip, -bsTypeAhead, -bsNavTypeAhead, -updateTypeAhead, -removeTooltip, -removePopover, -bsCollapse, -bsCollapsePanel, -updateCollapse, -bsButtonGroup, -bsButton, -bsActionButton, -bsToggleButton, -updateButtonGroup, -updateButton, -highlightCells, -highlightRows, -bsMedia, -bsModal, -toggleModal) -import(shiny, - methods) +# Generated by roxygen2 (4.1.0): do not edit by hand + +export(addPopover) +export(addTooltip) +export(bsAlert) +export(bsButton) +export(bsCollapse) +export(bsCollapsePanel) +export(bsExample) +export(bsModal) +export(bsPopover) +export(bsTooltip) +export(bsTypeahead) +export(closeAlert) +export(createAlert) +export(popify) +export(removePopover) +export(removeTooltip) +export(tipify) +export(toggleModal) +export(updateButton) +export(updateCollapse) +export(updateTypeahead) diff --git a/NEWS b/NEWS deleted file mode 100644 index 245212f..0000000 --- a/NEWS +++ /dev/null @@ -1,52 +0,0 @@ -Version 0.20 --------------------------------------------------------------------------------- -* pageWithNavBar() - * I forgot to include the pageWithNavbar function in the NAMESPACE file so it - wasn't exported - -* Buttons/Button Groups - * singletons for including shinyBS's javascript and CSS files weren't added - when only button functions were included in an app - * buttons now have 'block' argument to create block-level buttons - * bsButtonGroup has 'block' argument to create block-level button groups - * Button Groups can now be vertically oriented with 'vertical' argument - -* Tooltips/Popovers - * Tooltips and Popovers will now work with the new selectize-type - selectInput's in shiny 0.9.0 - -* Tables - * highlightCells lets you highlight table cells based on their content - * highlightRows lets you highlight table rows based on the content of a table - column - - -Version 0.10 (Initial Release) --------------------------------------------------------------------------------- -* Alerts - Create alert anchors in your `ui.R` script and add alerts from - `server.R` - -* Tooltips - Add and configure tooltips on any element with an `inputId` or - `outputId` with `bsTooltip()` from the ui or with `addToolTip()` from the - server. - -* Popovers - Works the same as Tooltips but useful for more content heavy - applications. - -* TypeAhead - Works just like a 'textInput' but you can provide custom - autocomplete lists to guide the user to specific inputs. - -* Progress Bars - Fully configurable Progress bars that can be updated and - changed from `server.R`. - -* Navigation Bars - Create Bootstrap style navigation bars with buttons, links, - dropdowns, etc that control your shiny app. - -* Collapse Panels - Create collapsable panels that allow you to remove some - clutter from your app. - -* Buttons Groups - Create button groups that behave like radio buttons or - checkbox groups - -* Buttons - Access Twitter Bootstrap styles and sizes for action buttons and - toggle buttons \ No newline at end of file diff --git a/R/Alerts.R b/R/Alerts.R new file mode 100644 index 0000000..95e3407 --- /dev/null +++ b/R/Alerts.R @@ -0,0 +1,82 @@ +#'Alerts +#' +#'Alerts allow you to communicate information to the user on the fly. Standard +#'Bootstrap styling options give the user a hint at the type of information +#'contained in the Alert. +#' +#'@section Components: +#'There are three functions in the Alerts family: +#' \describe{ +#' \item{\code{\link{bsAlert}}}{Used in the UI to create an anchor where your +#' Alerts will be displayed.} +#' \item{\code{\link{createAlert}}}{Used in the Server logic to create +#' alerts. This would be used within a reactive context to display error +#' or success messages to the user based on the status of that context.} +#' \item{\code{\link{closeAlert}}}{Used in the Server logic to close an alert +#' that is already open. By default, Alerts are dismissable by the user, +#' but this offers you a way to close them programmatically.} +#' } +#' +#'@details +#'To create alerts in your Shiny app you must place \code{bsAlert} in your ui. +#'This serves as an anchor that tells shinyBS where to place the alerts created +#'with \code{createAlert}. +#' +#'Use \code{createAlert} in your server script to add alerts to the anchor +#'you created with \code{bsAlert} in your ui. You can place \code{createAlert} +#'in observers, reactives, or outputs. A common usage may be to have logic that +#'validates a user's inputs. If they are valid produce the requested output, if +#'not use \code{createAlert} to give the user info about what they need to +#'change. +#' +#'@section Changes: +#'\code{style} was called \code{type} in previous versions of shinyBS. +#' +#'\code{anchorId} was called \code{inputId} in previous versions of shinyBS. +#' +#'\code{content} was called \code{message} in previous versions of shinyBS. +#' +#'@examples +#' +#'library(shiny) +#'library(shinyBS) +#'app = shinyApp( +#' ui = +#' fluidPage( +#' sidebarLayout( +#' sidebarPanel(textInput("num1", NULL, value = 100), +#' "divided by", textInput("num2", NULL, value = 20), +#' "equals", textOutput("exampleOutput")), +#' mainPanel( +#' bsAlert("alert") +#' ) +#' ) +#' ), +#' server = +#' function(input, output, session) { +#' output$exampleOutput <- renderText({ +#' num1 <- as.numeric(input$num1) +#' num2 <- as.numeric(input$num2) +#' +#' if(is.na(num1) | is.na(num2)) { +#' createAlert(session, "alert", "exampleAlert", title = "Oops", +#' content = "Both inputs should be numeric.", append = FALSE) +#' } else if(num2 == 0) { +#' createAlert(session, "alert", "exampleAlert", title = "Oops", +#' content = "You cannot divide by 0.", append = FALSE) +#' } else { +#' closeAlert(session, "exampleAlert") +#' return(num1/num2) +#' } +#' +#' }) +#' } +#') +#' +#'\dontrun{ +#' runApp(app) +#'} +#'@templateVar item_name Alerts +#'@templateVar family_name Alerts +#'@template footer +NULL \ No newline at end of file diff --git a/R/Buttons.R b/R/Buttons.R new file mode 100644 index 0000000..f391998 --- /dev/null +++ b/R/Buttons.R @@ -0,0 +1,115 @@ +#'Buttons +#' +#'Twitter Bootstrap gives many options for styling buttons that aren't made +#'available by standard Shiny. Use shinyBS to create buttons of different sizes, +#'shapes, and colors. +#' +#'@section Components: +#'There are two functions in the Buttons family: +#' \describe{ +#' \item{\code{\link{bsButton}}}{Used in the UI to create a button. Buttons +#' can be of the type \code{action} or \code{toggle}.} +#' \item{\code{\link{updateButton}}}{Used in the Server logic to modify the +#' state of a button created with \code{\link{bsButton}}} +#' } +#' +#'@details +#'Create a button in the UI with \code{\link{bsButton}}. If \code{type = "action"} +#'the button will behave like the standard \code{\link{actionButton}} in shiny. +#'If \code{type = "toggle"} the button will behave like a \code{\link{checkboxInput}} +#'with an on and off state. It will return \code{TRUE} or \code{FALSE} to the Server +#'depending on its state. +#' +#'You can update the style and state of a \code{\link{bsButton}} from the Server +#'logic with \code{\link{updateButton}}. For example, a button could be set to +#'\code{disabled = TRUE} until the user has made some other selections, then once +#'those selections have been made, an observer on the Server could use \code{\link{updateButton}} +#'to enable the button allowing the user to proceed. Alternatively, you could set +#'the button to \code{style = "success"} to let them know that the button is ready +#'to be clicked. +#' +#'@section Changes: +#'\code{bsActionButton} and \code{bsToggleButton} were replaced with just +#'\code{\link{bsButton}} with a \code{type} argument. +#' +#'\code{icon} was added to allow placing an icon in the button. +#' +#'@examples +#'library(shiny) +#'library(shinyBS) +#'app = shinyApp( +#' ui = +#' fluidPage( +#' sidebarLayout( +#' sidebarPanel( +#' sliderInput("bins", +#' "Move the slider to see its effect on the button below:", +#' min = 1, +#' max = 50, +#' value = 1), +#' bsButton("actTwo", label = "Click me if you dare!", icon = icon("ban")), +#' tags$p("Clicking the first button below changes the disabled state of the second button."), +#' bsButton("togOne", label = "Toggle button disabled status", +#' block = TRUE, type = "toggle", value = TRUE), +#' bsButton("actOne", label = "Block Action Button", block = TRUE) +#' +#' ), +#' mainPanel( +#' textOutput("exampleText") +#' ) +#' ) +#' ), +#' server = +#' function(input, output, session) { +#' observeEvent(input$togOne, ({ +#' updateButton(session, "actOne", disabled = !input$togOne) +#' })) +#' observeEvent(input$bins, ({ +#' +#' b <- input$bins +#' disabled = NULL +#' style = "default" +#' icon = "" +#' +#' if(b < 5) { +#' disabled = TRUE +#' icon <- icon("ban") +#' } else { +#' disabled = FALSE +#' } +#' +#' if(b < 15 | b > 35) { +#' style = "danger" +#' } else if(b < 20 | b > 30) { +#' style = "warning" +#' } else { +#' style = "default" +#' icon = icon("check") +#' } +#' +#' updateButton(session, "actTwo", disabled = disabled, style = style, icon = icon) +#' +#' })) +#' +#' output$exampleText <- renderText({ +#' input$actTwo +#' b <- isolate(input$bins) +#' txt = "" +#' if((b > 5 & b < 15) | b > 35) { +#' txt = "That was dangerous." +#' } else if((b > 5 & b < 20) | b > 30) { +#' txt = "I warned you about that." +#' } else if(b >= 20 & b <= 30) { +#' txt = "You have chosen... wisely." +#' } +#' return(txt) +#' }) +#' } +#') +#'\dontrun{ +#' runApp(app) +#'} +#'@templateVar item_name Buttons +#'@templateVar family_name Buttons +#'@template footer +NULL \ No newline at end of file diff --git a/R/Collapses.R b/R/Collapses.R new file mode 100644 index 0000000..1208b8e --- /dev/null +++ b/R/Collapses.R @@ -0,0 +1,71 @@ +#'Collapses +#' +#' Collapse panels allow you to reduce clutter in your Shiny app by making +#' panels of information that open and close with a user's click. Any type of +#' content can go in a collapse panel. Standard Bootstrap styling options are +#' available. +#' +#'@section Components: +#' \describe{ +#' \item{\code{\link{bsCollapse}}}{A container for holder the individual panels created by \code{\link{bsCollapsePanel}}.} +#' \item{\code{\link{bsCollapsePanel}}}{Creates an individual Collapse Panel that resides within a \code{\link{bsCollapse}}.} +#' \item{\code{\link{updateCollapse}}}{Used within your server logic to open/close collapse panels or change their style.} +#'} +#' +#'@details +#'Collapses are designed to mimic \code{\link{tabsetPanel}} in their implementation. +#'Start with \code{bsCollapse} to create a panel group, then fill it with panels +#'using \code{bsCollapsePanel}. +#' +#'\code{bsCollapse} acts as an input, so you can retrieve which panels are open +#'from the input object passed to the function in \code{\link{shinyServer}}. +#' +#'\code{updateCollapse} can be used within your server logic to open/close +#'collapse panels or to change their style. +#' +#'@section Changes: +#'\code{style} is a new option that wasn't available in previous versions of +#'shinyBS. +#' +#'@examples +#'library(shiny) +#'library(shinyBS) +#' +#'app = shinyApp( +#' ui = +#' fluidPage( +#' sidebarLayout( +#' sidebarPanel(HTML("This button will open Panel 1 using updateCollapse."), +#' actionButton("p1Button", "Push Me!"), +#' selectInput("styleSelect", "Select style for Panel 1", +#' c("default", "primary", "danger", "warning", "info", "success")) +#' ), +#' mainPanel( +#' bsCollapse(id = "collapseExample", open = "Panel 2", +#' bsCollapsePanel("Panel 1", "This is a panel with just text ", +#' "and has the default style. You can change the style in ", +#' "the sidebar.", style = "info"), +#' bsCollapsePanel("Panel 2", "This panel has a generic plot. ", +#' "and a 'success' style.", plotOutput("genericPlot"), style = "success") +#' ) +#' ) +#' ) +#' ), +#' server = +#' function(input, output, session) { +#' output$genericPlot <- renderPlot(plot(rnorm(100))) +#' observeEvent(input$p1Button, ({ +#' updateCollapse(session, "collapseExample", open = "Panel 1") +#' })) +#' observeEvent(input$styleSelect, ({ +#' updateCollapse(session, "collapseExample", style = list("Panel 1" = input$styleSelect)) +#' })) +#' } +#') +#'\dontrun{ +#' runApp(app) +#'} +#'@templateVar item_name Collapses +#'@templateVar family_name Collapses +#'@template footer +NULL diff --git a/R/Modals.R b/R/Modals.R new file mode 100644 index 0000000..0237a28 --- /dev/null +++ b/R/Modals.R @@ -0,0 +1,93 @@ +#'Modals +#' +#'Modal windows are similar to popups but are rendered within the +#'original window. They can contain any combination of shiny inputs, shiny +#'outputs, and html. Possible uses include extra controls that you don't want +#'cluttering up the main app display or help pages to explain your apps +#'operation. +#' +#'@section Components: +#'There are only two functions in the Modals family: +#' \describe{ +#' \item{\code{\link{bsModal}}}{Used in the UI to create a modal window.} +#' \item{\code{\link{toggleModal}}}{Used in the Server logic to open or +#' close a modal window programmatically.} +#' } +#' +#'@details +#'Use \code{\link{bsModal}} in your UI to create a modal window. It works +#'like \code{\link{Collapses}} or \code{\link{tabPanel}}, any non-named arguments +#'will be passed as content for the modal. +#' +#'Create a button or link and assign its \code{inputId} as the \code{trigger} +#'in \code{\link{bsModal}}. +#' +#'@section Changes: +#'There is now a \code{toggle} argument in \code{\link{toggleModal}} that allows +#'you to specify whether you want the modal to open or close. +#' +#'The \code{size} argument in \code{\link{bsModal}} allows you to specify the +#'size of the modal window. Either \code{small} or \code{large}. +#' +#'@examples +#'library(shiny) +#'library(shinyBS) +#' +#'app = shinyApp( +#' ui = +#' fluidPage( +#' sidebarLayout( +#' sidebarPanel( +#' sliderInput("bins", +#' "Number of bins:", +#' min = 1, +#' max = 50, +#' value = 30), +#' actionButton("tabBut", "View Table") +#' ), +#' +#' mainPanel( +#' plotOutput("distPlot"), +#' bsModal("modalExample", "Data Table", "tabBut", size = "large", +#' dataTableOutput("distTable")) +#' ) +#' ) +#' ), +#' server = +#' function(input, output, session) { +#' +#' output$distPlot <- renderPlot({ +#' +#' x <- faithful[, 2] +#' bins <- seq(min(x), max(x), length.out = input$bins + 1) +#' +#' # draw the histogram with the specified number of bins +#' hist(x, breaks = bins, col = 'darkgray', border = 'white') +#' +#' }) +#' +#' output$distTable <- renderDataTable({ +#' +#' x <- faithful[, 2] +#' bins <- seq(min(x), max(x), length.out = input$bins + 1) +#' +#' # draw the histogram with the specified number of bins +#' tab <- hist(x, breaks = bins, plot = FALSE) +#' tab$breaks <- sapply(seq(length(tab$breaks) - 1), function(i) { +#' paste0(signif(tab$breaks[i], 3), "-", signif(tab$breaks[i+1], 3)) +#' }) +#' tab <- as.data.frame(do.call(cbind, tab)) +#' colnames(tab) <- c("Bins", "Counts", "Density") +#' return(tab[, 1:3]) +#' +#' }, options = list(pageLength=10)) +#' +#' } +#') +#'\dontrun{ +#' runApp(app) +#'} +#'@templateVar family_name Modals +#'@templateVar item_name Modals +#'@template footer +NULL diff --git a/R/Tooltips_and_Popovers.R b/R/Tooltips_and_Popovers.R new file mode 100644 index 0000000..bce5ccf --- /dev/null +++ b/R/Tooltips_and_Popovers.R @@ -0,0 +1,166 @@ +#'Tooltips and Popovers +#' +#'Tooltips and Popovers allow you to add additional information about controls +#'or outputs without cluttering up your user interface. You can add a tooltip to +#'a button that displays on hover and better explains what the button will do, or +#'you could add a popover to an output providing further analysis of that output. +#' +#'@section Components: +#'There are eight functions in the Tooltips and Popovers family: +#' \describe{ +#' \item{\code{\link{bsTooltip}}}{Used in the UI to add a tooltip to an element +#' in your UI.} +#' \item{\code{\link{bsPopover}}}{Used in the UI to add a popover to an element +#' in your UI.} +#' \item{\code{\link{tipify}}}{Wrap any UI element in \code{tipify} to add a +#' tooltip to the wrapped element. Preferred for elemented created with +#' \code{\link{renderUI}}.} +#' \item{\code{\link{popify}}}{Wrap any UI element in \code{popify} to add a +#' popover to the wrapped element. Preferred for elements created with +#' \code{\link{renderUI}}.} +#' \item{\code{\link{addTooltip}}}{Used in the Server logic to add a tooltip +#' to an element in your UI.} +#' \item{\code{\link{addPopover}}}{Used in the Server logic to add a popover +#' to an element in your UI.} +#' \item{\code{\link{removeTooltip}}}{Used in the Server logic to remove a +#' tooltip from an element in your UI.} +#' \item{\code{\link{removePopover}}}{Used in the Server logic to remove a +#' popover from an element in your UI.} +#' } +#' +#'@details +#'You can create tooltips and popovers from either the UI script or within the +#'Server logic. \code{\link{bsTooltip}} and \code{\link{bsPopover}} are used in +#'the UI, and \code{\link{addTooltip}} and \code{\link{addPopover}} are used in +#'the Server logic. \code{\link{tipify}} and \code{\link{popify}} can be used +#'within the UI or from within a \code{\link{renderUI}} in the Server logic. They +#'also have the added advantage of not requiring that the UI element have an ID +#'attribute. +#' +#'@note +#'Tooltips and Popovers cannot contain shiny inputs or outputs. +#' +#'There must be at least one \code{shinyBS} component in the UI of your +#'app in order for the necessary dependencies to be loaded. Because of this, +#'\code{\link{addTooltip}} and \code{\link{addPopover}} will not work if they +#'are the only shinyBS components in your app. +#' +#'Tooltips and popovers may not work on some of the more complex shiny inputs +#'or outputs. If you encounter a problem with tooltips or popovers not appearing +#'please file a issue on the github page so I can fix it. +#' +#'@section Changes: +#'An \code{options} argument has been added to the creation functions to allow +#'advanced users more control over how the tooltips and popovers appear. See +#'the \href{http://getbootstrap.com}{Twitter Bootstrap 3 documentation} for more +#'details. +#' +#'@examples +#'library(shiny) +#'library(shinyBS) +#' +#'app = shinyApp( +#' ui = +#' fluidPage( +#' sidebarLayout( +#' sidebarPanel( +#' sliderInput("bins", +#' "Number of bins:", +#' min = 1, +#' max = 50, +#' value = 30), +#' bsTooltip("bins", "The wait times will be broken into this many equally spaced bins", +#' "right", options = list(container = "body")) +#' ), +#' mainPanel( +#' plotOutput("distPlot"), +#' uiOutput("uiExample") +#' ) +#' ) +#' ), +#' server = +#' function(input, output, session) { +#' output$distPlot <- renderPlot({ +#' +#' # generate bins based on input$bins from ui.R +#' x <- faithful[, 2] +#' bins <- seq(min(x), max(x), length.out = input$bins + 1) +#' +#' # draw the histogram with the specified number of bins +#' hist(x, breaks = bins, col = 'darkgray', border = 'white') +#' +#' }) +#' output$uiExample <- renderUI({ +#' tags$span( +#' popify(bsButton("pointlessButton", "Button", style = "primary", size = "large"), +#' "A Pointless Button", +#' "This button is pointless. It does not do anything!"), +#' tipify(bsButton("pB2", "Button", style = "inverse", size = "extra-small"), +#' "This button is pointless too!") +#' ) +#' }) +#' addPopover(session, "distPlot", "Data", content = paste0("

Waiting time between ", +#' "eruptions and the duration of the eruption for the Old Faithful geyser ", +#' "in Yellowstone National Park, Wyoming, USA.

Azzalini, A. and ", +#' "Bowman, A. W. (1990). A look at some data on the Old Faithful geyser. ", +#' "Applied Statistics 39, 357-365.

"), trigger = 'click') +#' } +#') +#'\dontrun{ +#' runApp(app) +#'} +#'@templateVar item_name Tooltips_and_Popovers +#'@templateVar family_name Tooltips_and_Popovers +#'@template footer +NULL + + +## These Functions are common to multiple tooltip and popover functions +# Shared functions with really long names... +createTooltipOrPopoverOnServer <- function(session, id, type, options) { + + data <- list(action = "add", type = type, id = id, options = options) + session$sendCustomMessage(type = "updateTooltipOrPopover", data) + +} + +createTooltipOrPopoverOnUI <- function(id, type, options) { + + options = paste0("{'", paste(names(options), options, sep = "': '", collapse = "', '"), "'}") + + bsTag <- shiny::tags$script(shiny::HTML(paste0("$(document).ready(function() {setTimeout(function() {shinyBS.addTooltip('", id, "', '", type, "', ", options, ")}, 500)});"))) + + htmltools::attachDependencies(bsTag, shinyBSDep) + +} + +buildTooltipOrPopoverOptionsList <- function(title, placement, trigger, options, content) { + + if(is.null(options)) { + options = list() + } + + if(!missing(content)) { + content <- gsub("'", "'", content, fixed = TRUE) + if(is.null(options$content)) { + options$content = shiny::HTML(content) + } + } + + if(is.null(options$placement)) { + options$placement = placement + } + + if(is.null(options$trigger)) { + if(length(trigger) > 1) trigger = paste(trigger, collapse = " ") + options$trigger = trigger + } + + if(is.null(options$title)) { + options$title = title + options$title <- gsub("'", "'", options$title, fixed = TRUE) + } + + return(options) + +} \ No newline at end of file diff --git a/R/addPopover.R b/R/addPopover.R new file mode 100644 index 0000000..aadf0b1 --- /dev/null +++ b/R/addPopover.R @@ -0,0 +1,26 @@ +#'addPopover +#' +#'\code{addPopover} is used within the Server logic of an app to add a popover to a Shiny +#'input or output. +#' +#'@param session The session object passed to function given to shinyServer. +#'@param id The id of the element to attach the popover to. +#'@param title The title of the popover. +#'@param content The main content of the popover. +#'@param placement Where the popover should appear relative to its target +#'(\code{top}, \code{bottom}, \code{left}, or \code{right}). Defaults to \code{bottom}. +#'@param trigger What action should cause the popover to appear? (\code{hover}, +#'\code{focus}, \code{click}, or \code{manual}). Defaults to \code{hover}. +#'@param options A named list of additional options to be set on the popover. +#' +#'@templateVar item_name addPopover +#'@templateVar family_name Tooltips_and_Popovers +#'@template item_details +#'@template footer +#'@export +addPopover <- function(session, id, title, content, placement = "bottom", trigger = "hover", options = NULL) { + + options <- buildTooltipOrPopoverOptionsList(title, placement, trigger, options, content) + createTooltipOrPopoverOnServer(session, id, "popover", options) + +} \ No newline at end of file diff --git a/R/addTooltip.R b/R/addTooltip.R new file mode 100644 index 0000000..f12af41 --- /dev/null +++ b/R/addTooltip.R @@ -0,0 +1,25 @@ +#'addTooltip +#' +#'\code{addTooltip} is used within the Server logic of an app to add a tooltip to a Shiny +#'input or output. +#' +#'@param session The session object passed to function given to shinyServer. +#'@param id The id of the element to attach the tooltip to. +#'@param title The content of the tooltip. +#'@param placement Where the tooltip should appear relative to its target +#'(\code{top}, \code{bottom}, \code{left}, or \code{right}). Defaults to \code{"bottom"}. +#'@param trigger What action should cause the tooltip to appear? (\code{hover}, +#'\code{focus}, \code{click}, or \code{manual}). Defaults to \code{"hover"}. +#'@param options A named list of additional options to be set on the tooltip. +#' +#'@templateVar item_name addTooltip +#'@templateVar family_name Tooltips_and_Popovers +#'@template item_details +#'@template footer +#'@export +addTooltip <- function(session, id, title, placement = "bottom", trigger = "hover", options = NULL) { + + options <- buildTooltipOrPopoverOptionsList(title, placement, trigger, options) + createTooltipOrPopoverOnServer(session, id, "tooltip", options) + +} \ No newline at end of file diff --git a/R/bsAlert.R b/R/bsAlert.R index 55e64a0..7e51cd3 100644 --- a/R/bsAlert.R +++ b/R/bsAlert.R @@ -1,22 +1,21 @@ -# Creates an alert anchor -bsAlert <- function(inputId) { +#'bsAlert +#' +#'\code{bsAlert} creates an anchor point in your UI definition. This anchor point +#'is where alerts created in your Server logic will be displayed. +#' +#'@param anchorId A unique id the identifies the anchor. +#' +#'@templateVar item_name bsAlert +#'@templateVar family_name Alerts +#'@template item_details +#'@template footer +#'@export +bsAlert <- function(anchorId, inline = TRUE) { - sbsHead(tags$div(class="tbs-alert", id = inputId, " ")) - -} - -# Adds and alert to an alert anchor. -createAlert <- function(session, inputId, alertId = NULL, title=NULL, message=NULL, type=NULL, dismiss=TRUE, block=NULL, append=TRUE) { + class <- "sbs-alert" + if(!inline) class = paste(class, "sbs-alert-hover") - data <- dropNulls(list(id=inputId, alertId = alertId, title=title, message=message, type=type, dismiss=dismiss, block=block, append=append)) - - session$sendCustomMessage(type="createalert", data) + bsTag <- shiny::tags$div(class = class, id = anchorId, " ") + htmltools::attachDependencies(bsTag, shinyBSDep) } - -# Closes and alert -closeAlert <- function(session, alertId) { - - session$sendCustomMessage(type="closealert", alertId) - -} \ No newline at end of file diff --git a/R/bsButton.R b/R/bsButton.R new file mode 100644 index 0000000..576eea6 --- /dev/null +++ b/R/bsButton.R @@ -0,0 +1,56 @@ +#'bsButton +#' +#'\code{bsButton} is used in your UI script to create customizable action and toggle +#'buttons. +#' +#'@inheritParams shiny::actionButton +#'@param style A Bootstrap style to apply to the button. (\code{default}, \code{primary}, +#'\code{success}, \code{info}, \code{warning}, or \code{danger}) +#'@param size The size of the button (\code{extra-small}, \code{small}, +#'\code{default}, or \code{large}) +#'@param type The type of button to create. (\code{action} or \code{toggle}) +#'@param block \bold{logical} Should the button take the full width of the parent element? +#'@param disabled \bold{logical} Should the button be disabled (un-clickable)? +#'@param value \bold{logical} If \code{type = "toggle"}, the initial value of the button. +#' +#'@templateVar item_name bsButton +#'@templateVar family_name Buttons +#'@template item_details +#'@template footer +#'@export +bsButton <- function(inputId, label, icon = NULL, ..., style = "default", + size = "default", type = "action", block = FALSE, + disabled = FALSE, value = FALSE) { + btn <- shiny::actionButton(inputId, label, icon, ...) + if(type == "toggle") { + btn <- removeClass(btn, "action-button") + btn <- addClass(btn, "sbs-toggle-button") + if(value == TRUE) { + btn <- addClass(btn, "active") + } + } + if(style != "default") { + btn <- removeClass(btn, "btn-default") + btn <- addClass(btn, paste0("btn-", style)) + } + + size <- switch(size, + "extra-small" = "btn-xs", + "small" = "btn-sm", + "large" = "btn-lg", + "default") + + if(size != "default") { + btn <- addClass(btn, size) + } + + if(block == TRUE) { + btn <- addClass(btn, "btn-block") + } + if(disabled) { + btn <- addAttribs(btn, disabled = "disabled") + } + + htmltools::attachDependencies(btn, shinyBSDep) + +} \ No newline at end of file diff --git a/R/bsButtons.R b/R/bsButtons.R deleted file mode 100644 index ca2973a..0000000 --- a/R/bsButtons.R +++ /dev/null @@ -1,145 +0,0 @@ -# Generic button - used as base for bsToggleButton and bsActionButton and as -# contents of bsButtonGroup -bsButton <- function(inputId, label, value, style = NULL, size = NULL, block = FALSE, - disabled = FALSE) { - - btn <- tags$button(id = inputId, type = "button", class = "btn sbs-btn", label) - - if(disabled) btn <- addClass(btn, "disabled") - if(block) btn <- addClass(btn, "btn-block") - - if(!is.null(style)) { - inputCheck(style = style, valid = c("primary", "info", "success", "warning", - "danger", "inverse", "link")) - btn <- addClass(btn, paste0("btn-", tolower(style))) - } - - if(!is.null(size)) { - inputCheck(size = size, valid = c("large", "small", "mini")) - btn <- addClass(btn, paste0("btn-", tolower(size))) - } - - if(!missing(value)) btn$attribs['data-value'] <- value - - return(sbsHead(btn)) - -} - -# Creates a Toggle button that works like a checkboxinput -bsToggleButton <- function(inputId, label, value = FALSE, style = NULL, - size = NULL, block = FALSE, disabled = FALSE) { - - btn <- bsButton(inputId, label=label, style=style, size=size, block = block, disabled=disabled) - - btn[[2]] <- removeClass(btn[[2]], "sbs-btn") - btn[[2]] <- addClass(btn[[2]], "sbs-toggle-button") - - btn[[2]]$attribs['data-toggle'] <- "button" - - if(value) btn[[2]] <- addClass(btn[[2]], "active bs-active") - - return(btn) - -} - -# Creates an action button like the default action button but with more options -bsActionButton <- function(inputId, label, style = NULL, size = NULL, block = FALSE, - disabled = FALSE) { - - btn <- bsButton(inputId, label, style = style, size=size, block = block, disabled=disabled) - - btn[[2]] <- removeClass(btn[[2]], "sbs-btn") - btn[[2]] <- addClass(btn[[2]], "sbs-action-button") - - return(btn) - -} - -updateButton <- function(session, id, label = NULL, value = NULL, style = NULL, - size = NULL, block = NULL, disabled = NULL) { - - data <- dropNulls(list(label = label, value = value, style = style, - size = size, block = block, disabled = disabled)) - - session$sendInputMessage(id, data) - -} - -# Creates a button group -bsButtonGroup <- function(inputId, ..., label, toggle = "checkbox", style, size, - value = NULL, disabled = FALSE, block = FALSE, vertical = FALSE) { - - # Start the button group tag - btngrp <- tags$div(id = inputId, class = "btn-group sbs-button-group") - btns <- list(...) - - if(inputCheck(toggle = toggle, valid = c("checkbox", "radio"))) { - btngrp$attribs['data-toggle'] <- paste0("buttons-", toggle) - } - - if(block) btngrp <- addClass(btngrp, "btn-block") - if(vertical) btngrp <- addClass(btngrp, "btn-group-vertical") - - if(!missing(style)) { - if(inputCheck(style = style, - valid = c("primary", "info", "success", "warning", - "danger", "inverse", "link"))) { - style = paste0("btn-", style) - } - } - - if(!missing(size)) { - if(inputCheck(size = size, valid = c("large", "small", "mini"))) { - size = paste0("btn-", size) - } - } - - # Loop through the buttons for the group making neccesary changes - for(btn in btns) { - - btn2 <- btn[[2]] - - if(disabled) btn2 <- addClass(btn2, "disabled") - - btn2$attribs['data-toggle'] <- NULL - btn2 <- removeClass(btn2, "action-button btn-block toggle-button active") - - if(btn2$attribs['data-value'] %in% value) { - btn2 <- addClass(btn2, "active bs-active") - } - - if(block) btn2$name <- "span" - - if(!missing(size)) { - btn2 <- removeClass(btn2, "btn-large btn-small btn-mini") - btn2 <- addClass(btn2, size) - } - - if(!missing(style)) { - styles <- "btn-primary btn-info btn-success btn-warning btn-danger btn-inverse btn-link" - btn2 <- removeClass(btn2, styles) - btn2 <- addClass(btn2, style) - } - - btn[[2]] <- btn2 - - btngrp <- tagAppendChild(btngrp, btn) - - } - - if(!missing(label)) { - btngrp <- tagList(tags$label(label, 'for' = inputId), btngrp) - } - - return(sbsHead(btngrp)) - -} - -updateButtonGroup <- function(session, id, toggle = NULL, style = NULL, - size = NULL, disabled = NULL, value = NULL) { - - data <- dropNulls(list(toggle = toggle, style = style, size = size, - disabled = disabled, value = value)) - session$sendInputMessage(id, data) - -} \ No newline at end of file diff --git a/R/bsCollapse.R b/R/bsCollapse.R index 61e4274..cb34f0b 100644 --- a/R/bsCollapse.R +++ b/R/bsCollapse.R @@ -1,48 +1,42 @@ +#'bsCollapse +#' +#'\code{bsCollapse} is used in your UI to create a collapse panel group. Use +#'\code{\link{bsCollapsePanel}} to populate this object with panels. +#' +#'@param \dots \code{\link{bsCollapsePanel}} elements to include in the Collapse. +#'@param id \bold{Optional} You can use \code{input$id} in your Server logic to +#'determine which panels are open, and \code{\link{updateCollapse}} to open/close +#'panels. +#'@param multiple Can more than one panel be open at a time? Defaults to \code{FALSE}. +#'@param open The \code{value}, (or if none was supplied, the \code{title}) of +#'the panel(s) you want open on load. +#' +#'@templateVar item_name bsCollapse +#'@templateVar family_name Collapses +#'@template item_details +#'@template footer +#'@export bsCollapse <- function(..., id = NULL, multiple = FALSE, open = NULL) { - - if(is.null(id)) id = paste0("accordion", sprintf("%07i", as.integer(stats::runif(1, 1, 1000000)))) + + if(is.null(id)) id = paste0("collapse", sprintf("%07i", as.integer(stats::runif(1, 1, 1000000)))) if(!multiple & length(open) > 1) { open <- open[1] } panels <- list(...) + for(i in seq(length(panels))) { - if(panels[[i]]$children[[2]]$attribs$id %in% open) { - panels[[i]]$children[[2]]$attribs$class <- paste(panels[[i]]$children[[2]]$attribs$class, "in") + if(getAttribs(panels[[i]])$value %in% open) { + panels[[i]]$children[[2]] <- addClass(panels[[i]]$children[[2]], "in") + } + if(!multiple) { + panels[[i]]$children[[1]]$children[[1]]$children[[1]] <- addAttribs(panels[[i]]$children[[1]]$children[[1]]$children[[1]], 'data-parent' = paste0("#", id)) } - } - - sbsHead(tags$div(class="accordion", id = id, "data-multiple" = multiple, panels)) - -} - -bsCollapsePanel <- function(title, ..., id = NULL, value = NULL) { - - content <- list(...) - - if(is.null(id)) id <- paste0("cpanel", sprintf("%07i", as.integer(stats::runif(1, 1, 1000000)))) - - if(is.null(value)) { - value = title } - tags$div(class = "accordion-group", - tags$div(class = "accordion-heading", - tags$a(class = "accordion-toggle", 'data-toggle' = "collapse", href = paste0("#", id), title) - ), - tags$div(class = "accordion-body collapse", id = id, "data-value" = value, - tags$div(class = "accordion-inner", content) - ) - ) - + bsTag <- shiny::tags$div(class = "panel-group sbs-panel-group", "data-sbs-multi" = multiple, id=id, role = "tablist", panels) + htmltools::attachDependencies(bsTag, shinyBSDep) } - -updateCollapse <- function(session, id, open = NULL, close = NULL, multiple = NULL) { - - data <- dropNulls(list(open = open, close = close, multiple = multiple)) - session$sendInputMessage(id, data) - -} \ No newline at end of file diff --git a/R/bsCollapsePanel.R b/R/bsCollapsePanel.R new file mode 100644 index 0000000..5f5f16f --- /dev/null +++ b/R/bsCollapsePanel.R @@ -0,0 +1,42 @@ +#'bsCollapsePanel +#' +#'\code{bsCollapsePanel} creates individual panels within a \code{\link{bsCollapse}} object. +#' +#'@param title The title to display at the top of the panel. +#'@param \dots UI elements to include within the panel. +#'@param value \bold{Optional} The value to return when this panel is open. Defaults to \code{title}. +#'@param style \bold{Optional} A Bootstrap style to apply to the panel. (\code{primary}, \code{danger}, \code{warning}, \code{info}, or \code{success}) +#' +#'@templateVar item_name bsCollapsePanel +#'@templateVar family_name Collapses +#'@template item_details +#'@template footer +#'@export +bsCollapsePanel <- function(title, ..., value = title, style = NULL) { + + content <- list(...) + + id <- paste0("cpanel", sprintf("%07i", as.integer(stats::runif(1, 1, 1000000)))) + if(is.null(value)) { + value = title + } + if(is.null(style)) { + style = "default" + } + + bsTag <- shiny::tags$div(class = paste0("panel panel-", style), value = value, + shiny::tags$div(class = "panel-heading", role = "tab", id = paste0("heading_", id), + shiny::tags$h4(class = "panel-title", + shiny::tags$a("data-toggle" = "collapse", href = paste0("#", id), title) + ) + ), + shiny::tags$div(id = id, class = "panel-collapse collapse", role = "tabpanel", + shiny::tags$div(class = "panel-body", content) + ) + ) + + htmltools::attachDependencies(bsTag, shinyBSDep) + +} + + diff --git a/R/bsDemo.R b/R/bsDemo.R deleted file mode 100644 index 50593a3..0000000 --- a/R/bsDemo.R +++ /dev/null @@ -1,20 +0,0 @@ -# Open the demo app that shows all current functionality of the shinyBS package. -bsDemo <- function(port = NULL, launch.browser = getOption("shiny.launch.browser", - interactive())) { - - examplesDir <- system.file("examples", package = "shinyBS") - dir <- normalizePath(paste(examplesDir, "demo", sep = "/")) - runApp(dir, port = port, launch.browser = launch.browser) - -} - -bsNavDemo <- function(port = NULL, launch.browser = getOption("shiny.launch.browser", - interactive())) { - - examplesDir <- system.file("examples", package = "shinyBS") - dir <- normalizePath(paste(examplesDir, "navbar", sep = "/")) - runApp(dir, port = port, launch.browser = launch.browser) - -} - - \ No newline at end of file diff --git a/R/bsExample.R b/R/bsExample.R new file mode 100644 index 0000000..ce758a7 --- /dev/null +++ b/R/bsExample.R @@ -0,0 +1,41 @@ +#'bsExample +#' +#'A function to view examples of shinyBS functionality. Will run the examples +#'found in the examples sections of shinyBS documentation. Use this instead of +#'\code{example}. +#' +#'@param family A shinyBS family name +#'@param display.mode The display mode to use when running the example. See +#'\code{\link{runApp}}. +#'@param \dots Other parameters to pass to \code{\link{runApp}}. +#' +#'@details +#'This function is just a wrapper for \code{\link{runApp}} that runs copies of the +#'examples found in the family documention pages of \code{shinyBS}. By default, +#'\code{display.mode} is set to \code{showcase} so you can see the code while +#'the app is running. +#' +#'@examples +#'\dontrun{ +#' bsExample("Alerts")} +#'@export +bsExample <- function(family, display.mode = "showcase", ...) { + + exp <- system.file("examples", package="shinyBS") + fams <- list.dirs(exp, full.names = FALSE, recursive = FALSE) + + appname <- gsub(" ", "", family, fixed = TRUE) + appname <- gsub("_", "", appname, fixed = TRUE) + + if(appname %in% fams) { + + appname <- normalizePath(paste0(exp, "/", appname)) + shiny::runApp(appname, display.mode = display.mode, ...) + + } else { + + stop("Could not find shinyBS family: ", family, "\nAvailable families are: ", paste0(fams, collapse = ", ")) + + } + +} \ No newline at end of file diff --git a/R/bsGlyph.R b/R/bsGlyph.R deleted file mode 100644 index 6c92a85..0000000 --- a/R/bsGlyph.R +++ /dev/null @@ -1,6 +0,0 @@ -# Add a glyph-icon to a shiny element -bsGlyph <- function(name, white = FALSE) { - class <- name - if(white) class <- paste(class, "icon-white") - tags$i(class=class) -} \ No newline at end of file diff --git a/R/bsModal.R b/R/bsModal.R index 574c82d..38d638f 100644 --- a/R/bsModal.R +++ b/R/bsModal.R @@ -1,29 +1,62 @@ -bsModal <- function(id, title, trigger, ..., href) { - - mo <- tags$div(class = "modal sbs-modal hide fade", id = id, - "data-trigger" = trigger, - tags$div(class = "modal-header", - tags$button(Type = "button", class = "close", - "data-dismiss" = "modal", HTML("×")), - tags$h3(title)), - body <- tags$div(class = "modal-body"), - tags$div(class = "modal-footer", - tags$a(href = "#", class = "btn", "data-dismiss" = "modal", "Close") - ) - ) - - if(!missing(href)) { - mo <- addAttribs(mo, "data-remote" = href) +#'bsModal +#' +#'\code{bsModal} is used within the UI to create a modal window. +#' +#'@param id A unique identifier for the modal window +#'@param title The title to appear at the top of the modal +#'@param trigger The id of a button or link that will open the modal. +#'@param \dots UI elements to include within the modal +#'@param size \bold{Optional} What size should the modal be? (\code{small} or \code{large}) +#'@param footer A \code{list} of shiny UI elements to be added to the footer of the modal. +#'@param close.button Should a close button be added to the footer of the modal? +#'@param width An optional width argument for the modal. Must include units. Only applied if \code{size} is missing. +#'@templateVar item_name bsModal +#'@templateVar family_name Modals +#'@template item_details +#'@template footer +#'@export +bsModal <- function(id, title, trigger, ..., size, footer = NULL, close.button = TRUE, width = NULL) { + if(!missing(size)) { + if(size == "large") { + size = "modal-lg" + } else if(size == "small") { + size = "modal-sm" + } + size <- paste("modal-dialog", size) + width = NULL } else { - mo$children[[2]] <- tagAppendChildren(mo$children[[2]], list = list(...)) + size <- "modal-dialog" } - - return(mo) -} - -toggleModal <- function(session, modalId) { + if(is.null(footer)) { + footer <- tagList() + } - session$sendInputMessage(modalId, list(toggle = TRUE)) + if(close.button) { + footer <- shiny::tagAppendChild(footer, tagList(shiny::tags$button(type = "button", class = "btn btn-default", "data-dismiss" = "modal", "Close"))) + } -} \ No newline at end of file + bsTag <- shiny::tags$div(class = size, + shiny::tags$div(class = "modal-content", + shiny::tags$div(class = "modal-header", + shiny::tags$button(type = "button", class = "close", "data-dismiss" = "modal", shiny::tags$span(shiny::HTML("×"))), + shiny::tags$h4(class = "modal-title", title) + ), + shiny::tags$div(class = "modal-body", list(...)), + shiny::tags$div(class = "modal-footer", + footer + ) + ) + ) + + if(!is.null(width)) { + bsTag <- addAttribs(bsTag, style = paste0("width: ", width, " !important;")) + } + + bsTag <- shiny::tags$div(class = "modal sbs-modal fade", id = id, tabindex = "-1", "data-sbs-trigger" = trigger, + bsTag + ) + + htmltools::attachDependencies(bsTag, shinyBSDep) + +} diff --git a/R/bsNavBar.R b/R/bsNavBar.R deleted file mode 100644 index cb97faa..0000000 --- a/R/bsNavBar.R +++ /dev/null @@ -1,38 +0,0 @@ -# Creates the shell of a navbar that can have navbar elements added to it. -bsNavBar <- function(inputId, brand, ..., rightItems, fixed=FALSE, inverse=FALSE) { - - class <- "navbar" - if(inverse) class <- paste(class, "navbar-inverse") - if(fixed) class <- paste(class, "navbar-fixed-top") - - leftItems <- list(...) - if(missing(rightItems)) rightItems = list("") - - sbsHead(tags$div(id = inputId, class = class, - tags$div(class = "navbar-inner", - tags$a(class="brand", href="#", brand), - tags$ul(class="nav pull-left", leftItems), - tags$ul(class="nav pull-right", rightItems) - ) - ) - ) - -} - -# Allows the user to change some aspects of th navbar from the server. -updateNavBar <- function(session, inputId, brand=NULL, fixed=NULL, inverse=NULL) { - - data <- dropNulls(list(id=inputId, brand=brand, fixed=fixed, inverse=inverse)) - - session$sendCustomMessage(type="modifynavbar", data) - -} - -# Wrapper for creating a page with a navbar -pageWithNavBar <- function(title = "", navbar, mainContent) { - - basicPage(tags$head(tags$title(title)), - navbar, - mainContent) - -} \ No newline at end of file diff --git a/R/bsNavBarInputs.R b/R/bsNavBarInputs.R deleted file mode 100644 index 70043c1..0000000 --- a/R/bsNavBarInputs.R +++ /dev/null @@ -1,116 +0,0 @@ -# Create a link input for a navbar that acts like an actionButton -bsNavLink <- function(inputId, label, href="#") { - - if(!inherits(label, "shiny.tag")) label <- HTML(label) - - tags$li(tags$a(id = inputId, type="button", href = href, class="action-button", label)) - -} - -# Create a link input for a navbar that acts like a checkboxInput -bsNavToggleLink <- function(inputId, label, value=FALSE) { - - if(!inherits(label, "shiny.tag")) label <- HTML(label) - - class = "" - if(value) class = "active" - - tags$li(class = class, tags$a(id = inputId, href="#", class = "sbs-toggle", label)) - -} - -# Update a toggleLink object -updateToggleLink <- function(session, inputId, label=NULL, value=NULL) { - data <- dropNulls(list(label=label, value = value)) - - session$sendInputMessage(inputId, data) - -} - -# Create a vertical divider between navbar elements -bsNavDivider <- function() { - tags$li(class="divider-vertical") -} - -# Wraps actionbutton in a li so it works with bsNavBar -bsNavButton <- function(inputId, label) { - - tags$li(tags$form(class="navbar-form", actionButton(inputId, label))) - -} - -# Same as textInput but with label and a placeholder and optional width argument to save space -bsNavTextInput <- function(inputId, label, value = "", width=NULL) { - - style = "" - if(!is.null(width)) style = paste0("width: ", width, "px;") - - tags$li(tags$form(class="navbar-form", tags$input(id = inputId, style=style, type = "text", value = value, placeholder=label))) - -} - -# dateInput element for navbars -bsNavDateInput <- function(inputId, label, value = NULL, min = NULL, - max = NULL, format = "yyyy-mm-dd", startview = "month", - weekstart = 0, language = "en", width = NULL) { - - if (inherits(value, "Date")) - value <- format(value, "%Y-%m-%d") - if (inherits(min, "Date")) - min <- format(min, "%Y-%m-%d") - if (inherits(max, "Date")) - max <- format(max, "%Y-%m-%d") - - style = "" - if(!is.null(width)) style = paste0("width: ", width, "px;") - - tagList(singleton(tags$head(tags$script(src = "shared/datepicker/js/bootstrap-datepicker.min.js"), - tags$link(rel = "stylesheet", type = "text/css", href = "shared/datepicker/css/datepicker.css"))), - tags$li(tags$form(id = inputId, class = "shiny-date-input navbar-form", tags$input(type = "text", style = style, class = "input-medium datepicker", placeholder = label, - `data-date-language` = language, `data-date-weekstart` = weekstart, - `data-date-format` = format, `data-date-start-view` = startview, - `data-min-date` = min, `data-max-date` = max, `data-initial-date` = value) - ) - ) - ) -} - -# Same as dateRangeInput with slight formatting modification. Would like to figure out how to remove space from between date inputs -bsNavDateRangeInput <- function(inputId, label, start = NULL, end = NULL, - min = NULL, max = NULL, format = "yyyy-mm-dd", - startview = "month", weekstart = 0, language = "en", width=NULL) { - - if (inherits(start, "Date")) - start <- format(start, "%Y-%m-%d") - if (inherits(end, "Date")) - end <- format(end, "%Y-%m-%d") - if (inherits(min, "Date")) - min <- format(min, "%Y-%m-%d") - if (inherits(max, "Date")) - max <- format(max, "%Y-%m-%d") - - style = "" - if(!is.null(width)) style = paste0("width: ", width, "px;") - - x <- label # Just a placeholder - - tagList(singleton(tags$head(tags$script(src = "shared/datepicker/js/bootstrap-datepicker.min.js"), - tags$link(rel = "stylesheet", type = "text/css", href = "shared/datepicker/css/datepicker.css"))), - tags$li(tags$form(id = inputId, class = "shiny-date-range-input input-daterange navbar-form", - tags$input(class = "input-small", style = style, placeholder="Start Date", - type = "text", `data-date-language` = language, - `data-date-weekstart` = weekstart, `data-date-format` = format, - `data-date-start-view` = startview, `data-min-date` = min, - `data-max-date` = max, `data-initial-date` = start), - tags$input(class = "input-small", style = style, placeholder="End Date", - type = "text", `data-date-language` = language, - `data-date-weekstart` = weekstart, `data-date-format` = format, - `data-date-start-view` = startview, `data-min-date` = min, - `data-max-date` = max, `data-initial-date` = end) - ) - ) - ) - - -} - diff --git a/R/bsNavDropDown.R b/R/bsNavDropDown.R deleted file mode 100644 index 4dfd25b..0000000 --- a/R/bsNavDropDown.R +++ /dev/null @@ -1,91 +0,0 @@ -# Creates a dropdown shiny input that returns the value of the last dropdown element clicked - -processChoice <- function(choice) { - - cname <- names(choice) - if(is.null(cname)) cname <- "" - if(cname == "") cname = choice[[1]] - - if(inherits(choice[[1]], "bsmedia")) { - ddi <- tags$li("data-value" = cname, tags$a(tabindex = "-1", href="#", choice[[1]])) - - } else if(!is.list(choice[[1]])) { - if(is.na(choice[[1]])) { - if(is.na(cname)) { - ddi <- tags$li(class = "divider") - } else { - ddi <- tags$li(class = "nav-header", cname) - } - } else { - ddi <- tags$li("data-value" = choice[[1]], tags$a(tabindex = "-1", href = "#", cname)) - } - } else { - ddi <- tags$li(class = "dropdown-submenu", - tags$a(tabindex = "-1", href = "#", cname)) - sdd <- tags$ul(class = "dropdown-menu") - for(i in seq(length(choice[[1]]))) { - sdd <- tagAppendChild(sdd, processChoice(choice[[1]][i])) - } - ddi <- tagAppendChild(ddi, sdd) - - } - - return(ddi) - -} - -bsNavDropDown <- function(inputId, label, choices, selected="") { - - #If label isn't already a shiny tag make it HTML - if(!inherits(label, "shiny.tag")) label <- HTML(label) - - # Start the dropdown HTML - dd <- tags$li(id = inputId, class = "dropdown sbs-dropdown", "data-value" = selected, - tags$a(href="#", class = "dropdown-toggle", "data-toggle" = "dropdown", label, tags$b(class = "caret"))) - - ddm <- tags$ul(class = "dropdown-menu") - - for(i in seq(length(choices))) { - ddm <- tagAppendChild(ddm, processChoice(choices[i])) - } - - return(tagAppendChild(dd, ddm)) - -} - -# Allows updating out navbar dropdowns. -updateDropDown <- function(session, inputId, label=NULL, choices=NULL, selected=NULL) { - - if(!is.null(choices)) { - options <- tags$ul(class = "dropdown-menu") - for(i in seq(length(choices))) { - options <- tagAppendChild(options, processChoice(choices[i])) - } - options <- as.character(options) - } else { - options <- NULL - } - - message <- dropNulls(list(label = label, options = options, - value = selected)) - - session$sendInputMessage(inputId, message) - -} - -bsMedia <- function(id, heading, text, image) { - - med <- tags$div(class = "media", id = id) - - if(!missing(image)) { - med <- tagAppendChild(med, tags$div(class = "pull-left", href = "#", tags$img(class = "media-object", src = image, "data-src" = image))) - } - - med <- tagAppendChild(med, tags$div(class = "media-body", - tags$h4(class = "media-heading", heading), text)) - - class(med) <- c(class(med), "bsmedia") - - return(med) - -} \ No newline at end of file diff --git a/R/bsNavText.R b/R/bsNavText.R deleted file mode 100644 index 1494d44..0000000 --- a/R/bsNavText.R +++ /dev/null @@ -1,4 +0,0 @@ -# same as textOutput but wrapped for better formatting in navbar -bsNavTextOutput <- function(outputId) { - tags$li(tags$p(id = outputId, class="navbar-text shiny-text-output")) -} diff --git a/R/bsPopover.R b/R/bsPopover.R index ea09953..28f190a 100644 --- a/R/bsPopover.R +++ b/R/bsPopover.R @@ -1,24 +1,26 @@ -# Add a popover from the ui.R script -bsPopover <- function(id, title, content, placement="right", trigger="click") { - - sbsHead(tags$script(HTML(paste0("$(document).ready(function() {setTimeout(function() {addPopover('", id, "', '", title, "', '", content, - "', '", placement, "', '", trigger, "')}, 100);})")))) +#'bsPopover +#' +#'\code{bsPopover} is used within the UI of an app to add a popover to a Shiny +#'input or output. +#' +#'@param id The id of the element to attach the popover to. +#'@param title The title of the popover. +#'@param content The main content of the popover. +#'@param placement Where the popover should appear relative to its target +#'(\code{top}, \code{bottom}, \code{left}, or \code{right}). Defaults to \code{"bottom"}. +#'@param trigger What action should cause the popover to appear? (\code{hover}, +#'\code{focus}, \code{click}, or \code{manual}). Defaults to \code{"hover"}. +#'@param options A named list of additional options to be set on the popover. +#' +#'@templateVar item_name bsPopover +#'@templateVar family_name Tooltips_and_Popovers +#'@template item_details +#'@template footer +#'@export +bsPopover <- function(id, title, content, placement="bottom", trigger="hover", options = NULL) { -} - -# Used to dynamically create popovers in server.R -addPopover <- function(session, id, title="", content, placement="right", trigger="click") { - - data <- list(id = id, title = title, content = content, - placement = placement, trigger = trigger) + options = buildTooltipOrPopoverOptionsList(title, placement, trigger, options, content) - session$sendCustomMessage(type="addpopover", data) - -} - -#Remove popover -removePopover <- function(session, id) { - - session$sendCustomMessage(type="removepopover", id) + createTooltipOrPopoverOnUI(id, "popover", options) } \ No newline at end of file diff --git a/R/bsProgressBar.R b/R/bsProgressBar.R deleted file mode 100644 index ddceaf5..0000000 --- a/R/bsProgressBar.R +++ /dev/null @@ -1,33 +0,0 @@ -# Create a progressbar in ui.R -bsProgressBar <- function(inputId, value = 0, visible=TRUE, - color, striped=FALSE, animate=FALSE) { - - class = "progress" - if(striped) { - class=paste(class, "progress-striped") - } else if(animate) { - class=paste(class, "progress-striped active") - } - if(!missing(color)) { - class=paste0(class, " progress-", color) - } - if(!visible) { - class=paste(class, "hidden") - } - - sbsHead(tags$div(class=class, id=inputId, - tags$div(class="bar", style=paste0("width: ", value, "%;")) - ) - ) - -} - -# Update the progress bar from server.R -updateProgressBar <- function(session, inputId, value=NULL, visible=NULL, color=NULL, striped=NULL, animate=NULL) { - - data <- dropNulls(list(id=inputId, value=value, visible=visible, - color=color, striped=striped, animate=animate)) - - session$sendCustomMessage("updateprogress", data) - -} \ No newline at end of file diff --git a/R/bsTable.R b/R/bsTable.R deleted file mode 100644 index c9c3c14..0000000 --- a/R/bsTable.R +++ /dev/null @@ -1,19 +0,0 @@ -highlightCells <- function(session, id, min = NULL, max = NULL, regex = NULL, column = NULL, - class = NULL, style = NULL, reset = NULL, skip.row.names = TRUE) { - - data <- dropNulls(list(id = id, min = min, max = max, regex = regex, column = column, - class = class, style = style, reset = reset, skip = skip.row.names)) - - session$sendCustomMessage("highlightCells", data) - -} - -highlightRows <- function(session, id, column, min=NULL, max=NULL, regex = NULL, - class = NULL, style = NULL, reset = NULL) { - - data <- dropNulls(list(id = id, column = column, min = min, max = max, regex = regex, - class = class, style = style, reset = reset)) - - session$sendCustomMessage("highlightRows", data) - -} \ No newline at end of file diff --git a/R/bsTooltip.R b/R/bsTooltip.R index 76268d3..ae04f6e 100644 --- a/R/bsTooltip.R +++ b/R/bsTooltip.R @@ -1,27 +1,25 @@ -# Used to create a tooltip from ui.R -bsTooltip <- function(id, title, placement="bottom", trigger="hover") { - - if(length(trigger) > 1) trigger = paste(trigger, collapse = " ") - - sbsHead(tags$script(paste0("$(document).ready(function() {setTimeout(function() {addTooltip('", id, "', '", title, "', '", - placement, "', '", trigger, "')}, 100)});"))) - -} - -# Remove Tooltip from object -removeTooltip <- function(session, id) { - - session$sendCustomMessage(type="removetooltip", id) - -} - -# Used to dynamically create tooltips in server.R -addTooltip <- function(session, id, title, placement = "bottom", trigger = "hover") { - - if(length(trigger) > 1) trigger = paste(trigger, collapse = " ") - - data <- list(id = id, title = title, placement = placement, trigger = trigger) - session$sendCustomMessage(type="addtooltip", data) - -} - +#'bsTooltip +#' +#'\code{bsTooltip} is used within the UI of an app to add a tooltip to a Shiny +#'input or output. +#' +#'@param id The id of the element to attach the tooltip to. +#'@param title The content of the tooltip. +#'@param placement Where the tooltip should appear relative to its target +#'(\code{top}, \code{bottom}, \code{left}, or \code{right}). Defaults to \code{"bottom"}. +#'@param trigger What action should cause the tooltip to appear? (\code{hover}, +#'\code{focus}, \code{click}, or \code{manual}). Defaults to \code{"hover"}. +#'@param options A named list of additional options to be set on the tooltip. +#' +#'@templateVar item_name bsTooltip +#'@templateVar family_name Tooltips_and_Popovers +#'@template item_details +#'@template footer +#'@export +bsTooltip <- function(id, title, placement="bottom", trigger="hover", options = NULL) { + + options = buildTooltipOrPopoverOptionsList(title, placement, trigger, options) + + createTooltipOrPopoverOnUI(id, "tooltip", options) + +} \ No newline at end of file diff --git a/R/bsTypeAhead.R b/R/bsTypeAhead.R deleted file mode 100644 index 1513ff3..0000000 --- a/R/bsTypeAhead.R +++ /dev/null @@ -1,41 +0,0 @@ -# Create a typeahead text input -bsTypeAhead <- function(inputId, label, value = "", choices, items=8, minLength=1) { - - choices <- paste0("[\'", paste0(choices, collapse="\', \'") , "\']") - - sbsHead(tagList(tags$label(label, `for` = inputId), - tags$input(id = inputId, type="text", class="sbs-typeahead", - "data-provide"="typeahead", autocomplete="off", - value = value), - tags$script(paste0("$('#", inputId, "').typeahead({source: ", choices, ", - items: ", items, ", - minLength: ", minLength, "})")) - ) - ) - -} - -# Same as bsTypeAhead but with label as placeholder and optional width argument to save space. -bsNavTypeAhead <- function(inputId, label, value = "", choices, items=8, minLength=1, width = NULL) { - - choices <- paste0("[\"", paste0(choices, collapse="\", \"") , "\"]") - - style = "" - if(!is.null(width)) style = paste0("width: ", width, "px;") - - - tags$li(tags$form(class="navbar-form", tags$input(id = inputId, type="text", class="sbs-typeahead", - "data-provide"="typeahead", "data-source"=choices, style=style, - "data-items"=items, "data-minLength"=1, autocomplete="off", - placeholder=label, value = value))) - -} - -# Update a typeahead element from server.R -updateTypeAhead <- function(session, inputId, label=NULL, value=NULL, choices=NULL) { - - data <- dropNulls(list(label=label, value=value, choices=choices)) - - session$sendInputMessage(inputId, data) - -} \ No newline at end of file diff --git a/R/bsTypeahead.R b/R/bsTypeahead.R new file mode 100644 index 0000000..bd05652 --- /dev/null +++ b/R/bsTypeahead.R @@ -0,0 +1,41 @@ +#'bsTypeahead +#' +#'\code{typeaheadInput} creates a textinput with type ahead function buttons. +#' +#'@param inputId Input variable to assign the control's value to +#'@param label Display label for the control +#'@param value Initial value +#'@param choices Array of strings to match against. Can also be JavaScript +#' function. Use htmlwidgets::JS() to indicate JavaScript. The length of \code{choices} must no exceed 131370. +#'@param items The max number of items to display in the dropdown. Can also be +#' set to 'all' +#'@param minLength The minimum character length needed before triggering +#' autocomplete suggestions. You can set it to 0 so suggestion are shown even +#' when there is no text when lookup function is called. +#'@seealso \code{\link{updateTypeaheadInput}} +#'@export +bsTypeahead <- function(inputId, label, value = "", choices, items = 8, minLength = 1) { + if(!is.null(choices)) { + if(length(choices) > 131370) { + warning("Due to a limitation of the Bootstrap2 Typeahead JavaScript library the length of 'choices' must not exceed 2 ^ 17 - 2!"); + } + } + if(!'JS_EVAL' %in% class(choices)) { + choices <- jsonlite::toJSON(choices); + } + typeahead <- shiny::tagList( + shiny::div(class = 'form-group shiny-input-container', + shiny::tags$label(label, `for` = inputId), + shiny::tags$input(id = inputId, type="text", + class="form-control shiny-bound-input typeahead", + "data-provide" = "typeahead", autocomplete="off", + value = value), + shiny::tags$script(paste0("$('#", inputId, "').typeahead({source: ", choices, ", + items: ", items, ", + minLength: ", minLength, "})")) + ) + ) + + htmltools::attachDependencies(typeahead, typeaheadDep) + +} \ No newline at end of file diff --git a/R/closeAlert.R b/R/closeAlert.R new file mode 100644 index 0000000..f96b328 --- /dev/null +++ b/R/closeAlert.R @@ -0,0 +1,18 @@ +#'closeAlert +#' +#'\code{closeAlert} is used within your Server logic to close an alert that you +#'created with \code{\link{createAlert}}. +#' +#'@param alertId The id of the alert to be dismissed. +#'@inheritParams createAlert +#' +#'@templateVar item_name closeAlert +#'@templateVar family_name Alerts +#'@template item_details +#'@template footer +#'@export +closeAlert <- function(session, alertId) { + + session$sendCustomMessage(type="bsAlertClose", alertId) + +} \ No newline at end of file diff --git a/R/createAlert.R b/R/createAlert.R new file mode 100644 index 0000000..16d8807 --- /dev/null +++ b/R/createAlert.R @@ -0,0 +1,30 @@ +#'createAlert +#' +#'\code{createAlert} is used within the Server logic of your Shiny app to display +#'an alert to the user. +#' +#'@param session The session object passed to function given to shinyServer. +#'@param anchorId The unique identifier of the anchor where the alert should be +#'displayed. +#'@param alertId \bold{Optional} A unique identifier for the Alert. +#'@param title \bold{Optional} A title for the Alert. +#'@param content The main body of the Alert. HTML tags are allowed. +#'@param style A bootstrap style to apply. Defaults to \code{info}. +#'@param dismiss \code{logical} Should the Alert be user dismissable? Defaults to \code{TRUE}. +#'@param append \code{logical} Should the Alert be appended below existing Alerts? Default to \code{TRUE}. +#' +#'@templateVar item_name createAlert +#'@templateVar family_name Alerts +#'@template item_details +#'@template footer +#'@export +createAlert <- function(session, anchorId, alertId = NULL, title=NULL, + content=NULL, style=NULL, dismiss=TRUE, append=TRUE) { + + data <- dropNulls(list(id = anchorId, alertId = alertId, title = title, + content = content, style = style, dismiss = dismiss, + append = append)) + + session$sendCustomMessage(type="bsAlertCreate", data) + +} diff --git a/R/misc.R b/R/misc.R index 3623693..3238633 100644 --- a/R/misc.R +++ b/R/misc.R @@ -1,40 +1,16 @@ .onAttach <- function(...) { # Create link to javascript and css files for package - addResourcePath("sbs", system.file("www", package="shinyBS")) + shiny::addResourcePath("sbs", system.file("www", package="shinyBS")) } -# Wrapper to add the appropriate singletons to the head of the shiny app -sbsHead <- function(...) { - - tagList(singleton(tags$head(tags$script(src = "sbs/shinyBS.js"), - tags$link(rel = "stylesheet", type = "text/css", href = "sbs/shinyBS.css"))), - ... - ) -} +shinyBSDep <- htmltools::htmlDependency("shinyBS", packageVersion("shinyBS"), src = c("href" = "sbs"), script = "shinyBS.js", stylesheet = "shinyBS.css") +typeaheadDep <- htmltools::htmlDependency("shinyBS", packageVersion("shinyBS"), src = c("href" = "sbs"), script = c("bootstrap3-typeahead.js", "typeahead_inputbinding.js")); # Copy of dropNulls function for shiny to avoid using shiny:::dropNulls dropNulls <- function(x) { - x[!vapply(x, is.null, FUN.VALUE = logical(1))] -} - -# Takes a tag and removes any classes in the remove argument -removeClass <- function(tag, remove) { - - if(length(remove) == 1) remove <- strsplit(remove, " ", fixed = TRUE)[[1]] - - class <- strsplit(tag$attribs$class, " ", fixed = TRUE)[[1]] - class <- class[!(class %in% remove)] - tag$attribs$class <- paste(class, collapse = " ") - - return(tag) - -} - -addClass <- function(tag, add) { - tag$attribs$class <- paste(tag$attribs$class, add) - return(tag) + x[!vapply(x, is.null, FUN.VALUE = logical(1))] } addAttribs <- function(tag, ...) { @@ -53,27 +29,6 @@ removeAttribs <- function(tag, ...) { return(tag) } -inputCheck <- function(..., valid, stop.func = FALSE) { - - v <- list(...)[1] - - if(!(v %in% valid)) { - - n <- names(list(...))[1] - caller <- deparse(sys.call(-1)[1]) - msg <- paste0("Invalid '", n, "' argument in ", caller, ": ", v) - if(stop.func) { - stop(msg, call. = FALSE) - } else { - warning(msg, call. = FALSE) - } - - return(FALSE) - - } else { - - return(TRUE) - - } - +getAttribs <- function(tag) { + tag$attribs } diff --git a/R/popify.R b/R/popify.R new file mode 100644 index 0000000..1020145 --- /dev/null +++ b/R/popify.R @@ -0,0 +1,36 @@ +#'popify +#' +#'\code{popify} can be wrapped around any shiny UI element to add a popover to the +#'wrapped element. This should be a safer way to add popovers to elements created with +#'\code{\link{renderUI}}. +#' +#'@param el A shiny UI element. +#'@param title The title of the popover. +#'@param content The main content of the popover. +#'@param placement Where the popover should appear relative to its target +#'(\code{top}, \code{bottom}, \code{left}, or \code{right}). Defaults to \code{"bottom"}. +#'@param trigger What action should cause the popover to appear? (\code{hover}, +#'\code{focus}, \code{click}, or \code{manual}). Defaults to \code{"hover"}. +#'@param options A named list of additional options to be set on the popover. +#' +#'@templateVar item_name popify +#'@templateVar family_name Tooltips_and_Popovers +#'@template item_details +#'@template footer +#'@export +popify <- function(el, title, content, placement="bottom", trigger="hover", options = NULL) { + + id <- el$attribs$id + + if(is.null(id)) { + id <- paste0("tipify", as.integer(runif(1, 1, 10000000))) + el <- addAttribs(el, id = id) + } + + options = buildTooltipOrPopoverOptionsList(title, placement, trigger, options, content) + + script <- createTooltipOrPopoverOnUI(id, "popover", options) + + return(shiny::tagList(el, script)) + +} \ No newline at end of file diff --git a/R/removePopover.R b/R/removePopover.R new file mode 100644 index 0000000..024d1de --- /dev/null +++ b/R/removePopover.R @@ -0,0 +1,18 @@ +#'removePopover +#' +#'\code{removePopover} is used within the Server logic of an app to remove an +#'existing popover from a Shiny input or output. +#' +#'@param session The session object passed to function given to shinyServer. +#'@param id The id of the element to remove the popover from. +#' +#'@templateVar item_name removePopover +#'@templateVar family_name Tooltips_and_Popovers +#'@template item_details +#'@template footer +#'@export +removePopover <- function(session, id) { + + session$sendCustomMessage(type="updateTooltipOrPopover", list(action = "remove", type = "popover", id = id)) + +} \ No newline at end of file diff --git a/R/removeTooltip.R b/R/removeTooltip.R new file mode 100644 index 0000000..51ae00e --- /dev/null +++ b/R/removeTooltip.R @@ -0,0 +1,18 @@ +#'removeTooltip +#' +#'\code{removeTooltip} is used within the Server logic of an app to remove an +#'existing tooltip from a Shiny input or output. +#' +#'@param session The session object passed to function given to shinyServer. +#'@param id The id of the element to remove the tooltip from. +#' +#'@templateVar item_name removeTooltip +#'@templateVar family_name Tooltips_and_Popovers +#'@template item_details +#'@template footer +#'@export +removeTooltip <- function(session, id) { + + session$sendCustomMessage(type="updateTooltipOrPopover", list(action = "remove", type = "tooltip", id = id)) + +} \ No newline at end of file diff --git a/R/tagManipulators.R b/R/tagManipulators.R new file mode 100644 index 0000000..a2ad0fe --- /dev/null +++ b/R/tagManipulators.R @@ -0,0 +1,96 @@ +addClass <- function(tag, class) { + + if(!is.null(class)) { + tag$attribs$class <- trimws(paste(tag$attribs$class, class), "both") + } + + tag + +} + +removeClass <- function(tag, class) { + + if(!is.null(class) & !is.null(tag$attribs$class)) { + cls <- strsplit(tag$attribs$class, " ")[[1]] + cls <- cls[cls != class] + tag$attribs$class <- paste(cls, collapse = " ") + } + + tag + +} + +hasClass <- function(tag, class) { + if(!is.null(class) & !is.null(tag$attribs$class)) { + class %in% strsplit(tag$attribs$class, " ")[[1]] + } else { + FALSE + } +} + +checkClass <- function(class, include) { + if(!include) class <- NULL + class +} + +buildClass <- function(prefix, variable) { + if(!is.null(variable)) { + variable <- paste0(prefix, variable) + } + variable +} + +addStyles <- function(tag, ..., .dots) { + + new_styles <- list(...) + + if(!missing(.dots)) { + new_styles <- c(new_styles, .dots) + } + + if(!is.null(tag$attribs$style)) { + styles <- parseStyles(tag$attribs$style) + } else { + styles <- list() + } + + for(i in seq_along(new_styles)) { + styles[[names(new_styles)[i]]] <- new_styles[[i]] + } + + tag$attribs$style <- writeStyles(styles) + + tag + +} + +removeStyles <- function(tag, ...) { + + if(!is.null(tag$attribs$style)) { + styleList <- list(...) + styles <- parseStyles(tag$attribs$style) + styles <- styles[!names(styles) %in% styleList] + tag$attribs$style <- writeStyles(styles) + } + + tag + +} + +parseStyles <- function(styleString) { + + styles <- trimws(strsplit(styleString, ";")[[1]]) + styles <- strsplit(styles, ":") + style_names <- sapply(styles, function(s) trimws(s[1])) + styles <- lapply(styles, function(s) trimws(s[2])) + names(styles) <- style_names + + return(styles) + +} + +writeStyles <- function(styleList) { + + paste(names(styleList), styleList, sep = ": ", collapse = "; ") + +} diff --git a/R/tipify.R b/R/tipify.R new file mode 100644 index 0000000..659d53f --- /dev/null +++ b/R/tipify.R @@ -0,0 +1,35 @@ +#'tipify +#' +#'\code{tipify} can be wrapped around any shiny UI element to add a tooltip to the +#'wrapped element. This should be a safer way to add tooltips to elements created with +#'\code{\link{renderUI}}. +#' +#'@param el A shiny UI element. +#'@param title The content of the tooltip. +#'@param placement Where the tooltip should appear relative to its target +#'(\code{top}, \code{bottom}, \code{left}, or \code{right}). Defaults to \code{"bottom"}. +#'@param trigger What action should cause the tooltip to appear? (\code{hover}, +#'\code{focus}, \code{click}, or \code{manual}). Defaults to \code{"hover"}. +#'@param options A named list of additional options to be set on the tooltip. +#' +#'@templateVar item_name tipify +#'@templateVar family_name Tooltips_and_Popovers +#'@template item_details +#'@template footer +#'@export +tipify <- function(el, title, placement="bottom", trigger="hover", options = NULL) { + + id <- el$attribs$id + + if(is.null(id)) { + id <- paste0("tipify", as.integer(runif(1, 1, 10000000))) + el <- addAttribs(el, id = id) + } + + options = buildTooltipOrPopoverOptionsList(title, placement, trigger, options) + + script <- createTooltipOrPopoverOnUI(id, "tooltip", options) + + return(shiny::tagList(el, script)) + +} \ No newline at end of file diff --git a/R/toggleModal.R b/R/toggleModal.R new file mode 100644 index 0000000..3621535 --- /dev/null +++ b/R/toggleModal.R @@ -0,0 +1,19 @@ +#'toggleModal +#' +#'\code{toggleModal} is used within your Server logic to open or close a modal +#'window. +#' +#'@param session The session object passed to function given to shinyServer. +#'@param modalId The id of the modal window you want to open/close +#'@param toggle Should the modal window \code{open}, \code{close}, or \code{toggle}? +#' +#'@templateVar item_name toggleModal +#'@templateVar family_name Modals +#'@template item_details +#'@template footer +#'@export +toggleModal <- function(session, modalId, toggle = "toggle") { + + session$sendInputMessage(modalId, list(toggle = toggle)) + +} \ No newline at end of file diff --git a/R/updateButton.R b/R/updateButton.R new file mode 100644 index 0000000..03f0c78 --- /dev/null +++ b/R/updateButton.R @@ -0,0 +1,37 @@ +#'updateButton +#' +#'\code{updateButton} is used in your Server logic to update the style or state +#'of a button. +#' +#'@inheritParams bsButton +#'@param session The session object passed to function given to shinyServer. +#' +#'@details Because of the way it is coded, \code{updateButton} may work on buttons not +#'created by \code{\link{bsButton}} such as \code{\link{submitButton}}. +#' +#'See \code{\link{Buttons}} for more information about how to use \code{updateButton} with the rest of the Buttons family. +#' +#'@templateVar item_name updateButton +#'@templateVar family_name Buttons +#'@template item_details +#'@template footer +#'@export +updateButton <- function(session, inputId, label = NULL, icon = NULL, value = NULL, style = NULL, + size = NULL, block = NULL, disabled = NULL) { + + if(!is.null(icon)) icon <- as.character(icon) + + if(!is.null(size)) { + size <- switch(size, + "extra-small" = "btn-xs", + "small" = "btn-sm", + "large" = "btn-lg", + "default" = "default") + } + + data <- dropNulls(list(id = inputId, label = label, icon = icon, value = value, style = style, + size = size, block = block, disabled = disabled)) + + session$sendCustomMessage("bsButtonUpdate", data) + +} \ No newline at end of file diff --git a/R/updateCollapse.R b/R/updateCollapse.R new file mode 100644 index 0000000..000dff2 --- /dev/null +++ b/R/updateCollapse.R @@ -0,0 +1,27 @@ +#'updateCollapse +#' +#'\code{updateCollapse} is used within the Server logic of your Shiny app to +#'modify a Collapse after load. +#' +#'@param session The session object passed to function given to shinyServer. +#'@param id The id of the Collapse object you want to change. +#'@param open A vector of \code{value} (or \code{title} if no \code{value} was +#'provided) values identifying the panels you want to open. +#'@param close A vector of \code{value} (or \code{title} if no \code{value} was +#'provided) values identifying the panels you want to close. +#'@param style A named list of Bootstrap styles (\code{primary}, \code{danger}, \code{info}, +#'\code{warning}, \code{success}, or \code{default}). The names should correspond +#'to the \code{value} (or \code{title} if no \code{value} was provided) of the +#'\code{\link{bsCollapsePanel}} you want to change. +#' +#'@templateVar item_name updateCollapse +#'@templateVar family_name Collapses +#'@template item_details +#'@template footer +#'@export +updateCollapse <- function(session, id, open = NULL, close = NULL, style = NULL) { + + data <- dropNulls(list(open = open, close = close, style = style)) + session$sendInputMessage(id, data) + +} \ No newline at end of file diff --git a/R/updateTypeahead.R b/R/updateTypeahead.R new file mode 100644 index 0000000..8acadba --- /dev/null +++ b/R/updateTypeahead.R @@ -0,0 +1,23 @@ +#'updateTypeahead +#' +#'\code{updateTypeahead} Update a typeaheadInput buttons. +#'@param session The session object passed to function given to shinyServer. +#'@param inputId Input variable to assign the control's value to +#'@param label Display label for the control +#'@param value Initial value +#'@param choices Array of strings to match against. Can also be JavaScript +#' function. Use htmlwidgets::JS() to indicate JavaScript. +#'@seealso \code{\link{typeaheadInput}} +#'@export +updateTypeahead<- function(session, inputId, label=NULL, value=NULL, choices=NULL) { + + if(!is.null(choices)) { + if(length(choices) > 131370) { + warning("Due to a limitation of the Bootstrap2 Typeahead JavaScript library the length of 'choices' must not exceed 2 ^ 17 - 2!"); + } + } + + data <- dropNulls(list(id = inputId, label=label, value=value, choices=choices)) + session$sendCustomMessage("typeaheadUpdate", data) + +} diff --git a/README.md b/README.md index bf713ad..d4bd08e 100644 --- a/README.md +++ b/README.md @@ -8,70 +8,34 @@ Eric shinyBS ------- -**shinyBS** is a package that adds several additional Twitter Boostrap components to shiny. -You can install shinyBS from this repository by first installing `devtools`. At the R prompt type: +**shinyBS** is a package that adds several additional Twitter Boostrap +components to shiny. In January RStudio updated shiny to work with Bootstrap3 +which completely broke the original shinyBS. I have updated shinyBS to +work with the newest versions of shiny. -``` -install.packages("devtools") -``` - -After installing `devtools` in R you can install shinyBS by typing at the R prompt: - -``` -install_github("shinyBS", "ebailey78") -``` - -`shinyBS` was also added to CRAN. You can install the CRAN version with: +After several rounds of revisions, shinyBS v0.61 was accepted by CRAN on March 31st, 2015 and is available for install with `install.packages()` -``` +```R install.packages("shinyBS") ``` -For a quick demonstration of `shinyBS` functionality run the following code at the R prompt: - -``` -library(shinyBS) -bsDemo() -``` - -### What's New - -#### Version 0.25 (working version) - -* **bsNavDropDown** - * You can now create submenus inside a drop down by making a including lists inside your choices argument list. The submenus are built recursively so theoretically submenus can go as deep as you want - * You can create headers and dividers in your menus by include `NA`'s in you choices list, a named `NA` will become a header and an unnamed `NA` will become a divider. - * You can create dropdowns with media objects as their options. This is done with the `bsMedia()` function. - * I am working on a bsNavDemo() example that will better explain changes to dropdowns. -* **bsModal** - * You can now create modal windows with the `bsModal()` function. These are trigger from a button or link and can contain any combination of inputs, outputs, or standard html. -* **Table Highlighting** - * Per Request: highlightCells() now accepts a `column` argument which limits cell highlighting to that column. +Not all functionality that was in the previous versions was kept in this new version. Partly because of time constraints and partly because of some functionality being removed from Bootstrap. -#### Version 0.20 (released: 2014-03-19) +Features that remain in shinyBS 0.61 include: -* **pageWithNavBar** - * I forgot to include the pageWithNavbar function in the NAMESPACE file so it wasn't exported -* **Buttons/Button Groups** - * singletons for including shinyBS's javascript and CSS files weren't added when only button functions were included in an app - * added `block` argument for creating block level buttons and button groups - * added `vertical` argument for creating verically oriented button groups - -* **Tooltips/Popovers** - * Tooltips and Popovers will now work with the new selectize-type selectInput's in shiny 0.9.0 -* **Tables** - * `highlightCells` lets you highlight table cells based on their content - * `highlightRows` lets you highlight table rows based on the content of a table column +* Alerts +* Tooltips +* Popovers +* Modal Windows +* Collapse Panels +* Button upgrades -#### Version 0.10 (released: 2014-03-11) +Features that are not included in shinyBS 0.61 include: -* **Alerts** - Create alert anchors in your `ui.R` script and add alerts from `server.R` -* **Tooltips** - Add and configure tooltips on any element with an `inputId` or `outputId` with `bsTooltip()` from the ui or with `addToolTip()` from the server. -* **Popovers** - Works the same as Tooltips but useful for more content heavy applications. -* **TypeAhead** - Works just like a 'textInput' but you can provide custom autocomplete lists to guide the user to specific inputs. -* **Progress Bars** - Fully configurable Progress bars that can be updated and changed from `server.R`. -* **Navigation Bars** - Create Bootstrap style navigation bars with buttons, links, dropdowns, etc that control your shiny app. -* **Collapse Panels** - Create collapsable panels that allow you to remove some clutter from your app. -* **Buttons Groups** - Create button groups that behave like radio buttons or checkbox groups -* **Buttons** - Access Twitter Bootstrap styles and sizes for action buttons and toggle buttons +* Navbars and related components +* Typeaheads +* Progress Bars +* Button Groups +* Table Formatting +Now that this version has been been accepted by CRAN I will start working on updates and added functionality. If you have a request please open an issue and let me know. Thanks! diff --git a/inst/examples/Alerts/server.R b/inst/examples/Alerts/server.R new file mode 100644 index 0000000..b1eee03 --- /dev/null +++ b/inst/examples/Alerts/server.R @@ -0,0 +1,22 @@ +library(shiny) +library(shinyBS) +shinyServer( + function(input, output, session) { + output$exampleOutput <- renderText({ + num1 <- as.numeric(input$num1) + num2 <- as.numeric(input$num2) + + if(is.na(num1) | is.na(num2)) { + createAlert(session, "alert", "exampleAlert", title = "Oops", + content = "Both inputs should be numeric.", append = FALSE) + } else if(num2 == 0) { + createAlert(session, "alert", "exampleAlert", title = "Oops", + content = "You cannot divide by 0.", append = FALSE) + } else { + closeAlert(session, "exampleAlert") + return(num1/num2) + } + + }) + } +) diff --git a/inst/examples/Alerts/ui.R b/inst/examples/Alerts/ui.R new file mode 100644 index 0000000..6378a91 --- /dev/null +++ b/inst/examples/Alerts/ui.R @@ -0,0 +1,13 @@ +library(shiny) +library(shinyBS) + fluidPage( + sidebarLayout( + sidebarPanel(textInput("num1", NULL, value = 100), + "divided by", textInput("num2", NULL, value = 20), + "equals", textOutput("exampleOutput")), + mainPanel( + bsAlert("alert") + ) + ) +) + diff --git a/inst/examples/Buttons/server.R b/inst/examples/Buttons/server.R new file mode 100644 index 0000000..e0a21c1 --- /dev/null +++ b/inst/examples/Buttons/server.R @@ -0,0 +1,49 @@ +library(shiny) +library(shinyBS) +shinyServer( + function(input, output, session) { + observeEvent(input$togOne, ({ + updateButton(session, "actOne", disabled = !input$togOne) + })) + observeEvent(input$bins, ({ + + b <- input$bins + disabled = NULL + style = "default" + icon = "" + + if(b < 5) { + disabled = TRUE + icon <- icon("ban") + } else { + disabled = FALSE + } + + if(b < 15 | b > 35) { + style = "danger" + } else if(b < 20 | b > 30) { + style = "warning" + } else { + style = "default" + icon = icon("check") + } + + updateButton(session, "actTwo", disabled = disabled, style = style, icon = icon) + + })) + + output$exampleText <- renderText({ + input$actTwo + b <- isolate(input$bins) + txt = "" + if((b > 5 & b < 15) | b > 35) { + txt = "That was dangerous." + } else if((b > 5 & b < 20) | b > 30) { + txt = "I warned you about that." + } else if(b >= 20 & b <= 30) { + txt = "You have chosen... wisely." + } + return(txt) + }) + } +) diff --git a/inst/examples/Buttons/ui.R b/inst/examples/Buttons/ui.R new file mode 100644 index 0000000..7b37a05 --- /dev/null +++ b/inst/examples/Buttons/ui.R @@ -0,0 +1,23 @@ +library(shiny) +library(shinyBS) + fluidPage( + sidebarLayout( + sidebarPanel( + sliderInput("bins", + "Move the slider to see its effect on the button below:", + min = 1, + max = 50, + value = 1), + bsButton("actTwo", label = "Click me if you dare!", icon = icon("ban")), + tags$p("Clicking the first button below changes the disabled state of the second button."), + bsButton("togOne", label = "Toggle button disabled status", + block = TRUE, type = "toggle", value = TRUE), + bsButton("actOne", label = "Block Action Button", block = TRUE) + + ), + mainPanel( + textOutput("exampleText") + ) + ) +) + diff --git a/inst/examples/Collapses/server.R b/inst/examples/Collapses/server.R new file mode 100644 index 0000000..c2fac84 --- /dev/null +++ b/inst/examples/Collapses/server.R @@ -0,0 +1,13 @@ +library(shiny) +library(shinyBS) +shinyServer( + function(input, output, session) { + output$genericPlot <- renderPlot(plot(rnorm(100))) + observeEvent(input$p1Button, ({ + updateCollapse(session, "collapseExample", open = "Panel 1") + })) + observeEvent(input$styleSelect, ({ + updateCollapse(session, "collapseExample", style = list("Panel 1" = input$styleSelect)) + })) + } +) diff --git a/inst/examples/Collapses/ui.R b/inst/examples/Collapses/ui.R new file mode 100644 index 0000000..0dd53a7 --- /dev/null +++ b/inst/examples/Collapses/ui.R @@ -0,0 +1,21 @@ +library(shiny) +library(shinyBS) + fluidPage( + sidebarLayout( + sidebarPanel(HTML("This button will open Panel 1 using updateCollapse."), + actionButton("p1Button", "Push Me!"), + selectInput("styleSelect", "Select style for Panel 1", + c("default", "primary", "danger", "warning", "info", "success")) + ), + mainPanel( + bsCollapse(id = "collapseExample", open = "Panel 2", + bsCollapsePanel("Panel 1", "This is a panel with just text ", + "and has the default style. You can change the style in ", + "the sidebar.", style = "info"), + bsCollapsePanel("Panel 2", "This panel has a generic plot. ", + "and a 'success' style.", plotOutput("genericPlot"), style = "success") + ) + ) + ) +) + diff --git a/inst/examples/Modals/server.R b/inst/examples/Modals/server.R new file mode 100644 index 0000000..174fde5 --- /dev/null +++ b/inst/examples/Modals/server.R @@ -0,0 +1,33 @@ +library(shiny) +library(shinyBS) +shinyServer( + function(input, output, session) { + + output$distPlot <- renderPlot({ + + x <- faithful[, 2] + bins <- seq(min(x), max(x), length.out = input$bins + 1) + + # draw the histogram with the specified number of bins + hist(x, breaks = bins, col = 'darkgray', border = 'white') + + }) + + output$distTable <- renderDataTable({ + + x <- faithful[, 2] + bins <- seq(min(x), max(x), length.out = input$bins + 1) + + # draw the histogram with the specified number of bins + tab <- hist(x, breaks = bins, plot = FALSE) + tab$breaks <- sapply(seq(length(tab$breaks) - 1), function(i) { + paste0(signif(tab$breaks[i], 3), "-", signif(tab$breaks[i+1], 3)) + }) + tab <- as.data.frame(do.call(cbind, tab)) + colnames(tab) <- c("Bins", "Counts", "Density") + return(tab[, 1:3]) + + }, options = list(pageLength=10)) + + } +) diff --git a/inst/examples/Modals/ui.R b/inst/examples/Modals/ui.R new file mode 100644 index 0000000..bc0170a --- /dev/null +++ b/inst/examples/Modals/ui.R @@ -0,0 +1,21 @@ +library(shiny) +library(shinyBS) + fluidPage( + sidebarLayout( + sidebarPanel( + sliderInput("bins", + "Number of bins:", + min = 1, + max = 50, + value = 30), + actionButton("tabBut", "View Table") + ), + + mainPanel( + plotOutput("distPlot"), + bsModal("modalExample", "Data Table", "tabBut", size = "large", + dataTableOutput("distTable")) + ) + ) +) + diff --git a/inst/examples/TooltipsandPopovers/server.R b/inst/examples/TooltipsandPopovers/server.R new file mode 100644 index 0000000..d7de9e2 --- /dev/null +++ b/inst/examples/TooltipsandPopovers/server.R @@ -0,0 +1,33 @@ +library(shiny) +library(shinyBS) +shinyServer( + function(input, output, session) { + output$distPlot <- renderPlot({ + + # generate bins based on input$bins from ui.R + x <- faithful[, 2] + bins <- seq(min(x), max(x), length.out = input$bins + 1) + + # draw the histogram with the specified number of bins + hist(x, breaks = bins, col = 'darkgray', border = 'white') + + }) + output$dataTable <- renderDataTable({ + faithful + }) + output$uiExample <- renderUI({ + tags$span( + popify(bsButton("pointlessButton", "Button", style = "primary", size = "large"), + "A Pointless Button", + "This button is pointless. It does not do anything!"), + tipify(bsButton("pB2", "Button", style = "inverse", size = "extra-small"), + "This button is pointless too!") + ) + }) + addPopover(session, "distPlot", "Data", content = paste0("

Waiting time between ", + "eruptions and the duration of the eruption for the Old Faithful geyser ", + "in Yellowstone National Park, Wyoming, USA.

Azzalini, A. and ", + "Bowman, A. W. (1990). A look at some data on the Old Faithful geyser. ", + "Applied Statistics 39, 357-365.

"), trigger = 'click') + } +) diff --git a/inst/examples/TooltipsandPopovers/ui.R b/inst/examples/TooltipsandPopovers/ui.R new file mode 100644 index 0000000..99c2cbc --- /dev/null +++ b/inst/examples/TooltipsandPopovers/ui.R @@ -0,0 +1,24 @@ +library(shiny) +library(shinyBS) + fluidPage( + sidebarLayout( + sidebarPanel( + sliderInput("bins", + "Number of bins:", + min = 1, + max = 50, + value = 30), + selectInput("pointlessSelect", "Pointless Select", choices = c("A", "B", "C"), selectize = FALSE), + bsTooltip("pointlessSelect", "This is another pointless input element, its just here to look pretty."), + bsTooltip("bins", "The wait times will be broken into this many equally spaced bins", + "right", options = list(container = "body")) + ), + mainPanel( + plotOutput("distPlot"), + dataTableOutput("dataTable"), + uiOutput("uiExample"), + bsPopover("dataTable", "A popover", "This is a popover. I hope it works.", placement = "left") + ) + ) +) + diff --git a/inst/examples/demo/server.R b/inst/examples/demo/server.R deleted file mode 100644 index 0c1d9a0..0000000 --- a/inst/examples/demo/server.R +++ /dev/null @@ -1,491 +0,0 @@ -library(shiny) -library(shinyBS) - -pollutants <- c('Acetone', 'Acrolein', 'Benzene', 'Benzyl Chloride', 'Bromodichloromethane', 'Bromoform', 'Bromomethane', '1,3-Butadiene', 'Carbon Disulfide', 'Carbon Tetrachloride', 'Chlorobenzene', 'Chloroethane', 'Chloroform', 'Chloromethane', 'Cyclohexane', 'Dibromochloromethane', '1,2-Dibromoethane', 'm-Dichlorobenzene', 'p-Dichlorobenzene', 'o-Dichlorobenzene', 'Dichlorodifluoromethane (F-12)', '1,1-Dichloroethane', '1,2-Dichloroethane', 't-1,2-Dichloroethene', 'c-1,2-Dichloroethene', 'Dichloromethane', '1,2-Dichloropropane', 'c-1,3-Dichloropropene', 't-1,3-Dichloropropene', 'Dichloro-Tetrafluoroethane (F-114)', '1,4-Dioxane', 'Ethanol', 'Ethyl Acetate', 'Ethylbenzene', 'p-Ethyltoluene', 'Heptane', 'Hexachlorobutadiene', 'Hexane', 'Isopropanol', 'Methyl Ethyl Ketone (MEK)', 'Methyl Isobutyl Ketone (MIBK)', 'Methyl n-Butyl Ketone (MBK)', 'Methyl Tert-Butyl Ether (MTBE)', 'Propene', 'Styrene', '1,1,2,2-Tetrachloroethane', 'Tetrachloroethene (PCE)', 'Tetrahydrofuran (THF)', 'Toluene', 'Trichlorotrifluoroethane (F-113)', '1,2,4-Trichlorobenzene', '1,1,1-Trichloroethane', '1,1,2-Trichloroethane', 'Trichloroethene (TCE)', 'Trichlorofluoromethane (F-11)', '1,3,5-Trimethylbenzene', '1,2,4-Trimethylbenzene', 'Vinyl Acetate', 'Vinyl Chloride', 'Vinylidene Chloride', 'o-Xylene', 'm+p-Xylenes') -fruits <- c("Apple", "Banana", "Pear", "Peach", "Starfruit", "Orange", "Grapefruit", "Lemon", "Strawberry", "Blueberry", "Raspberry", "Persimmon", "Brocolli", "Cauliflower", "Green Beans", "Spinach", "Lettuce", "Asparagus", "Celery", "Olives", "Kale", "Arugula", "Artichokes", "Zuchinni", "Squash", "Watermellon", "Pumpkin", "Carrots", "Cucumber", "Grapes", "Onion", "Peas", "Shallots", "Tomato", "Tomatillo", "Yams") -animals <- c("Cat", "Dog", "Mouse", "Rat", "Opossum", "Raccoon", "Fox", "Deer", "Squirrel", "Chipmunk", "Black Bear", "Polar Bear", "Grizzly Bear", "Lion", "Tiger", "Monkey", "Gorilla", "Chimpanzee", "Bonobo", "Lemur", "Meerkat", "Pig", "Cow", "Horse", "Chicken", "Goose", "Duck", "Sparrow", "African Swallow", "European Swallow", "Dove", "Hawk", "Eagle", "Crow", "Albatross", "Gazelle", "Cougar", "Hippo", "Rhino", "Kangaroo", "Panda", "Koala", "Rattlesnake", "Snake", "Lizard", "Salamander", "Shark", "Whale", "Dolphin", "Seal", "Sealion", "Otter", "Badger", "Groundhog", "Manatee", "Walrus", "Bass", "Sunfish", "Guppy", "Trout", "Tuna", "Salmon", "Goldfish", "Stingray", "Jellyfish") - -baseUI <- function(main.code = "\tHello World!\n") { - - txt1 <- "library(shiny)\n" - txt1 <- paste0(txt1, "library(shinyBS)\n") - txt1 <- paste0(txt1, "\n") - txt1 <- paste0(txt1, "shinyUI(basicPage(\n") - - txt2 <- "))" - - as.character(tagList(tags$span(class = "extracode", txt1), - tags$span(class = "maincode", main.code), - tags$span(class = "extracode", txt2))) - -} - -baseServer <- function(main.code = "") { - - txt1 <- "library(shiny)\n" - txt1 <- paste0(txt1, "library(shinyBS)\n") - txt1 <- paste0(txt1, "\n") - txt1 <- paste0(txt1, "shinyServer(function(input, output, session) {\n") - - txt2 <- "})" - - as.character(tagList(tags$div(class = "extracode", txt1), - tags$div(class = "maincode", main.code), - tags$div(class = "extracode", txt2))) - -} - -shinyServer(function(input, output, session) { - -# Stop the app when button is clicked - observe({ - if(input$bsClose > 0) { - stopApp() - message("bsDemo() stopped. You can now close the browser window.") - } - }) - -###### CODE TO CONTROL NAVBAR DEMO ###### - - # Navbar UI Code Example - output$nbUICode <- renderText({ - baseUI( - -" bsNavBar(\"navBar\", brand = \"shinyBS\", - bsNavLink(\"nbLink1\", \"Link\", href=\"#\"), - bsNavDropDown(\"nbdd\", \"Dropdown\", c(\"Apple\", \"Pear\", \"Banana\", \"Grapes\", \"Orange\")), - bsNavDivider(), - bsNavToggleLink(\"nbLink2\", \"Toggle\", value=TRUE), - rightItems = list( - bsNavTextInput(\"nbText\", \"Text Input\", width=75), - bsNavButton(\"nbButton\", \"Button\") - ) - ) -" - ) - }) - - # Navbar Server Code Example - output$nbServerCode <- renderText({ - baseServer( -paste0(" observe({ - input$some_input # This causes the observer to take a dependency on input$some_input - - updateNavBar(session, \"navBar\", brand = \"", input$nbBrand, "\", fixed = ", input$nbFixed, ", inverse = ", input$nbInvert, ") - })") - ) - - }) - - # Navbar demo table generator - output$nbDemo <- renderTable({ - - tb <- rbind( - c("Link as ActionButton", input$nbLink1), - c("Dropdown", input$nbdd), - c("Toggle Link", input$nbLink2), - c("Button", input$nbButton), - c("Text Input", input$nbText)) - - colnames(tb) <- c("Input", "Value") - - return(tb) - - }, include.rownames=FALSE) - - # Changes example navbar based on changes in control panel - nbObserve <- observe({ - - updateNavBar(session, "navBar", brand = input$nbBrand, fixed = input$nbFixed, inverse = input$nbInvert) - - }) - -###### CODE TO CONTROL ALERT DEMO ###### - - # Alert UI Code Example - output$alUICode <- renderText({ - baseUI(paste0("\t", "bsAlert(inputId = \"alert_anchor\")", "\n")) - }) - - # Alert Server Code Example - output$alServerCode <- renderText({ - - txt <- "createAlert(session, inputId = \"alert_anchor\"," - if(input$alTitle) txt <- paste0(txt, "\n\t\ttitle = \"TITLE GOES HERE\",") - txt <- paste0(txt, "\n\t\tmessage = \"MESSAGE GOES HERE\",") - txt <- paste0(txt, "\n\t\ttype = \"", input$alType, "\",") - txt <- paste0(txt, "\n\t\tdismiss = ", input$alDis, ",\n\t\tblock = ", input$alBlock, ",\n\t\tappend = ", input$alAppend, "\n\t)") - - baseServer(paste0("\t", txt, "\n")) - - }) - - #Alert Creator - alCreate <- observe({ - - input$alCreate - - title <- isolate(input$alTitle) - dismiss <- isolate(input$alDis) - type <- isolate(input$alType) - block <- isolate(input$alBlock) - append <- isolate(input$alAppend) - - message <- includeHTML("http://www.gameofipsum.com/api/?type=html¶graphs=1&percent=0") - message <- as.vector(substr(message, 4, nchar(message) - 4)) - - if(title) { - tt <- switch(type, - "warning" = "Warning!", - "danger" = "Danger!", - "info" = "Just so you know...", - "success" = "Congratulations!") - } - - txt <- "createAlert(session, \"alert_anchor\"," - if(title) txt <- paste0(txt, " title = \"", tt, "\",") - txt <- paste0(txt, " message = \"", message, "\",") - txt <- paste0(txt, " type = \"", type, "\",") - txt <- paste0(txt, " dismiss = ", dismiss, ",") - txt <- paste0(txt, " block = ", block, ",") - txt <- paste0(txt, " append = ", append, ")") - - eval(parse(text=txt)) - - }) - -###### CODE TO CONTROL PROGRESS BAR DEMO ###### - - # Progress Bar UI Code Demo - output$pbUICode <- renderText({ - baseUI("\tbsProgressBar(\"pb1\", value = 50)\n") - }) - - # Progress Bar Server Code Demo - output$pbServerCode <- renderText({ - - if(input$pbradio == "none") { - striped=FALSE - animate=FALSE - } else if(input$pbradio == "striped") { - striped=TRUE - animate=FALSE - } else { - striped=TRUE - animate=TRUE - } - - txt <- paste0("updateProgressBar(session, inputId = \"pb1\", value = ", input$pbnumb, ", visible = ", !input$pbcb,", color = \"", input$pbselect, "\", striped = ", striped, ", animate = ", animate, ")") - eval(parse(text=txt)) - return(baseServer(paste("\t", txt))) - - }) - - -###### CODE TO CONTROL TYPEAHEAD DEMO ###### - - output$taUICode <- renderText({ - - txt <- "\t# This is the variable containing the source for the typeahead. It has been truncated to save space.\n" - txt <- paste0(txt, "\tpollutants = c('Acetone', 'Acrolein', 'Benzene', 'Benzyl Chloride', ...)\n") - txt <- paste0(txt, "\n") - txt <- paste0(txt, "\tbsTypeAhead(inputId = \"ta1\", label = \"TypeAhead:\", choices = pollutants)\n") - baseUI(txt) - - }) - - output$taServerCode <- renderText({ - - choice <- switch(input$taChoice, - "Pollutants" = "pollutants", - "Fruits and Vegetables" = "fruits", - "Animals" = "animals") - code <- paste0("updateTypeAhead(session, inputId = \"ta1\", label = \"", input$taLabel, "\", choices = ", choice, ")") - - txt <- "\t# These are additional variables containing sources for the typeahead. They have also been truncated to save space.\n" - txt <- paste0(txt, "\tpollutants = c('Acetone', 'Acrolein', 'Benzene', 'Benzyl Chloride', ...)\n") - txt <- paste0(txt, "\tfruits = c('Apple', 'Banana', 'Pear', 'Peach', 'Orange', 'Strawberre')\n") - txt <- paste0(txt, "\tanimals = c('Cat', 'Dog', 'Deer', 'Squirrel', 'Opossum', 'Fox', 'Sparrow')\n") - txt <- paste0(txt, "\n") - txt <- paste0(txt, code, "\n") - - eval(parse(text=code)) - - return(baseServer(txt)) - - }) - -###### CODE TO CONTROL TOOLTIPS AND POPOVERS DEMO ###### - - # Code to control Tooltips and Popovers example page mockup - randData <- reactive({ - - rfunc <- switch(input$tpdist, - "Normal" = rnorm, - "Lognormal" = rlnorm, - "Uniform" = runif, - "Exponential" = rexp) - - rfunc(input$tpobs) - - }) - - output$tpplot <- renderPlot({hist(randData(), main=input$tptitle)}) - - # Generates text for serverside tooltip and/or popover add. - tpText <- reactive({ - - target <- switch(input$tpTarget, - "link" = "tplink", - "slider" = "tpobs", - "select" = "tpdist", - "text" = "tptitle") - func <- switch(input$tpType, - "Tooltip" = "addTooltip", - "Popover" = "addPopover") - txt <- paste0(func, "(session, id = ", deparse(target), ", title = ", deparse(input$tpTitle)) - if(func == "addPopover") txt <- paste0(txt, ", content = ", deparse(input$tpContent)) - txt <- paste0(txt, ", placement = ", deparse(input$tpPlacement), ", trigger = ", deparse(input$tpTrigger), ")") - - return(txt) - - }) - - # Tooltips and Popovers Server Code Example - output$tpServerCode <- renderText({baseServer(paste0("\t", tpText()))}) - - # Tooltips and Popovers UI Code Example - output$tpUICode <- renderText({ - baseUI( - ' tags$p(HTML("This is some example text. It is here so that I can put a link in the example. ...")), - tags$div(class = "row-fluid", - tags$div(class = "span3 well control-panel", - sliderInput("tpobs", "Number of observations:", min = 1, max = 1000, value = 500), - selectInput("tpdist", "Distribution", choices = c("Normal", "Lognormal", "Uniform", "Exponential")), - textInput("tptitle", "Plot Title", "A Plot") - ), - tags$div(class = "span9", - plotOutput("tpplot") - ) - ), - bsTooltip("tpobs", "This changes the sample size of the random data set.", "right"), - bsTooltip("tpdist", "This allows changes to the distribution", "right"), - bsTooltip("tptitle", "Add a custom title to the plot", "right"), - bsPopover("tpplot", "Boxplot", "I really wanted to have a boxplot based on the same dataset as the histogram appear ...", trigger="click", placement="right")' -) - }) - - # Observer to add tooltips/popovers when the "Add" Button is clicked. - tpObs <- observe({ - if(input$tpAdd > 0) { - eval(parse(text = isolate(tpText()))) - } - }) - -###### CODE TO CONTROL COLLAPSE DEMO ###### - - output$coUICode <- renderText({ - - ft <- '\tbsCollapse(multiple = TRUE, open = "col1", id = "collapse1",\n' - ft <- paste0(ft, '\t\tbsCollapsePanel("Collapse #1", "Cell treachery spearwife night\'s watch, tower suckling ...", id="col1", value="test1"),\n') - ft <- paste0(ft, '\t\tbsCollapsePanel("Collapse #2", actionButton("btn123", "A Button"), textInput("txt1234", "A Text Input"), id="col2", value="test2"),\n') - ft <- paste0(ft, '\t\tbsCollapsePanel("Collapse #3", plotOutput("testPlot1"), id="col3", value="test3")\n') - ft <- paste0(ft, '\t)\n') - - return(baseUI(ft)) - - }) - - coObs <- observe({ - if(input$coUpdate > 0) { - updateCollapse(session, "collapse1", multiple = isolate(input$coMult), open = isolate(input$coOpen), close = isolate(input$coClose)) - } - }) - - output$coServerCode <- renderText({ - baseServer(paste0("updateCollapse(session, id = \"collapse1\", multiple = ", deparse(input$coMult), ", open = ", deparse(input$coOpen), ", close = ", deparse(input$coClose), ")")) - }) - - output$coValue <- renderText({paste("input$collapse1 = ", deparse(input$collapse1))}) - - output$testPlot1 <- renderPlot({plot(rnorm(1000))}) - - -###### CODE TO CONTROL BUTTON GROUPS DEMO ##### - - output$bgValue <- renderTable({ - - df <- cbind(c("bsActionButton", "bsToggleButton", "bsButtonGroup"), c(deparse(input$ab1), deparse(input$tb1), deparse(input$btngrp1))) - colnames(df) <- c("Input", "Value") - return(df) - - }, include.rownames=FALSE) - - output$bgServerCode <- renderText({ - bg <- input$bgValue - if(is.null(input$bgValue)) bg <- "none" - - baseServer(paste0(" updateButton(session, \"ab1\", style = ", deparse(input$bgStyle), ", size = ", deparse(input$bgSize), ", disabled = ", deparse(input$bgDisabled), ") - updateButton(session, \"tb1\", style = ", deparse(input$bgStyle), ", size = ", deparse(input$bgSize), ", disabled = ", deparse(input$bgDisabled), ") - updateButtonGroup(session, \"btngrp1\", toggle = ", deparse(input$bgToggle), ", style = ", deparse(input$bgStyle), ", size = ", deparse(input$bgSize), ", disabled = ", deparse(input$bgDisabled), ", value = ", deparse(bg), ") - -")) - }) - - output$bgUICode <- renderText({ - baseUI("bsActionButton(\"ab1\", label = \"bsActionButton\"), - bsToggleButton(\"tb1\", label = \"bsToggleButton\"), - tags$p(), - bsButtonGroup(\"btngrp1\", label = \"bsButtonGroup\", toggle = \"radio\", value = \"right\", - bsButton(\"btn1\", label = \"Left\", value = \"left\"), - bsButton(\"btn2\", label = \"Middle\", value = \"middle\"), - bsButton(\"btn3\", label = \"Right\", value = \"right\")) -") - }) - - observe({ - bg <- input$bgValue - if(is.null(input$bgValue)) bg <- "none" - updateButton(session, "ab1", style = input$bgStyle, size = input$bgSize, disabled = input$bgDisabled) - updateButton(session, "tb1", style = input$bgStyle, size = input$bgSize, disabled = input$bgDisabled) - updateButtonGroup(session, "btngrp1", toggle = input$bgToggle, style = input$bgStyle, size = input$bgSize, disabled = input$bgDisabled, value = bg) - }) - -###### CODE TO CONTROL TABLES DEMO ##### - - output$htTable <- renderTable({ - - d <- as.integer(runif(84, 0, 20)) - - d[runif(10, 1, 84)] <- NA - - df <- as.data.frame(matrix(d, nrow = 7, ncol = 12)) - - colnames(df) <- month.abb - rownames(df) <- c("Troy", "Abed", "Britta", "Jeff", "Annie", "Pierce", "Shirley") - - return(df) - - }) - - output$htUICode <- renderText({baseUI("\ttags$p(style = \"font-weight: bold; text-align: center;\", \"2013 Sales Figures\")\n\ttableOutput('htTable')\n")}) - - output$htServerCode <- renderText({ - - min <- paste(", min =", input$htMin) - max <- paste(", max =", input$htMax) - reset <- paste(", reset =", input$htReset) - style <- paste(", style =", deparse(input$htStyle)) - regex <- paste(", regex =", deparse(input$htText)) - class <- paste(", class =", deparse(input$htClass)) - - if(input$htMin == "") min = "" - if(input$htMax == "") max = "" - if(input$htReset == FALSE) reset = "" - if(input$htStyle == "") style = "" - if(input$htText == "") regex = "" - if(input$htClass == "none") class = "" - - op <- paste0("\thighlightCells(session, 'htTable'", class, style, min, max, regex, reset, ")") - op <- paste0(op, "\n\thighlightRows(session, 'htTable', column = ", deparse(input$htCol), class, style, min, max, regex, ")") - - return(baseServer(op)) - - }) - - observe({ - - if(input$htAdd > 0) { - - class = isolate(input$htClass) - min <- isolate(input$htMin) - max <- isolate(input$htMax) - style <- isolate(input$htStyle) - regex <- isolate(input$htText) - column <- isolate(input$htCol) - - if(class == "none") class <- NULL - if(min == "") min <- NULL - if(max == "") max <- NULL - if(style == "") style <- NULL - if(regex == "") regex <- NULL - if(column == "") column <- NULL - - highlightCells(session, "htTable", min = min, max = max, column = column, - class = class, style = style, regex = regex, reset = isolate(input$htReset)) - - } - - }) - - observe({ - - if(input$htRow > 0) { - - class = isolate(input$htClass) - min <- isolate(input$htMin) - max <- isolate(input$htMax) - style <- isolate(input$htStyle) - regex <- isolate(input$htText) - column <- isolate(input$htCol) - - if(class == "none") class <- NULL - if(min == "") min <- NULL - if(max == "") max <- NULL - if(style == "") style <- NULL - if(regex == "") regex <- NULL - - highlightRows(session, "htTable", column = column, min = min, max = max, - class = class, style = style, regex = regex, reset = isolate(input$htReset)) - - } - - }) - -###### CODE TO CONTROL MODAL DEMO ##### - -morandData <- reactive({ - - rfunc <- switch(input$modist, - "Normal" = rnorm, - "Lognormal" = rlnorm, - "Uniform" = runif, - "Exponential" = rexp) - - rfunc(input$moobs) - -}) - -observe({ - if(input$moTog1 > 0) { - toggleModal(session, "moMod") - } -}) - -output$moplot <- renderPlot({hist(morandData(), main=input$motitle)}) - -output$moValue <- renderText({paste0("input$moMod = ", input$moMod, "\ninput$moMod2 = ", input$moMod2)}) - -output$moUICode <- renderText({baseUI('\tbsButton("moTrig", "Open Modal", style = "primary"), - bsButton("moTrig2", "Open Remote Modal", style = "primary"), - bsModal("moMod", "Example Modal", trigger = "moTrig", - tags$p(HTML("Modals can contain anything:")), - tags$div(class = "row-fluid", - tags$div(class = "span4 well control-panel", - sliderInput("moobs", "Number of observations:", min = 1, max = 1000, value = 500), - selectInput("modist", "Distribution", choices = c("Normal", "Lognormal", "Uniform", "Exponential")), - textInput("motitle", "Plot Title", "A Modal Plot") - ), - tags$div(class = "span8", - plotOutput("moplot") - ) - ) - ), - bsModal("moMod2", "A Remote Modal", trigger = "moTrig2", href = "moDemo.html") -')}) - -output$moServerCode <- renderText({baseServer("\ttoggleModal(session, \"moMod\")")}) - -}) - - diff --git a/inst/examples/demo/ui.R b/inst/examples/demo/ui.R deleted file mode 100644 index d23610c..0000000 --- a/inst/examples/demo/ui.R +++ /dev/null @@ -1,242 +0,0 @@ -library(shiny) -library(shinyBS) - -###### Creates a standardized "Demo" panel for the bsDemo() app. ##### -demoPanel <- function(title, intro, controls, example, uiCode, serverCode) { - tabPanel(title, - tags$div(class = "row-fluid", - tags$div(class = "span7", - tags$div(class = "row-fluid", - tags$div(class = "span12", - tags$div(class = "intro", - tags$h4(title), - tags$p(HTML(intro)), - tags$hr() - ) - ) - ), - tags$div(class = "row-fluid", - tags$div(class = "span3", - tags$div(class="section-label", "Control Panel"), - tags$div(class = "well control-panel", - tags$small("Use the controls below to manipulate the example to the right. Code to the far right will also update."), - controls - ) - ), - tags$div(class = "span9", - tags$div(class = "section-label", "Example"), - tags$div(class = "example-box", - example - ) - ) - ) - ), - tags$div(class = "span5", - tags$div(class = "section-label", "ui.R"), - tags$div(class = "scriptblock", - htmlOutput(uiCode) - ), - tags$div(class = "section-label", "server.R"), - tags$div(class = "scriptblock", - htmlOutput(serverCode) - ) - ) - ) - ) -} - -pollutants <- c('Acetone', 'Acrolein', 'Benzene', 'Benzyl Chloride', 'Bromodichloromethane', 'Bromoform', 'Bromomethane', '1,3-Butadiene', 'Carbon Disulfide', 'Carbon Tetrachloride', 'Chlorobenzene', 'Chloroethane', 'Chloroform', 'Chloromethane', 'Cyclohexane', 'Dibromochloromethane', '1,2-Dibromoethane', 'm-Dichlorobenzene', 'p-Dichlorobenzene', 'o-Dichlorobenzene', 'Dichlorodifluoromethane (F-12)', '1,1-Dichloroethane', '1,2-Dichloroethane', 't-1,2-Dichloroethene', 'c-1,2-Dichloroethene', 'Dichloromethane', '1,2-Dichloropropane', 'c-1,3-Dichloropropene', 't-1,3-Dichloropropene', 'Dichloro-Tetrafluoroethane (F-114)', '1,4-Dioxane', 'Ethanol', 'Ethyl Acetate', 'Ethylbenzene', 'p-Ethyltoluene', 'Heptane', 'Hexachlorobutadiene', 'Hexane', 'Isopropanol', 'Methyl Ethyl Ketone (MEK)', 'Methyl Isobutyl Ketone (MIBK)', 'Methyl n-Butyl Ketone (MBK)', 'Methyl Tert-Butyl Ether (MTBE)', 'Propene', 'Styrene', '1,1,2,2-Tetrachloroethane', 'Tetrachloroethene (PCE)', 'Tetrahydrofuran (THF)', 'Toluene', 'Trichlorotrifluoroethane (F-113)', '1,2,4-Trichlorobenzene', '1,1,1-Trichloroethane', '1,1,2-Trichloroethane', 'Trichloroethene (TCE)', 'Trichlorofluoromethane (F-11)', '1,3,5-Trimethylbenzene', '1,2,4-Trimethylbenzene', 'Vinyl Acetate', 'Vinyl Chloride', 'Vinylidene Chloride', 'o-Xylene', 'm+p-Xylenes') - -##### Shiny UI ##### -shinyUI(basicPage(tags$head(tags$title("shinyBS Demo Page"), - tags$link(type = "text/css", rel = "stylesheet", href="demo.css"), - tags$script(src = "demo.js") - ), - tags$div(class="pull-right", style="padding-top: 5px;", bsActionButton("bsClose", label = "Stop Demo", style = "primary")), - tabsetPanel(id = "tabset", selected = "Introduction", - tabPanel("Introduction", tags$div(class = "row-fluid", tags$div(class = "span12", tags$h3("shinyBS Demo"))), - tags$div(class = "row-fluid", tags$div(class = "span6", - tags$p(HTML("shinyBS is an R package that makes much of the functionality inherent to Twitter Boostrap available to shiny programmers without the need to make custom html user interfaces. It began as a project to help me better understand how shiny works but I hope it will be useful to others.

I've created bsDemo() to hopefully help reduce the learning curve for using shinyBS by allowing you to interact with new components directly within a shiny application rather than having to have to rely soley on the help files in R. Each added component is represented by a tab above. Clicking a tab will display a demonstration panel for the component. Each panel is laid out like the example on the right. A brief explanation of a panel follows:")), - tags$ul(tags$li("The upper-left section of the panel contains brief explanatory text for the component."), - tags$li("The upper-right section contains a minimal example of how the component could be implemented in a ui.R script."), - tags$li("The lower-right section contains a minimal example of how the component could be implemented or updated from a server.R script."), - tags$li("The lower-middle section contains an interactive example of the component."), - tags$li("The lower-left section contains a control panel that allows you to see how changes to the arguments of the component affect the appearance and/or behavior in the example component. The code contained in the ui.R and server.R scripts will also update to reflect the changes you make in the control panel.") - ), - tags$p(HTML("Please use the tabs above to explore shinyBS functionality. I have made great efforts to make sure that the code all works under multiple use scenarios but if you find a bug, or if you have suggestions for additional functionality, please contact me at ebailey@idem.in.gov.")) - - ), - tags$div(class = "span6", tags$img(src="expic.png")))), -##### Navbar Demo ##### - demoPanel(title = "Navbars", - intro = paste0("

Navbars offer a space-efficient way to group your inputs together in your shiny app. Most of the customizations in Twitter Bootstrap are available as arguments in the bsNavBar() function. Any element you add to the navbar will align to the left, unless you add them to the rightItems argument, which will cause them to align to the right.

", - "

Several of shiny's default inputs have been reformatted to look better in the navbar. For example, textInput has had its label changed to a placeholder and has an added 'width' attribute to help save room. New versions of inputs have had bsNav prepended to their names.

", - "

Refer to the help files for shinyBS for additional information about navBar inputs.

" - ), - controls = tagList(textInput("nbBrand", "Brand", "navbar"), - checkboxInput("nbInvert", "Inverse", FALSE), - checkboxInput("nbFixed", "Fixed to Top", FALSE), - tags$hr(), - tags$h5("Current Navbar Element Values"), - tableOutput("nbDemo") - ), - example = tags$div(style="height: 800px;", bsNavBar("navBar", "shinyBS", - bsNavLink("nbLink1", "Link", href="#"), - bsNavDropDown("nbdd", "Dropdown", c("Apple", "Pear", "Banana", "Grapes", "Orange")), - bsNavDivider(), - bsNavToggleLink("nbLink2", "Toggle", value=TRUE), - rightItems = list( - bsNavTextInput("nbText", "Text Input", width = 75), - bsNavButton("nbButton", "Button") - ) - )), - uiCode = "nbUICode", - serverCode = "nbServerCode" - ), -##### Alerts Demo ##### - demoPanel(title = "Alerts", - intro = "

Alerts allow you to communicate information to the user on the fly. Begin by creating an alert anchor with the bsAlert() function in the iu.R script. You can then add alerts to this anchor with createAlert() and remove them with closeAlert().

By default, new alerts are placed below any alerts already present in the alert anchor but if you set append = FALSE in createAlert() the new alert will overwrite any existing alerts.

Also by default, alerts will be dismissable by the user with a small × in the upper-right corner of the alert. You can override this behavior by setting dismiss = FALSE in createAlert(). The alert can then only be removed using closeAlert() (be sure to set alertId when you create the alert) or by creating a new alert with append = FALSE in the same anchor.

", - controls = tagList(selectInput("alType", "Type", c("warning", "info", "danger", "success")), - checkboxInput("alTitle", "Title", FALSE), - checkboxInput("alDis", "Dismissible", TRUE), - checkboxInput("alBlock", "Block", FALSE), - checkboxInput("alAppend", "Append", TRUE), - actionButton("alCreate", "Create Alert") - ), - example = tagList(bsAlert("alert_anchor"), - tags$p(HTML("Alert box text generated by Game of Ipsum."))), - uiCode = "alUICode", - serverCode = "alServerCode" - ), -##### Progress Bars Demo ##### - demoPanel(title = "Progress Bars", - intro = "

Progress bars are created with the bsProgressBar() function in ui.R and then modified with updateProgressBar() in server.R.

If you don't want the progress bar to be present all the time you should still create it in your ui.R script but set visible = FALSE. You can then use updateProgressBar() to make it visible when you want it.

The easiest use for them would be in some sort of loop where you can add an updateProgressBar() to the code in the loop to reflect how much of the loop has completed.

The color argument corresponds to the same predefined classes that alerts have, with the addition of a darker blue 'standard' option.

", - controls = tagList(sliderInput("pbnumb", "Percent Complete", 50, min=0, max=100), - selectInput("pbselect", "Color", c("standard", "warning", "info", "danger", "success")), - radioButtons("pbradio", "Style", c("none", "striped", "animated")), - checkboxInput("pbcb", "Hidden", FALSE)), - example = bsProgressBar("pb1", 50), - uiCode = "pbUICode", - serverCode = "pbServerCode" - ), -##### TypeAhead Demo ##### - demoPanel(title = "TypeAheads", - intro = "

TypeAhead boxes are special versions of textboxes that help lead the user to acceptable inputs. They are created with the bsTypeAhead() function and can be updated with updateTypeAhead(). You can set the minimum match length and number of items to display at creation, but these properties cannot be changed by updateTypeAhead().

The example below allows you to choose between three predefined vectors for the choice arugment but any reality any vector or list can be used.

", - controls = tagList(textInput("taLabel", "Label", "TypeAhead:"), - selectInput("taChoice", "Choices", c("Pollutants", "Fruits and Vegetables", "Animals")) - ), - example = bsTypeAhead("ta1", label = "TypeAhead:", choices = pollutants), - uiCode = "taUICode", - serverCode = "taServerCode" - ), -##### Tooltips and Popovers Demo ##### - demoPanel(title = "Tooltips and Popovers", - intro = "

Tooltips and popovers are added in very similar ways. Tooltips/Popovers can be added to any element with an inputId or an outputId by using bsTooltip() in ui.R, or addTooltip() in server.R. Similarly, you can remove tooltips and popovers from an object by using removeTooltip() and removePopover(), respectively.

Tooltips would generally be used to provide brief additional information about an input or output element. Popovers can contain much more detailed information but currently cannot contain shiny inputs or outputs. I hope to figure out how to incorporate them in a future release.

Some tooltips and popovers have already been added to the example below. These are used to illustrate how they can be added in the ui.R script. You can add your own tooltips and popovers from the control panel. The code for these will be shown in the server.R script.", - controls = tagList(selectInput("tpTarget", "Target", c("link", "slider", "select", "text", "plot")), - radioButtons("tpType", "Type", choices = c("Tooltip", "Popover"), selected= "Tooltip"), - textInput("tpTitle", "Title", "A tooltip"), - conditionalPanel("input.tpType == 'Popover'", textInput("tpContent", "Content", "This is content. Isn't it great!")), - selectInput("tpPlacement", "Placement", c("top", "bottom", "left", "right")), - radioButtons("tpTrigger", "Triggers", choices = c("click", "hover", "focus", "manual"), selected="hover"), - actionButton("tpAdd", "Add")), - example = tagList(tags$p(HTML("This is some example text. It is here so that I can put a link in the example. I've given the link an id attribute so that tooltips and popovers can be assigned to it. Otherwise this example is an expansion of the '01_Hello' example that is part of shiny. ")), - tags$div(class = "row-fluid", - tags$div(class = "span3 well control-panel", - sliderInput("tpobs", "Number of observations:", min = 1, max = 1000, value = 500), - selectInput("tpdist", "Distribution", choices = c("Normal", "Lognormal", "Uniform", "Exponential")), - textInput("tptitle", "Plot Title", "A Plot") - ), - tags$div(class = "span9", - plotOutput("tpplot") - ) - ), - bsTooltip("tpobs", "This changes the sample size of the random data set.", "right"), - bsTooltip("tpdist", "This allows changes to the distribution", "right"), - bsTooltip("tptitle", "Add a custom title to the plot", "right"), - bsTooltip("tpplot", "Click plot to show popover", "top"), - bsPopover("tpplot", "Boxplot", "I really wanted to have a boxplot based on the same dataset as the histogram appear in this box. Unfortunately, it appears that popovers are written when they are shown and destroyed when they are hidden so there is nothing persistent for shiny to bind to. So instead of a plot you get this text...", trigger="click", placement="right") - ), - uiCode = "tpUICode", - serverCode = "tpServerCode" - ), -##### Collapse Demo ##### - demoPanel(title = "Collapse Panels", - intro = "

Collapses (sometimes called accordions) are an alternative way to segment information and free up space in your shiny app. They have been designed to work in a very similar way to tabsetPanel() and tabPanel(). Create a collapse group with bsCollapse() and include any number of panels in it with bsCollapsePanel().

Similar to tabsetPanel(), bsCollapse() will return the value of the panel that is currently open. If multiple = TRUE then it will return an array of all open panel values.

You can use updateCollapse() to open and close panels or turn multiple on and off from server.R.

In some cases, collapse panels did not render properly when testing in Internet Explorer 10.

", - controls = tagList(checkboxInput("coMult", "Multiple"), - checkboxGroupInput("coOpen", "Open", c("Collapse #1" = "col1", "Collapse #2" = "col2", "Collapse #3" = "col3")), - checkboxGroupInput("coClose", "Close", c("Collapse #1" = "col1", "Collapse #2" = "col2", "Collapse #3" = "col3")), - actionButton("coUpdate", "Update"), - tags$h5("Output"), - textOutput("coValue")), - example = bsCollapse(multiple = FALSE, open = c("col1"), id = "collapse1", - bsCollapsePanel("Collapse #1", "Cell treachery spearwife night's watch, tower suckling pig, drink, your king commands it spare me your false courtesy tourney. Feed it to the goats, seven hells lord of light as high as honor in his cups. Sword greyscale old bear none so wise godswood the last of the dragons rouse me not. No foe may pass bloody mummers, let me soar spiced wine your grace honed and ready fire.", id="col1", value = "test1"), - bsCollapsePanel("Collapse #2", actionButton("btn123", "A Button"), textInput("txt1234", "A Text Input"), id="col2", value = "test2"), - bsCollapsePanel("Collapse #3", plotOutput("testPlot1"), id="col3", value = "test3")), - uiCode = "coUICode", - serverCode = "coServerCode" - ), -##### Buttons Demo ##### - demoPanel(title = "Buttons", - intro = "

actionButtons are already a part of shiny but by using bsActionButton() you can create action buttons that can be sized and styled using Twitter Bootstrap's default styles (primary, info, success, warning, danger, inverse, and link) and sizes (large, small, and mini). You can also disable and enable the action button using the disabled argument at creation or in updateButton().

There is also a bsToggleButton() function that allows the creation of a button that can be toggled on/off; returning TRUE/FALSE depending on its current state. Toggle buttons can be styled the same as the action buttons previously mentioned.

Button Groups offer functionality similar to radioButtons() or checkBoxGroupInput(), depending on the value of the toggle argument. Create a button group by starting with bsButtonGroup() and adding bsButton() objects to it. Similar to how tabs are added in tabsetPanel(). Buttons in a button group can be individually styled, or if the style, size, or disabled argument is supplied to bsButtonGroup() these values will be applied to all buttons in the group.

", - controls = tagList(radioButtons("bgToggle", "toggle", choices = c("radio", "checkbox"), selected = "radio"), - selectInput("bgSize", "Size", choices = c("large", "default", "small", "mini"), selected = "default"), - selectInput("bgStyle", "Style", choices = c("default", "primary", "info", "success", "warning", "danger", "inverse", "link"), selected = "default"), - checkboxInput("bgDisabled", "Disabled"), - checkboxGroupInput("bgValue", "Value", choices = c("left", "middle", "right"), selected = "right"), - tags$p(HTML("Input Values")), - tableOutput("bgValue")), - example = tagList(bsActionButton("ab1", label = "bsActionButton"), - bsToggleButton("tb1", label = "bsToggleButton"), - tags$p(), - bsButtonGroup("btngrp1", label = "bsButtonGroup", toggle = "radio", value = "right", - bsButton("btn1", label = "Left", value = "left"), - bsButton("btn2", label = "Middle", value = "middle"), - bsButton("btn3", label = "Right", value = "right")) - ), - uiCode = "bgUICode", - serverCode = "bgServerCode"), -##### Table Highlighting Demo ##### - demoPanel(title = "Tables", - intro = "

These functions are experimental and may change significantly. The idea is to be able to highlight cells or rows based on their contents. You can match cells based on a numeric range with the min and max arguments or use the regex argument to use regular expresssions for cell matching.

highlightCells() is used for highlighting individual cells and highlightRows() is used for highlighting entire rows. Both functions use the same arguments with highlightRows() having an additional column argument for indicating the column to search. You can supply the column argument with the value that appears in the top row or with a numeric index value for the column. highlightCells() also has a skip.row.names argument for skipping the first column in a table.

Cells can be styled with the class or style arguments. class can be one of eight predefined classes (success, warning, error, info, good, bad, neutral, disabled) or any class you have defined. If you use the style argument its contents will be directly inserted into the style attribute of matching td and tr elements.

", - controls = tagList(selectInput("htClass", "Class", choices = c("none", "success", "warning", "error", "info", "good", "bad", "neutral")), - textInput("htStyle", "Style"), - textInput("htCol", "Column"), - textInput("htMin", "Min"), - textInput("htMax", "Max"), - textInput("htText", "Text"), - checkboxInput("htReset", "Reset Highlighting"), - bsActionButton("htAdd", "highlightCells()", block = TRUE), - bsActionButton("htRow", "highlightRows()", block = TRUE)), - example = tagList(tags$p(style = "font-weight: bold; text-align: center;", "2013 Sales Figures"), - tableOutput("htTable")), - uiCode = "htUICode", - serverCode = "htServerCode"), -##### Modal Demo ##### - demoPanel(title = "Modals", - intro = "

Modals are popup windows that can contain any html objects you want. You can either build the content of the modal window with R code or you can set the href argument to the location of a html file and have the html file loaded into the body of the modal.

Modals need to be linked to a button or anchor in the app. You create this link by setting the trigger argument in bsModal() to the id of the button or anchor you want to open the modal.

Modals are shiny inputs that return TRUE or FALSE based on whether they are currently visible.

You can open and/or close a modal from server.R by using the toggleModal() function.

", - controls = tagList(actionButton("moTog1", "Toggle Modal"), tags$p(), - textOutput("moValue")), - example = tagList(bsButton("moTrig", "Open Modal", style = "primary"), - bsButton("moTrig2", "Open Remote Modal", style = "primary"), - bsModal("moMod", "Example Modal", trigger = "moTrig", - tags$p(HTML("Modals can contain anything:")), - tags$div(class = "row-fluid", - tags$div(class = "span4 well control-panel", - sliderInput("moobs", "Number of observations:", min = 1, max = 1000, value = 500), - selectInput("modist", "Distribution", choices = c("Normal", "Lognormal", "Uniform", "Exponential")), - textInput("motitle", "Plot Title", "A Modal Plot") - ), - tags$div(class = "span8", - plotOutput("moplot") - ) - ) - ), - bsModal("moMod2", "A Remote Modal", trigger = "moTrig2", href = "moDemo.html") - - ), - uiCode = "moUICode", - serverCode = "moServerCode" - ) - ) - -)) \ No newline at end of file diff --git a/inst/examples/demo/www/demo.css b/inst/examples/demo/www/demo.css deleted file mode 100644 index 90d3337..0000000 --- a/inst/examples/demo/www/demo.css +++ /dev/null @@ -1,83 +0,0 @@ -.scriptblock > div{ - - font-family: monospace; - display: block; - padding: 8.5px; - margin: 0px 0px 9px; - font-size: 1em; - line-height: 1.2em; - word-break: keep-all; - word-wrap: break-word; - white-space: pre-wrap; - background-color: rgb(245, 245, 245); - border: 1px solid rgba(0, 0, 0, 0.15); - border-radius: 4px 4px 4px 4px; - -moz-tab-size: 2; - -o-tab-size: 2; - tab-size: 2; - height: 100%; - -} - -code { - font-family: monospace; - background-color: rgb(245, 245, 245); - border: 1px solid rgba(0, 0, 0, 0.15); - color: rgba(0, 0, 0, 0.65); - -} - -.example-box { - min-height: 20px; - padding: 19px; - margin-bottom: 20px; - background-color: none; - border: 1px solid #E3E3E3; - border-radius: 4px; - box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.05) inset; -} - -.control-panel > small { - display: block; - font-size: 75%; - line-height: 13px; - text-align: justify; - margin-bottom: 13px; -} - -.section-label { - padding-left: 7px; - padding-bottom: 3px; - font-weight: bold; -} - -.control-panel > input, .control-panel > select, .control-panel > div > input, .control-panel > div > select { - width: 95% -} - -.intro { - - text-align: justify; - -} - -.extracode { - - color : rgb(150, 150, 150); - -} - -.maincode { - - color: rgb(25, 25, 25); - font-weight: bold; - -} - -#htTable > table { - width: 100%; -} - -#htTable > table th { - text-align: center; -} \ No newline at end of file diff --git a/inst/examples/demo/www/demo.js b/inst/examples/demo/www/demo.js deleted file mode 100644 index e69de29..0000000 diff --git a/inst/examples/demo/www/expic.png b/inst/examples/demo/www/expic.png deleted file mode 100644 index 8fc5930..0000000 Binary files a/inst/examples/demo/www/expic.png and /dev/null differ diff --git a/inst/examples/demo/www/moDemo.html b/inst/examples/demo/www/moDemo.html deleted file mode 100644 index 652446c..0000000 --- a/inst/examples/demo/www/moDemo.html +++ /dev/null @@ -1,9 +0,0 @@ - - - - -

This text comes from an html file in the www directory of the bsDemo app directory. By setting the href argument in bsModal() to this file's name, it was loaded into the body of the modal window. You could achieve a similar effect by using shiny's includeHTML() function.

- - - - \ No newline at end of file diff --git a/inst/examples/navbar/server.R b/inst/examples/navbar/server.R deleted file mode 100644 index 31434fb..0000000 --- a/inst/examples/navbar/server.R +++ /dev/null @@ -1,35 +0,0 @@ -library(shiny) -library(shinyBS) - -ch <- list("Font Color" = list("White" = "txt:white", "Black" = "txt:black", "Red" = "txt:red", "Blue" = "txt:blue", "Green" = "txt:green", "Yellow" = "txt:yellow", "Orange" = "txt:orange", "Purple" = "txt:purple"), - "Background Color" = list("White" = "bg:white", "Black" = "bg:black", "Red" = "bg:red", "Blue" = "bg:blue", "Green" = "bg:green", "Yellow" = "bg:yellow", "Orange" = "bg:orange", "Purple" = "bg:purple")) - - -shinyServer(function(input, output, session) { - - output$test <- renderText({ - - input$ndd1 - - }) - - observe({ - - cmd <- unlist(strsplit(input$ndd1, ":")) - if(length(cmd) > 0) { - session$sendCustomMessage("options", list(option = cmd[1], value = cmd[2])) - } - - }) - - observe({ - - if(input$test > 0) { - - updateDropDown(session, "ndd1", choices = ch) - - } - - }) - -}) \ No newline at end of file diff --git a/inst/examples/navbar/ui.R b/inst/examples/navbar/ui.R deleted file mode 100644 index a1c8308..0000000 --- a/inst/examples/navbar/ui.R +++ /dev/null @@ -1,22 +0,0 @@ -library(shiny) -library(shinyBS) - -options <- list("Font Size" = list("8pt" = "txtsz:8", "10pt" = "txtsz:10", "12pt" = "txtsz:12", "14pt" = "txtsz:14", "16pt" = "txtsz:16", "18pt" = "txtsz:18"), - "Font Color" = list("White" = "txt:white", "Black" = "txt:black", "Red" = "txt:red", "Blue" = "txt:blue", "Green" = "txt:green", "Yellow" = "txt:yellow", "Orange" = "txt:orange", "Purple" = "txt:purple"), - "Background Color" = list("White" = "bg:white", "Red" = "bg:red", "Blue" = "bg:blue", "Green" = "bg:green", "Yellow" = "bg:yellow", "Orange" = "bg:orange", "Purple" = "bg:purple")) -media <- list(GI = bsMedia("GI", "Gary IITRI", "Gary IITRI has been an active monitor since 1998. Besides air toxics, Gary IITRI also monitors meteorology paramaters and criteria pollutants. Gary IITRI is also an unofficial PAMS monitor so it has hourly data for may air toxics.", "holder.js/100x100"), - NE = bsMedia("NE", "Falls of the Ohio", "The Falls of the Ohio air toxics monitor is one of the newer monitors in the ToxWatch network, only active since 2008. It is located on the roof of the State Park visitors center and collects only 1-in-6 day toxics samples.", "holder.js/100x100/sky")) - - -shinyUI(pageWithNavBar("NavBar Demo", - navbar = bsNavBar("mainnb", "navBar Demo", - bsNavDropDown("ndd1", "Options", options), - bsNavDropDown("ndd2", "Monitors", media) - ), - tagList(tags$head(tags$script(src = "nbDemo.js"), - tags$script(src = "holder/holder.js")), - suppressWarnings(includeHTML("http://www.gameofipsum.com/api/?type=html¶graphs=5&percent=0")), - bsActionButton("test", "Test", size = "large", style = "primary") - ) - ) - ) \ No newline at end of file diff --git a/inst/examples/navbar/www/holder/holder.js b/inst/examples/navbar/www/holder/holder.js deleted file mode 100644 index d2fe17f..0000000 --- a/inst/examples/navbar/www/holder/holder.js +++ /dev/null @@ -1,658 +0,0 @@ -/*! - -Holder - 2.3.2 - client side image placeholders -(c) 2012-2014 Ivan Malopinsky / http://imsky.co - -Provided under the MIT License. -Commercial use requires attribution. - -*/ -var Holder = Holder || {}; -(function (app, win) { -var system_config = { - use_svg: false, - use_canvas: false, - use_fallback: false -}; -var instance_config = {}; -var preempted = false; -canvas = document.createElement('canvas'); -var dpr = 1, bsr = 1; -var resizable_images = []; - -if (!canvas.getContext) { - system_config.use_fallback = true; -} else { - if (canvas.toDataURL("image/png") - .indexOf("data:image/png") < 0) { - //Android doesn't support data URI - system_config.use_fallback = true; - } else { - var ctx = canvas.getContext("2d"); - } -} - -if(!!document.createElementNS && !!document.createElementNS('http://www.w3.org/2000/svg', 'svg').createSVGRect){ - system_config.use_svg = true; - system_config.use_canvas = false; -} - -if(!system_config.use_fallback){ - dpr = window.devicePixelRatio || 1, - bsr = ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1; -} - -var ratio = dpr / bsr; - -var settings = { - domain: "holder.js", - images: "img", - bgnodes: ".holderjs", - themes: { - "gray": { - background: "#eee", - foreground: "#aaa", - size: 12 - }, - "social": { - background: "#3a5a97", - foreground: "#fff", - size: 12 - }, - "industrial": { - background: "#434A52", - foreground: "#C2F200", - size: 12 - }, - "sky": { - background: "#0D8FDB", - foreground: "#fff", - size: 12 - }, - "vine": { - background: "#39DBAC", - foreground: "#1E292C", - size: 12 - }, - "lava": { - background: "#F8591A", - foreground: "#1C2846", - size: 12 - } - }, - stylesheet: "" -}; -app.flags = { - dimensions: { - regex: /^(\d+)x(\d+)$/, - output: function (val) { - var exec = this.regex.exec(val); - return { - width: +exec[1], - height: +exec[2] - } - } - }, - fluid: { - regex: /^([0-9%]+)x([0-9%]+)$/, - output: function (val) { - var exec = this.regex.exec(val); - return { - width: exec[1], - height: exec[2] - } - } - }, - colors: { - regex: /#([0-9a-f]{3,})\:#([0-9a-f]{3,})/i, - output: function (val) { - var exec = this.regex.exec(val); - return { - size: settings.themes.gray.size, - foreground: "#" + exec[2], - background: "#" + exec[1] - } - } - }, - text: { - regex: /text\:(.*)/, - output: function (val) { - return this.regex.exec(val)[1]; - } - }, - font: { - regex: /font\:(.*)/, - output: function (val) { - return this.regex.exec(val)[1]; - } - }, - auto: { - regex: /^auto$/ - }, - textmode: { - regex: /textmode\:(.*)/, - output: function(val){ - return this.regex.exec(val)[1]; - } - } -} - -function text_size(width, height, template) { - height = parseInt(height, 10); - width = parseInt(width, 10); - var bigSide = Math.max(height, width) - var smallSide = Math.min(height, width) - var scale = 1 / 12; - var newHeight = Math.min(smallSide * 0.75, 0.75 * bigSide * scale); - return { - height: Math.round(Math.max(template.size, newHeight)) - } -} - -var svg_el = (function(){ - //Prevent IE <9 from initializing SVG renderer - if(!window.XMLSerializer) return; - var serializer = new XMLSerializer(); - var svg_ns = "http://www.w3.org/2000/svg" - var svg = document.createElementNS(svg_ns, "svg"); - //IE throws an exception if this is set and Chrome requires it to be set - if(svg.webkitMatchesSelector){ - svg.setAttribute("xmlns", "http://www.w3.org/2000/svg") - } - var bg_el = document.createElementNS(svg_ns, "rect") - var text_el = document.createElementNS(svg_ns, "text") - var textnode_el = document.createTextNode(null) - text_el.setAttribute("text-anchor", "middle") - text_el.appendChild(textnode_el) - svg.appendChild(bg_el) - svg.appendChild(text_el) - - return function(props){ - svg.setAttribute("width",props.width); - svg.setAttribute("height", props.height); - bg_el.setAttribute("width", props.width); - bg_el.setAttribute("height", props.height); - bg_el.setAttribute("fill", props.template.background); - text_el.setAttribute("x", props.width/2) - text_el.setAttribute("y", props.height/2) - textnode_el.nodeValue=props.text - text_el.setAttribute("style", css_properties({ - "fill": props.template.foreground, - "font-weight": "bold", - "font-size": props.text_height+"px", - "font-family":props.font, - "dominant-baseline":"central" - })) - return serializer.serializeToString(svg) - } -})() - -function css_properties(props){ - var ret = []; - for(p in props){ - if(props.hasOwnProperty(p)){ - ret.push(p+":"+props[p]) - } - } - return ret.join(";") -} - -function draw_canvas(args) { - var ctx = args.ctx, - dimensions = args.dimensions, - template = args.template, - ratio = args.ratio, - holder = args.holder, - literal = holder.textmode == "literal", - exact = holder.textmode == "exact"; - - var ts = text_size(dimensions.width, dimensions.height, template); - var text_height = ts.height; - var width = dimensions.width * ratio, - height = dimensions.height * ratio; - var font = template.font ? template.font : "Arial,Helvetica,sans-serif"; - canvas.width = width; - canvas.height = height; - ctx.textAlign = "center"; - ctx.textBaseline = "middle"; - ctx.fillStyle = template.background; - ctx.fillRect(0, 0, width, height); - ctx.fillStyle = template.foreground; - ctx.font = "bold " + text_height + "px " + font; - var text = template.text ? template.text : (Math.floor(dimensions.width) + "x" + Math.floor(dimensions.height)); - if (literal) { - var dimensions = holder.dimensions; - text = dimensions.width + "x" + dimensions.height; - } - else if(exact && holder.exact_dimensions){ - var dimensions = holder.exact_dimensions; - text = (Math.floor(dimensions.width) + "x" + Math.floor(dimensions.height)); - } - var text_width = ctx.measureText(text).width; - if (text_width / width >= 0.75) { - text_height = Math.floor(text_height * 0.75 * (width / text_width)); - } - //Resetting font size if necessary - ctx.font = "bold " + (text_height * ratio) + "px " + font; - ctx.fillText(text, (width / 2), (height / 2), width); - return canvas.toDataURL("image/png"); -} - -function draw_svg(args){ - var dimensions = args.dimensions, - template = args.template, - holder = args.holder, - literal = holder.textmode == "literal", - exact = holder.textmode == "exact"; - - var ts = text_size(dimensions.width, dimensions.height, template); - var text_height = ts.height; - var width = dimensions.width, - height = dimensions.height; - - var font = template.font ? template.font : "Arial,Helvetica,sans-serif"; - var text = template.text ? template.text : (Math.floor(dimensions.width) + "x" + Math.floor(dimensions.height)); - - if (literal) { - var dimensions = holder.dimensions; - text = dimensions.width + "x" + dimensions.height; - } - else if(exact && holder.exact_dimensions){ - var dimensions = holder.exact_dimensions; - text = (Math.floor(dimensions.width) + "x" + Math.floor(dimensions.height)); - } - var string = svg_el({ - text: text, - width:width, - height:height, - text_height:text_height, - font:font, - template:template - }) - return "data:image/svg+xml;base64,"+btoa(unescape(encodeURIComponent(string))); -} - -function draw(args) { - if(instance_config.use_canvas && !instance_config.use_svg){ - return draw_canvas(args); - } - else{ - return draw_svg(args); - } -} - -function render(mode, el, holder, src) { - var dimensions = holder.dimensions, - theme = holder.theme, - text = holder.text ? decodeURIComponent(holder.text) : holder.text; - var dimensions_caption = dimensions.width + "x" + dimensions.height; - theme = (text ? extend(theme, { - text: text - }) : theme); - theme = (holder.font ? extend(theme, { - font: holder.font - }) : theme); - el.setAttribute("data-src", src); - holder.theme = theme; - el.holder_data = holder; - - if (mode == "image") { - el.setAttribute("alt", text ? text : theme.text ? theme.text + " [" + dimensions_caption + "]" : dimensions_caption); - if (instance_config.use_fallback || !holder.auto) { - el.style.width = dimensions.width + "px"; - el.style.height = dimensions.height + "px"; - } - if (instance_config.use_fallback) { - el.style.backgroundColor = theme.background; - } else { - el.setAttribute("src", draw({ctx: ctx, dimensions: dimensions, template: theme, ratio:ratio, holder: holder})); - - if(holder.textmode && holder.textmode == "exact"){ - resizable_images.push(el); - resizable_update(el); - } - - } - } else if (mode == "background") { - if (!instance_config.use_fallback) { - el.style.backgroundImage = "url(" + draw({ctx:ctx, dimensions: dimensions, template: theme, ratio: ratio, holder: holder}) + ")"; - el.style.backgroundSize = dimensions.width + "px " + dimensions.height + "px"; - } - } else if (mode == "fluid") { - el.setAttribute("alt", text ? text : theme.text ? theme.text + " [" + dimensions_caption + "]" : dimensions_caption); - if (dimensions.height.slice(-1) == "%") { - el.style.height = dimensions.height - } else if(holder.auto == null || !holder.auto){ - el.style.height = dimensions.height + "px" - } - if (dimensions.width.slice(-1) == "%") { - el.style.width = dimensions.width - } else if(holder.auto == null || !holder.auto){ - el.style.width = dimensions.width + "px" - } - if (el.style.display == "inline" || el.style.display === "" || el.style.display == "none") { - el.style.display = "block"; - } - - set_initial_dimensions(el) - - if (instance_config.use_fallback) { - el.style.backgroundColor = theme.background; - } else { - resizable_images.push(el); - resizable_update(el); - } - } -} - -function dimension_check(el, callback) { - var dimensions = { - height: el.clientHeight, - width: el.clientWidth - }; - if (!dimensions.height && !dimensions.width) { - el.setAttribute("data-holder-invisible", true) - callback.call(this, el) - } - else{ - el.removeAttribute("data-holder-invisible") - return dimensions; - } -} - -function set_initial_dimensions(el){ - if(el.holder_data){ - var dimensions = dimension_check(el, app.invisible_error_fn( set_initial_dimensions)) - if(dimensions){ - var holder = el.holder_data; - holder.initial_dimensions = dimensions; - holder.fluid_data = { - fluid_height: holder.dimensions.height.slice(-1) == "%", - fluid_width: holder.dimensions.width.slice(-1) == "%", - mode: null - } - if(holder.fluid_data.fluid_width && !holder.fluid_data.fluid_height){ - holder.fluid_data.mode = "width" - holder.fluid_data.ratio = holder.initial_dimensions.width / parseFloat(holder.dimensions.height) - } - else if(!holder.fluid_data.fluid_width && holder.fluid_data.fluid_height){ - holder.fluid_data.mode = "height"; - holder.fluid_data.ratio = parseFloat(holder.dimensions.width) / holder.initial_dimensions.height - } - } - } -} - -function resizable_update(element) { - var images; - if (element.nodeType == null) { - images = resizable_images; - } else { - images = [element] - } - for (var i in images) { - if (!images.hasOwnProperty(i)) { - continue; - } - var el = images[i] - if (el.holder_data) { - var holder = el.holder_data; - var dimensions = dimension_check(el, app.invisible_error_fn( resizable_update)) - if(dimensions){ - if(holder.fluid){ - if(holder.auto){ - switch(holder.fluid_data.mode){ - case "width": - dimensions.height = dimensions.width / holder.fluid_data.ratio; - break; - case "height": - dimensions.width = dimensions.height * holder.fluid_data.ratio; - break; - } - } - el.setAttribute("src", draw({ - ctx: ctx, - dimensions: dimensions, - template: holder.theme, - ratio: ratio, - holder: holder - })) - } - if(holder.textmode && holder.textmode == "exact"){ - holder.exact_dimensions = dimensions; - el.setAttribute("src", draw({ - ctx: ctx, - dimensions: holder.dimensions, - template: holder.theme, - ratio: ratio, - holder: holder - })) - } - } - } - } -} - -function parse_flags(flags, options) { - var ret = { - theme: extend(settings.themes.gray, {}) - }; - var render = false; - for (var fl = flags.length, j = 0; j < fl; j++) { - var flag = flags[j]; - if (app.flags.dimensions.match(flag)) { - render = true; - ret.dimensions = app.flags.dimensions.output(flag); - } else if (app.flags.fluid.match(flag)) { - render = true; - ret.dimensions = app.flags.fluid.output(flag); - ret.fluid = true; - } else if (app.flags.textmode.match(flag)) { - ret.textmode = app.flags.textmode.output(flag) - } else if (app.flags.colors.match(flag)) { - ret.theme = app.flags.colors.output(flag); - } else if (options.themes[flag]) { - //If a theme is specified, it will override custom colors - if(options.themes.hasOwnProperty(flag)){ - ret.theme = extend(options.themes[flag], {}); - } - } else if (app.flags.font.match(flag)) { - ret.font = app.flags.font.output(flag); - } else if (app.flags.auto.match(flag)) { - ret.auto = true; - } else if (app.flags.text.match(flag)) { - ret.text = app.flags.text.output(flag); - } - } - return render ? ret : false; -} - -for (var flag in app.flags) { - if (!app.flags.hasOwnProperty(flag)) continue; - app.flags[flag].match = function (val) { - return val.match(this.regex) - } -} - -app.invisible_error_fn = function(fn){ - return function(el){ - if(el.hasAttribute("data-holder-invisible")){ - throw new Error("Holder: invisible placeholder") - } - } -} - -app.add_theme = function (name, theme) { - name != null && theme != null && (settings.themes[name] = theme); - return app; -}; - -app.add_image = function (src, el) { - var node = selector(el); - if (node.length) { - for (var i = 0, l = node.length; i < l; i++) { - var img = document.createElement("img") - img.setAttribute("data-src", src); - node[i].appendChild(img); - } - } - return app; -}; - -app.run = function (o) { - - instance_config = extend({}, system_config) - preempted = true; - - var options = extend(settings, o), - images = [], - imageNodes = [], - bgnodes = []; - - if(options.use_canvas != null && options.use_canvas){ - instance_config.use_canvas = true; - instance_config.use_svg = false; - } - - if (typeof (options.images) == "string") { - imageNodes = selector(options.images); - } else if (window.NodeList && options.images instanceof window.NodeList) { - imageNodes = options.images; - } else if (window.Node && options.images instanceof window.Node) { - imageNodes = [options.images]; - } else if(window.HTMLCollection && options.images instanceof window.HTMLCollection){ - imageNodes = options.images - } - - if (typeof (options.bgnodes) == "string") { - bgnodes = selector(options.bgnodes); - } else if (window.NodeList && options.elements instanceof window.NodeList) { - bgnodes = options.bgnodes; - } else if (window.Node && options.bgnodes instanceof window.Node) { - bgnodes = [options.bgnodes]; - } - for (i = 0, l = imageNodes.length; i < l; i++) images.push(imageNodes[i]); - - var holdercss = document.getElementById("holderjs-style"); - if (!holdercss) { - holdercss = document.createElement("style"); - holdercss.setAttribute("id", "holderjs-style"); - holdercss.type = "text/css"; - document.getElementsByTagName("head")[0].appendChild(holdercss); - } - - if (!options.nocss) { - if (holdercss.styleSheet) { - holdercss.styleSheet.cssText += options.stylesheet; - } else { - if(options.stylesheet.length){ - holdercss.appendChild(document.createTextNode(options.stylesheet)); - } - } - } - - var cssregex = new RegExp(options.domain + "\/(.*?)\"?\\)"); - for (var l = bgnodes.length, i = 0; i < l; i++) { - var src = window.getComputedStyle(bgnodes[i], null) - .getPropertyValue("background-image"); - var flags = src.match(cssregex); - var bgsrc = bgnodes[i].getAttribute("data-background-src"); - if (flags) { - var holder = parse_flags(flags[1].split("/"), options); - if (holder) { - render("background", bgnodes[i], holder, src); - } - } else if (bgsrc != null) { - var holder = parse_flags(bgsrc.substr(bgsrc.lastIndexOf(options.domain) + options.domain.length + 1) - .split("/"), options); - if (holder) { - render("background", bgnodes[i], holder, src); - } - } - } - for (l = images.length, i = 0; i < l; i++) { - var attr_data_src, attr_src; - attr_src = attr_data_src = src = null; - try { - attr_src = images[i].getAttribute("src"); - attr_datasrc = images[i].getAttribute("data-src"); - } catch (e) {} - if (attr_datasrc == null && !! attr_src && attr_src.indexOf(options.domain) >= 0) { - src = attr_src; - } else if ( !! attr_datasrc && attr_datasrc.indexOf(options.domain) >= 0) { - src = attr_datasrc; - } - if (src) { - var holder = parse_flags(src.substr(src.lastIndexOf(options.domain) + options.domain.length + 1).split("/"), options); - if (holder) { - if (holder.fluid) { - render("fluid", images[i], holder, src) - } else { - render("image", images[i], holder, src); - } - } - } - } - return app; -}; - -contentLoaded(win, function () { - if (window.addEventListener) { - window.addEventListener("resize", resizable_update, false); - window.addEventListener("orientationchange", resizable_update, false); - } else { - window.attachEvent("onresize", resizable_update) - } - preempted || app.run({}); - - if (typeof window.Turbolinks === "object") { - document.addEventListener("page:change", function() { app.run({}) }) - } -}); -if (typeof define === "function" && define.amd) { - define([], function () { - return app; - }); -} - -//github.com/davidchambers/Base64.js -(function(){function t(t){this.message=t}var e="undefined"!=typeof exports?exports:this,r="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";t.prototype=Error(),t.prototype.name="InvalidCharacterError",e.btoa||(e.btoa=function(e){for(var o,n,a=0,i=r,c="";e.charAt(0|a)||(i="=",a%1);c+=i.charAt(63&o>>8-8*(a%1))){if(n=e.charCodeAt(a+=.75),n>255)throw new t("'btoa' failed");o=o<<8|n}return c}),e.atob||(e.atob=function(e){if(e=e.replace(/=+$/,""),1==e.length%4)throw new t("'atob' failed");for(var o,n,a=0,i=0,c="";n=e.charAt(i++);~n&&(o=a%4?64*o+n:n,a++%4)?c+=String.fromCharCode(255&o>>(6&-2*a)):0)n=r.indexOf(n);return c})})(); - -//getElementsByClassName polyfill -document.getElementsByClassName||(document.getElementsByClassName=function(e){var t=document,n,r,i,s=[];if(t.querySelectorAll)return t.querySelectorAll("."+e);if(t.evaluate){r=".//*[contains(concat(' ', @class, ' '), ' "+e+" ')]",n=t.evaluate(r,t,null,0,null);while(i=n.iterateNext())s.push(i)}else{n=t.getElementsByTagName("*"),r=new RegExp("(^|\\s)"+e+"(\\s|$)");for(i=0;iupdateCollapse."), + actionButton("p1Button", "Push Me!"), + selectInput("styleSelect", "Select style for Panel 1", + c("default", "primary", "danger", "warning", "info", "success")) + ), + mainPanel( + bsCollapse(id = "collapseExample", open = "Panel 2", + bsCollapsePanel("Panel 1", "This is a panel with just text ", + "and has the default style. You can change the style in ", + "the sidebar.", style = "info"), + bsCollapsePanel("Panel 2", "This panel has a generic plot. ", + "and a 'success' style.", plotOutput("genericPlot"), style = "success") + ), + + uiOutput("tooltip_test"), + actionButton("test2", "Test2"), + bsTooltip("test2", title = "Test2", placement="right"), + tipify(tags$button("Hello"), "Test without ID") + + ) + ) + ), + server = + function(input, output, session) { + output$genericPlot <- renderPlot(plot(rnorm(100))) + observeEvent(input$p1Button, ({ + updateCollapse(session, "collapseExample", open = "Panel 1") + })) + observeEvent(input$styleSelect, ({ + updateCollapse(session, "collapseExample", style = list("Panel 1" = input$styleSelect)) + })) + + output$tooltip_test <- renderUI({ + tipify(actionButton("test", "Test"), title = "test", placement = "right") + }) + } +) + +runApp(app) \ No newline at end of file diff --git a/inst/www/bootstrap3-typeahead.js b/inst/www/bootstrap3-typeahead.js new file mode 100644 index 0000000..d824f6d --- /dev/null +++ b/inst/www/bootstrap3-typeahead.js @@ -0,0 +1,476 @@ +/* ============================================================= + * bootstrap3-typeahead.js v3.1.0 + * https://github.com/bassjobsen/Bootstrap-3-Typeahead + * ============================================================= + * Original written by @mdo and @fat + * ============================================================= + * Copyright 2014 Bass Jobsen @bassjobsen + * + * Licensed under the Apache License, Version 2.0 (the 'License'); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an 'AS IS' BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================ */ + + +(function (root, factory) { + + 'use strict'; + + // CommonJS module is defined + if (typeof module !== 'undefined' && module.exports) { + module.exports = factory(require('jquery')); + } + // AMD module is defined + else if (typeof define === 'function' && define.amd) { + define(['jquery'], function ($) { + return factory ($); + }); + } else { + factory(root.jQuery); + } + +}(this, function ($) { + + 'use strict'; + // jshint laxcomma: true + + + /* TYPEAHEAD PUBLIC CLASS DEFINITION + * ================================= */ + + var Typeahead = function (element, options) { + this.$element = $(element); + this.options = $.extend({}, $.fn.typeahead.defaults, options); + this.matcher = this.options.matcher || this.matcher; + this.sorter = this.options.sorter || this.sorter; + this.select = this.options.select || this.select; + this.autoSelect = typeof this.options.autoSelect == 'boolean' ? this.options.autoSelect : true; + this.highlighter = this.options.highlighter || this.highlighter; + this.render = this.options.render || this.render; + this.updater = this.options.updater || this.updater; + this.displayText = this.options.displayText || this.displayText; + this.source = this.options.source; + this.delay = this.options.delay; + this.$menu = $(this.options.menu); + this.$appendTo = this.options.appendTo ? $(this.options.appendTo) : null; + this.shown = false; + this.listen(); + this.showHintOnFocus = typeof this.options.showHintOnFocus == 'boolean' ? this.options.showHintOnFocus : false; + this.afterSelect = this.options.afterSelect; + this.addItem = false; + }; + + Typeahead.prototype = { + + constructor: Typeahead, + + select: function () { + var val = this.$menu.find('.active').data('value'); + this.$element.data('active', val); + if(this.autoSelect || val) { + var newVal = this.updater(val); + this.$element + .val(this.displayText(newVal) || newVal) + .change(); + this.afterSelect(newVal); + } + return this.hide(); + }, + + updater: function (item) { + return item; + }, + + setSource: function (source) { + this.source = source; + }, + + show: function () { + var pos = $.extend({}, this.$element.position(), { + height: this.$element[0].offsetHeight + }), scrollHeight; + + scrollHeight = typeof this.options.scrollHeight == 'function' ? + this.options.scrollHeight.call() : + this.options.scrollHeight; + + (this.$appendTo ? this.$menu.appendTo(this.$appendTo) : this.$menu.insertAfter(this.$element)) + .css({ + top: pos.top + pos.height + scrollHeight + , left: pos.left + }) + .show(); + + this.shown = true; + return this; + }, + + hide: function () { + this.$menu.hide(); + this.shown = false; + return this; + }, + + lookup: function (query) { + var items; + if (typeof(query) != 'undefined' && query !== null) { + this.query = query; + } else { + this.query = this.$element.val() || ''; + } + + if (this.query.length < this.options.minLength) { + return this.shown ? this.hide() : this; + } + + var worker = $.proxy(function() { + + if($.isFunction(this.source)) this.source(this.query, $.proxy(this.process, this)); + else if (this.source) { + this.process(this.source); + } + }, this); + + clearTimeout(this.lookupWorker); + this.lookupWorker = setTimeout(worker, this.delay); + }, + + process: function (items) { + var that = this; + + items = $.grep(items, function (item) { + return that.matcher(item); + }); + + items = this.sorter(items); + + if (!items.length && !this.options.addItem) { + return this.shown ? this.hide() : this; + } + + if (items.length > 0) { + this.$element.data('active', items[0]); + } else { + this.$element.data('active', null); + } + + // Add item + if (this.options.addItem){ + items.push(this.options.addItem); + } + + if (this.options.items == 'all') { + return this.render(items).show(); + } else { + return this.render(items.slice(0, this.options.items)).show(); + } + }, + + matcher: function (item) { + var it = this.displayText(item); + return ~it.toLowerCase().indexOf(this.query.toLowerCase()); + }, + + sorter: function (items) { + var beginswith = [] + , caseSensitive = [] + , caseInsensitive = [] + , item; + + while ((item = items.shift())) { + var it = this.displayText(item); + if (!it.toLowerCase().indexOf(this.query.toLowerCase())) beginswith.push(item); + else if (~it.indexOf(this.query)) caseSensitive.push(item); + else caseInsensitive.push(item); + } + + return beginswith.concat(caseSensitive, caseInsensitive); + }, + + highlighter: function (item) { + var html = $('
'); + var query = this.query; + var i = item.toLowerCase().indexOf(query.toLowerCase()); + var len, leftPart, middlePart, rightPart, strong; + len = query.length; + if(len === 0){ + return html.text(item).html(); + } + while (i > -1) { + leftPart = item.substr(0, i); + middlePart = item.substr(i, len); + rightPart = item.substr(i + len); + strong = $('').text(middlePart); + html + .append(document.createTextNode(leftPart)) + .append(strong); + item = rightPart; + i = item.toLowerCase().indexOf(query.toLowerCase()); + } + return html.append(document.createTextNode(item)).html(); + }, + + render: function (items) { + var that = this; + var self = this; + var activeFound = false; + items = $(items).map(function (i, item) { + var text = self.displayText(item); + i = $(that.options.item).data('value', item); + i.find('a').html(that.highlighter(text)); + if (text == self.$element.val()) { + i.addClass('active'); + self.$element.data('active', item); + activeFound = true; + } + return i[0]; + }); + + if (this.autoSelect && !activeFound) { + items.first().addClass('active'); + this.$element.data('active', items.first().data('value')); + } + this.$menu.html(items); + return this; + }, + + displayText: function(item) { + return item.name || item; + }, + + next: function (event) { + var active = this.$menu.find('.active').removeClass('active') + , next = active.next(); + + if (!next.length) { + next = $(this.$menu.find('li')[0]); + } + + next.addClass('active'); + }, + + prev: function (event) { + var active = this.$menu.find('.active').removeClass('active') + , prev = active.prev(); + + if (!prev.length) { + prev = this.$menu.find('li').last(); + } + + prev.addClass('active'); + }, + + listen: function () { + this.$element + .on('focus', $.proxy(this.focus, this)) + .on('blur', $.proxy(this.blur, this)) + .on('keypress', $.proxy(this.keypress, this)) + .on('keyup', $.proxy(this.keyup, this)); + + if (this.eventSupported('keydown')) { + this.$element.on('keydown', $.proxy(this.keydown, this)); + } + + this.$menu + .on('click', $.proxy(this.click, this)) + .on('mouseenter', 'li', $.proxy(this.mouseenter, this)) + .on('mouseleave', 'li', $.proxy(this.mouseleave, this)); + }, + + destroy : function () { + this.$element.data('typeahead',null); + this.$element.data('active',null); + this.$element + .off('focus') + .off('blur') + .off('keypress') + .off('keyup'); + + if (this.eventSupported('keydown')) { + this.$element.off('keydown'); + } + + this.$menu.remove(); + }, + + eventSupported: function(eventName) { + var isSupported = eventName in this.$element; + if (!isSupported) { + this.$element.setAttribute(eventName, 'return;'); + isSupported = typeof this.$element[eventName] === 'function'; + } + return isSupported; + }, + + move: function (e) { + if (!this.shown) return; + + switch(e.keyCode) { + case 9: // tab + case 13: // enter + case 27: // escape + e.preventDefault(); + break; + + case 38: // up arrow + // with the shiftKey (this is actually the left parenthesis) + if (e.shiftKey) return; + e.preventDefault(); + this.prev(); + break; + + case 40: // down arrow + // with the shiftKey (this is actually the right parenthesis) + if (e.shiftKey) return; + e.preventDefault(); + this.next(); + break; + } + + e.stopPropagation(); + }, + + keydown: function (e) { + this.suppressKeyPressRepeat = ~$.inArray(e.keyCode, [40,38,9,13,27]); + if (!this.shown && e.keyCode == 40) { + this.lookup(); + } else { + this.move(e); + } + }, + + keypress: function (e) { + if (this.suppressKeyPressRepeat) return; + this.move(e); + }, + + keyup: function (e) { + switch(e.keyCode) { + case 40: // down arrow + case 38: // up arrow + case 16: // shift + case 17: // ctrl + case 18: // alt + break; + + case 9: // tab + case 13: // enter + if (!this.shown) return; + this.select(); + break; + + case 27: // escape + if (!this.shown) return; + this.hide(); + break; + default: + this.lookup(); + } + + e.stopPropagation(); + e.preventDefault(); + }, + + focus: function (e) { + if (!this.focused) { + this.focused = true; + if (this.options.showHintOnFocus) { + this.lookup(''); + } + } + }, + + blur: function (e) { + this.focused = false; + if (!this.mousedover && this.shown) this.hide(); + }, + + click: function (e) { + e.stopPropagation(); + e.preventDefault(); + this.select(); + this.$element.focus(); + }, + + mouseenter: function (e) { + this.mousedover = true; + this.$menu.find('.active').removeClass('active'); + $(e.currentTarget).addClass('active'); + }, + + mouseleave: function (e) { + this.mousedover = false; + if (!this.focused && this.shown) this.hide(); + } + + }; + + + /* TYPEAHEAD PLUGIN DEFINITION + * =========================== */ + + var old = $.fn.typeahead; + + $.fn.typeahead = function (option) { + var arg = arguments; + if (typeof option == 'string' && option == 'getActive') { + return this.data('active'); + } + return this.each(function () { + var $this = $(this) + , data = $this.data('typeahead') + , options = typeof option == 'object' && option; + if (!data) $this.data('typeahead', (data = new Typeahead(this, options))); + if (typeof option == 'string') { + if (arg.length > 1) { + data[option].apply(data, Array.prototype.slice.call(arg ,1)); + } else { + data[option](); + } + } + }); + }; + + $.fn.typeahead.defaults = { + source: [] + , items: 8 + , menu: '' + , item: '
  • ' + , minLength: 1 + , scrollHeight: 0 + , autoSelect: true + , afterSelect: $.noop + , addItem: false + , delay: 0 + }; + + $.fn.typeahead.Constructor = Typeahead; + + + /* TYPEAHEAD NO CONFLICT + * =================== */ + + $.fn.typeahead.noConflict = function () { + $.fn.typeahead = old; + return this; + }; + + + /* TYPEAHEAD DATA-API + * ================== */ + + $(document).on('focus.typeahead.data-api', '[data-provide="typeahead"]', function (e) { + var $this = $(this); + if ($this.data('typeahead')) return; + $this.typeahead($this.data()); + }); + +})); diff --git a/inst/www/shinyBS.css b/inst/www/shinyBS.css index e85b463..8a3c628 100644 --- a/inst/www/shinyBS.css +++ b/inst/www/shinyBS.css @@ -1,55 +1,12 @@ -.dropdown-menu > li > a > .media { - - min-width: 480px; - white-space: normal; - +.sbs-alert-hover { + position: absolute; + z-index: 1000; + width: 30%; + margin-left: 35%; + margin-top: 10px; + opacity: 0.7; } -.navbar-form{ - padding-left: 3px; - padding-right: 3px; -} - -td.success { - background-color: rgb(223, 240, 216); -} - -td.error { - background-color: rgb(242, 222, 222); -} - -td.warning, tr.warning { - background-color: rgb(252, 248, 227); -} - -td.info { - background-color: rgb(217, 237, 247); -} - -td.disabled { - background-color: rgb(230, 230, 230); - color: rgb(51, 51, 51); - opacity: 0.65; -} - -td.good, tr.good { - background-color: rgb(200, 240, 205); - color: rgb(0, 100, 0) -} - -td.bad, tr.bad { - background-color: rgb(255, 200, 205); - color: rgb(150, 0, 0) -} - -td.neutral, tr.neutral{ - background-color: rgb(255, 235, 150); - color: rgb(150, 100, 0); -} - -.btn-group.btn-block { - display: table; -} -.btn-group.btn-block > .btn { - display: table-cell; +.sbs-alert-hover:hover { + opacity: 1.0; } \ No newline at end of file diff --git a/inst/www/shinyBS.js b/inst/www/shinyBS.js index fc63b23..cd65e90 100644 --- a/inst/www/shinyBS.js +++ b/inst/www/shinyBS.js @@ -1,786 +1,305 @@ -//Makes it so clicking on an tag such as bsNavLink won't return you to the top of the page. -$(document).ready(function() { - - $('a[href="#"]').click(function(e){ - e.preventDefault(); - }) - -}) - -//New Input Bindings - -var bsModalBinding = new Shiny.InputBinding(); -$.extend(bsModalBinding, { +var shinyBS = {inputBindings: {}}; +shinyBS.inputBindings.toggle = new Shiny.InputBinding(); +$.extend(shinyBS.inputBindings.toggle, { find: function(scope) { - return $(scope).find(".sbs-modal"); + return $(scope).find(".sbs-toggle-button"); }, getValue: function(el) { - return $(el).hasClass("in"); - }, - setValue: function(el, value) { - $(el).toggleClass("hide", value); + return $(el).hasClass("active"); }, subscribe: function(el, callback) { - $(el).on("shown.bsModalBinding hidden.bsModalBinding", function(e) { + $(el).on("click", function(e) { + $(el).toggleClass("active").blur(); callback(); }) }, - receiveMessage: function(el, data) { - if(data.hasOwnProperty("toggle")) { - if(data.toggle) { - $(el).modal("toggle"); - } - } - }, unsubscribe: function(el) { - $(el).off(".bsModalBinding"); - }, - initialize: function(el) { - var $trigger = $("#" + $(el).attr("data-trigger")); - $trigger.attr("data-target", "#" + $(el).attr("id")); - $trigger.attr("data-toggle", "modal"); + $(el).off("click"); } }); -Shiny.inputBindings.register(bsModalBinding); +Shiny.inputBindings.register(shinyBS.inputBindings.toggle) -var bsButtonBinding = new Shiny.InputBinding(); -$.extend(bsButtonBinding, { +shinyBS.inputBindings.modal = new Shiny.InputBinding(); +$.extend(shinyBS.inputBindings.modal, { find: function(scope) { - return $(scope).find(".sbs-btn"); + return $(scope).find(".sbs-modal"); }, getValue: function(el) { - return $(el).attr('data-value'); - }, - setValue: function(el, value) { - $(el).data('val', value); + return $(el).hasClass("in"); }, subscribe: function(el, callback) { - $(el).on("click.bsButtonBinding", function(e) { - callback(); - }); - }, - getState: function(el) { - return { value: this.getValue(el) }; + $(el).on("hidden.bs.modal shown.bs.modal", callback) }, - receiveMessage: function(el, data) { - updateButtonStyle(el, data); - }, unsubscribe: function(el) { - $(el).off(".bsButtonBinding"); - } -}); -Shiny.inputBindings.register(bsButtonBinding); - -/* Creates a clone of the actionButtonBinding, but with a receiveMessage -function for changing the style, size, etc. of the button. I tried to find a -way to do this without just copying the input binding but was unsuccessful. */ -var bsActionButtonInputBinding = new Shiny.InputBinding(); -$.extend(bsActionButtonInputBinding, { - find: function(scope) { - return $(scope).find(".sbs-action-button"); - }, - getValue: function(el) { - return $(el).data('val') || 0; - }, - setValue: function(el, value) { - $(el).data('val', value); - }, - subscribe: function(el, callback) { - $(el).on("click.bsActionButtonInputBinding", function(e) { - if(!$(el).hasClass("disabled")) { - var $el = $(this); - var val = $el.data('val') || 0; - $el.data('val', val + 1); - callback(); - }}) - }, - getState: function(el) { - return { value: this.getValue(el) }; + $(el).off("hidden.bs.modal shown.bs.modal") }, receiveMessage: function(el, data) { - updateButtonStyle(el, data); - }, - unsubscribe: function(el) { - $(el).off(".bsActionButtonInputBinding"); - } -}); -Shiny.inputBindings.register(bsActionButtonInputBinding) - -var bsToggleButtonBinding = new Shiny.InputBinding(); -$.extend(bsToggleButtonBinding, { - find: function(scope) { - return $(scope).find(".sbs-toggle-button"); - }, - getValue: function(el) { - return $(el).hasClass("bs-active"); - }, - setValue: function(el, value) { - $(el).toggleClass("active bs-active", value); - }, - subscribe: function(el, callback) { - $(el).on("click.bsToggleButtonBinding", function(e) { - if(!$(el).hasClass("disabled")) { - $(el).toggleClass("bs-active"); - callback(); + if(data.hasOwnProperty("toggle")) { + if(data.toggle == "show") { + $(el).modal("show"); + } else if(data.toggle == "hide") { + $(el).modal("hide"); } else { - //Disabled toggle buttons appear to still toggle invisibly, this makes it to a double toggle so the state remains correct. - $(el).toggleClass("active"); + $(el).modal("toggle"); } - }); - }, - getState: function(el) { - return { value: this.getValue(el) }; + }; }, - receiveMessage: function(el, data) { - updateButtonStyle(el, data); - if(data.hasOwnProperty("value")) { - $(el).toggleClass("active bs-active", data.value); - } - }, - unsubscribe: function(el) { - $(el).off(".bsToggleButtonBinding"); - } + initialize: function(el) { + $("#" + $(el).attr("data-sbs-trigger")).attr({"data-toggle": "modal", "data-target": "#" + $(el).attr("id")}); + } }); -Shiny.inputBindings.register(bsToggleButtonBinding); +Shiny.inputBindings.register(shinyBS.inputBindings.modal); -//Creates an input binding for bsCollapse objects -var collapseBinding = new Shiny.InputBinding(); -$.extend(collapseBinding, { +shinyBS.inputBindings.collapse = new Shiny.InputBinding(); +$.extend(shinyBS.inputBindings.collapse, { find: function(scope) { - return $(scope).find(".accordion"); - }, - getId: function(el) { - return Shiny.InputBinding.prototype.getId.call(this, el) || el.name; + return $(scope).find(".sbs-panel-group"); }, getValue: function(el) { - var op = $(el).find(".in").map(function() { - var v = $(this).attr("data-value"); - if(v == undefined) { - v = null; - }; - return v; - }).get(); - return op; + return $(el).data("sbs-value"); }, - receiveMessage: function(el, data) { + var $el = $(el); +/* I would think this code should work, but it doesn't for some reason so I am + commenting it out. if(data.hasOwnProperty('multiple')) { - if(data.multiple == false) { - $(el).find('.collapse').each(function(i, e) { - $(this).data('collapse').$parent = $("#" + $(el).attr("id")); - }) + if(data.multiple) { + $el.find(".collapse").each(function(i) {$(this).collapse({parent: false, toggle: false})}); } else { - $(el).find('.collapse').each(function(i, e) { - $(this).data('collapse').$parent = false; - }) + $el.find(".collapse").each(function(i) {$(this).collapse({parent: "#"+$el.attr("id"), toggle: false})}); } } - if(data.hasOwnProperty('open')) { - if(data.open instanceof Array) { - $.each(data.open, function(i, e) { - if($("#" + e).data('collapse').$parent == false) { - if(!$("#" + e).hasClass("in")) { - $("#" + e).collapse('show'); - } - } else { - if(!$("#" + data.open[0]).hasClass("in")) { - $("#" + data.open[0]).collapse('show'); - } - } - }) - } else { - if(!$("#" + data.open).hasClass("in")) { - $("#" + data.open).collapse('show'); - } +*/ + if(data.hasOwnProperty('style')) { + var panels = Object.keys(data.style) + for(var i = 0; i < panels.length; i++) { + var $p = $el.find("div[value='" + panels[i] + "']") + $p + .removeClass("panel-primary panel-danger panel-warning panel-error panel-info panel-success") + .addClass("panel-" + data.style[panels[i]]); } } - if(data.hasOwnProperty('close')) { - if(data.close instanceof Array) { - $.each(data.close, function(i, e) { - if($("#" + e).hasClass("in")) { - $("#" + e).collapse('hide'); - } - }) - } else { - if($("#" + data.close).hasClass("in")) { - $("#" + data.close).collapse('hide'); - } + if(data.hasOwnProperty('open')) { + if(!Array.isArray(data.open)) { + data.open = [data.open] } + data.open.forEach(function(value, index, array) { + $el.find("div[value='" + value + "'] > .panel-collapse").collapse("show"); + }) } - - }, - - initialize: function(el) { - - if($(el).attr('data-multiple') == 'FALSE') { - var par = "#"+$(el).attr("id") - } else { - var par = false; - } - $(el).find(".collapse").each(function(i, e) { - $(this).collapse({parent: par, toggle: false}); - }) - - }, - - subscribe: function(el, callback) { - $(el).find("div.accordion-body").on("shown hidden", function(e) { - callback(); - }); - }, - unsubscribe: function(el) { - $(el).find("div.accordion-body").off("shown hidden"); - } - -}); -Shiny.inputBindings.register(collapseBinding); - -//Creates an input binding for the bsNavDropdown object -var dropdownBinding = new Shiny.InputBinding(); -$.extend(dropdownBinding, { - find: function(scope) { - return $(scope).find(".sbs-dropdown"); - }, - getId: function(el) { - return Shiny.InputBinding.prototype.getId.call(this, el) || el.name; - }, - getValue: function(el) { - return $(el).attr("data-value"); - }, - setValue: function(el, value) { - $(el).attr("data-value", value); - }, - receiveMessage: function(el, data) { - if(data.hasOwnProperty('selected')) { - $(el).attr("data-value", data.selected) - } - if(data.hasOwnProperty('label')) { - $(el).children("a").html(data.label+""); - } - if(data.hasOwnProperty('options')) { - $(el).children("ul.dropdown-menu").replaceWith(data.options); - this.initialize(el); + if(data.hasOwnProperty("close")) { + if(!Array.isArray(data.close)) { + data.close = [data.close]; + } + data.close.forEach(function(value, index, array) { + $el.find("div[value='" + value + "'] > .panel-collapse").collapse("hide"); + }) } }, subscribe: function(el, callback) { - $(el).on("click.dropdownBinding", function(e) { - callback(); - }); + $(el).find(".collapse").on("shown.bs.collapse hidden.bs.collapse", callback); }, initialize: function(el) { - $(el).find("li").not(".divider, .nav-header, .dropdown-submenu").click(function() { - $(this).parents(".sbs-dropdown").attr("data-value", $(this).attr("data-value")); - $(this).parents(".sbs-dropdown").removeClass("open"); - }); - }, - unsubscribe: function(el) { - $(el).off(".dropdownBinding"); - } -}); -Shiny.inputBindings.register(dropdownBinding); - -//Creates input binding for TypeAhead Objects -var typeAheadBinding = new Shiny.InputBinding(); -$.extend(typeAheadBinding, { - - find: function(scope) { - return $(scope).find('.sbs-typeahead'); - }, - getId: function(el) { - return Shiny.InputBinding.prototype.getId.call(this, el) || el.name; - }, - getValue: function(el) { - return el.value; - }, - setValue: function(el, value) { - el.value = value; - }, - initialize: function(el) { - $(el).typeahead(); - }, - subscribe: function(el, callback) { - $(el).on('keyup.typeAheadBinding input.typeAheadBinding', function(event) { - callback(true); - }); - $(el).on('change.typeAheadBinding', function(event) { - callback(false); - }); - }, - unsubscribe: function(el) { - $(el).off('.textInputBinding'); - }, - receiveMessage: function(el, data) { - - if (data.hasOwnProperty('value')) { - this.setValue(el, data.value); - }; - if (data.hasOwnProperty('label')) { - $(el).parent().find('label[for=' + el.id + ']').text(data.label); - }; - if (data.hasOwnProperty('choices')) { - $(el).data('typeahead').source = data.choices; - }; - - $(el).trigger('change'); - - }, - getState: function(el) { - return { - label: $(el).parent().find('label[for=' + el.id + ']').text(), - value: el.value - }; - }, - getRatePolicy: function() { - return { - policy: 'debounce', - delay: 250 - }; - } - -}); -Shiny.inputBindings.register(typeAheadBinding); - -//Create Input Binding for bsNavtoggleLink Objects -var tLinkBinding = new Shiny.InputBinding(); -$.extend(tLinkBinding, { - find: function(scope) { - return $(scope).find(".sbs-toggle"); - }, - getValue: function(el) { - return $(el).parent().hasClass("active"); - }, - setValue: function(el, value) { - $(el).parent().toggleClass("active", value); - }, - getState: function(el) { - return { - label: $(el).text(), - value: $(el).parent().hasClass("active") - }; - }, - receiveMessage: function(el, data) { - if(data.hasOwnProperty("value")) { - $(el).parent().toggleClass("active", data.value); - }; - if(data.hasOwnProperty("label")) { - $(el).html(data.label); - }; - }, - initialize: function(el) { - $(el).click(function() { - $(this).parent().toggleClass("active"); - }) - }, - subscribe: function(el, callback) { - $(el).on("click.tLinkBinding", function(event) { - callback(); - }) - }, - unsubscribe: function(el) { - $(el).off("click.tLinkBinding"); - } - -}); -Shiny.inputBindings.register(tLinkBinding); - -//Create Input Binding for bsButtonGroups -var buttonGroupBinding = new Shiny.InputBinding(); - $.extend(buttonGroupBinding, { - find: function(scope) { - return $(scope).find(".sbs-button-group"); - }, - getValue: function(el) { - var op = $(el).children(".bs-active").map(function() { - var v = $(this).attr("data-value"); - if(v == undefined) { - v = null; - }; - return v; - }).get(); - return op; - }, - setValue: function(el, value) { - $(el).children(".bs-active").removeClass("bs-active active"); - if(value instanceof Array) { - $.each(value, function(i, e) { - $(el).children("#" + e).addClass("active bs-active"); - }) + var $el = $(el); + var $panels = $el.children(".panel"); + var val = []; + $panels.each(function(i) { + if($(this).children("div.panel-collapse.collapse").hasClass("in")) { + val.push($(this).attr("value")); + } + var $pan = $(this).children("div.panel-collapse.collapse"); + if($el.attr("data-sbs-multi") == "FALSE") { + var par = "#" + $el.attr("id"); } else { - $(el).children("#" + value).addClass("active bs-active"); + var par = false; } - }, - receiveMessage: function(el, data) { - var $el = $(el); - if(data.hasOwnProperty("toggle")) { - if(data.toggle == "none") { - $el.removeAttr("data-toggle"); - $el.children(".btn").removeClass("bs-active active"); - } else { - if($(el).attr("data-toggle") == "buttons-radio") { - $(el).children(".btn") - } - $el.attr("data-toggle", "buttons-" + data.toggle); - } - }; - if(data.hasOwnProperty("style")) { - $el.children(".btn").removeClass("btn-primary btn-info btn-success btn-warning btn-danger btn-inverse btn-link"); - if(data.style != "default") { - $el.children(".btn").addClass("btn-"+data.style); - } - }; - if(data.hasOwnProperty("size")) { - $el.children(".btn").removeClass("btn-large btn-small btn-mini"); - if(data.size != "default") { - $el.children(".btn").addClass("btn-"+data.size); - } - }; - if(data.hasOwnProperty("disabled")) { - $el.children(".btn").toggleClass("disabled", data.disabled); - }; - if(data.hasOwnProperty("value")) { - var val = data.value; - $el.children(".btn").removeClass("active bs-active"); - if(val instanceof Array & $el.attr("data-toggle") != "buttons-radio") { - $.each(val, function(i, e) { - $el.children(".btn[data-value = '"+e+"']").addClass("active bs-active"); - }) - } else { - if(val instanceof Array & $el.attr("data-toggle") == "buttons-radio") { - val = val[0]; - } - $el.children(".btn[data-value = '"+val+"']").addClass("active bs-active"); - } - }; - }, - subscribe: function(el, callback) { - $(el).children(".btn").on("click", function(e) { - if(!$(this).hasClass("disabled")) { - if($(el).attr("data-toggle") == "buttons-radio") { - $(el).children(".btn").removeClass("bs-active"); - $(this).addClass("bs-active"); - } else { - $(this).toggleClass("bs-active"); - } - callback(); - } - }) - }, - unsubscribe: function(el) { - $(el).children(".btn").off("click"); - } - }); -Shiny.inputBindings.register(buttonGroupBinding); - - -//Support Functions - -function addPopover(id, title, content, placement, trigger) { - - var $id = $("#"+id) - if($id.attr("type") == "slider") { - $id = $id.parent(); - } - if($id.hasClass("selectized")) { - $id = $id.siblings("div.selectize-control"); - } - var $par = $id.parent(); - if($par.is('[id]')) { - var par = $par.attr("id"); - } else { - var par = "par" + parseInt(Math.random()*1000000); - $par.attr("id", par); + $pan.collapse({parent: par, toggle: false}); + }); + $el.data("sbs-value", val); + $panels.on("show.bs.collapse", function(event) { + var val = $el.data("sbs-value"); + val.push($(this).attr("value")); + $el.data("sbs-value", val) + }); + $panels.on("hide.bs.collapse", function(event) { + var val = $el.data("sbs-value"); + var i = val.indexOf($(this).attr("value")) + if(i != -1) { + val.splice(i, 1); + $el.data("sbs-value", val); + } + }); } +}) +Shiny.inputBindings.register(shinyBS.inputBindings.collapse); - $id.popover('destroy'); - $id.popover({html: true, - placement: placement, - trigger: trigger, - title: title, - content: content, - container: '#' + par - }); - $id.data("popover") -}; -function addTooltip(id, title, placement, trigger) { +Shiny.addCustomMessageHandler("bsAlertCreate", function(data) { - var $id = $("#"+id) - if($id.attr("type") == "slider") { - $id = $id.parent() - } - if($id.hasClass("selectized")) { - $id = $id.siblings("div.selectize-control"); - } - var $par = $id.parent(); - if($par.is('[id]')) { - var par = $par.attr("id"); - } else { - var par = "par" + parseInt(Math.random()*1000000); - $par.attr("id", par); - } - - $id.tooltip('destroy'); - $id.tooltip({title: title, - placement: placement, - trigger: trigger, - html: true, - container: "#"+par - }); - -}; - -function updateButtonStyle(el, data) { + var create = true; - var $el = $(el) - if(data.hasOwnProperty("label")) { - $el.html(data.label); - } - if(data.hasOwnProperty("style")) { - $el.removeClass("btn-primary btn-info btn-success btn-warning btn-danger btn-inverse btn-link"); - if(data.style != "default") { - $el.addClass("btn-"+data.style); - } - } - if(data.hasOwnProperty("size")) { - $el.removeClass("btn-large btn-small btn-mini"); - if(data.size != "default") { - $el.addClass("btn-"+data.size); + if(data.hasOwnProperty("alertId")) { + if($("#" + data.alertId).length > 0) { + create = false; } } - if(data.hasOwnProperty("block")) { - $el.toggleClass("btn-block", data.block); - } - if(data.hasOwnProperty("disabled")) { - $el.toggleClass("disabled", data.disabled); - } - -} - -//New Customg Message Handlers + if(create) { -Shiny.addCustomMessageHandler("createalert", - function(data) { - - var cl = "alert"; - if(data.hasOwnProperty('type')) { - cl = cl+" alert-"+data.type; - }; - if(data.hasOwnProperty('block')) { - if(data.block == true) { - cl = cl+" alert-block"; - } - } + var $alert = $("
    "); - al = "
    " - - if(data.dismiss == true) { - al = al+""; + if(data.hasOwnProperty("dismiss")) { + $alert.addClass("alert-dismissable"); + } + + if(data.hasOwnProperty("alertId")) { + $alert.attr("id", data.alertId); } + if(data.hasOwnProperty('dismiss')) { + if(data.dismiss == true) { + $alert.append("") + } + } + if(data.hasOwnProperty('title')) { - al = al+"

    "+data.title+"

    "; + $alert.append("

    " + data.title + "

    "); } - al = al + data.message + "
    "; - + if(data.hasOwnProperty("content")) { + $alert.append(data.content); + } + if(data.append == true) { - $(al).appendTo("#"+data.id); + $alert.appendTo("#" + data.id); } else { - $("#"+data.id).html(al); + $("#" + data.id).html($alert); } } -); -Shiny.addCustomMessageHandler("closealert", - function(alertId) { - $("#"+alertId).alert('close'); - } -); +}); -Shiny.addCustomMessageHandler("updateprogress", - function(data) { - $el = $("#"+data.id); - if(data.hasOwnProperty('value')) { - $el.find("div.bar").width(data.value+"%"); - }; - if(data.hasOwnProperty('visible')) { - $el.toggleClass("hidden", !data.visible); - }; - if(data.hasOwnProperty('color')) { - $el.removeClass("progress-standard progress-info progress-success progress-danger progress-warning") - $el.addClass("progress-"+data.color) - }; - if(data.hasOwnProperty('striped')) { - $el.toggleClass('progress-striped', data.striped); - }; - if(data.hasOwnProperty('animate')) { - $el.toggleClass('active', data.animate); - } - } -); +Shiny.addCustomMessageHandler("bsAlertClose", function(alertId) { + $("#" + alertId).alert('close'); +}); -Shiny.addCustomMessageHandler("modifynavbar", - function(data) { - $el = $("#"+data.id); - if(data.hasOwnProperty("brand")) { - $el.find(".brand").text(data.brand); - }; - if(data.hasOwnProperty("fixed")) { - var f = $el.hasClass("navbar-fixed-top") - $el.toggleClass("navbar-fixed-top", data.fixed); - if($el.hasClass("navbar-fixed-top") && !f) { - $("body").css("padding-top", function(i, oV) { - return (parseInt(oV)+50)+"px"; - }) - } else if(!$el.hasClass("navbar-fixed-top") && f){ - $("body").css("padding-top", function(i, oV) { - return (parseInt(oV)-50)+"px"; - }) - } - }; - if(data.hasOwnProperty("inverse")) { - $el.toggleClass("navbar-inverse", data.inverse); - }; - }) +// The following function refer to tooltips but are used in the creation of +// tooltips and popovers because there structure is so similar. type="popover" +// will create a popover. -Shiny.addCustomMessageHandler("addtooltip", - function(data) { - addTooltip(id=data.id, title=data.title, placement=data.placement, trigger=data.trigger); - } -); - -Shiny.addCustomMessageHandler("removetooltip", - function(tooltipid) { - $("#"+tooltipid).tooltip("destroy"); +shinyBS.addTooltip = function(id, type, opts) { + var $id = shinyBS.getTooltipTarget(id); + var dopts = {html: true}; + opts = $.extend(opts, dopts); + + if(type == "tooltip") { + $id.tooltip("destroy"); + $id.tooltip(opts); + } else if(type == "popover") { + $id.popover("destroy"); + $id.popover(opts); } -); + +} -Shiny.addCustomMessageHandler("addpopover", - function(data) { - addPopover(id=data.id, title=data.title, content=data.content, placement=data.placement, trigger=data.trigger); - +shinyBS.removeTooltip = function(id, type) { + var $id = shinyBS.getTooltipTarget(id); + if(type == "tooltip") { + $id.tooltip("destroy"); + } else if(type == "popover") { + $id.popover("destroy"); } -); +} -Shiny.addCustomMessageHandler("removepopover", - function(popoverid) { - $("#"+popoverid).popover("destroy"); +// Makes adjustments to the tooltip and popover targets for specialized +// shiny inputs/outputs +shinyBS.getTooltipTarget = function(id) { + + var $id = $("#" + id).closest(".shiny-input-container, .shiny-bound-output, .btn, .shiny-download-link"); + +/* + if($id.hasClass("js-range-slider")) { + $id = $id.parent(); + } else if($id.hasClass("selectized")) { + $id = $id.siblings("div.selectize-control") } -); +*/ + return $id; + +} -// Table Highlighting Functions -Shiny.addCustomMessageHandler("highlightCells", - function(data) { - - var $tab = $("#"+data.id).children("table"); - var $tds = $tab.find("td"); - - if(data.skip) { - $tds = $tab.find("td:not(:first-child)"); - }; - - if(data.hasOwnProperty("column")) { - if($.isNumeric(data.column)) { - var ind = parseInt(data.column, 10); - } else { - var ind = $tab.find("tr:first-child").children("th").filter(function() { - return $.trim($(this).text()) == $.trim(data.column); - }).index(); - } - $tds = $tab.find("tr").find("td:nth-child(" + (ind + 1) + ")") - } - - if(data.hasOwnProperty("reset")) { - if(data.reset) { - $tds.removeClass().removeAttr("style"); - } - } - - if(data.hasOwnProperty("regex")) { - - $tds = $tds.filter(function() { - return this.textContent.match(data.regex); - }) - - } else { - if(data.hasOwnProperty("min")) { - $tds = $tds.filter(function() { - return parseFloat($(this).text(), 10) >= parseFloat(data.min, 10)}); - } - if(data.hasOwnProperty("max")) { - $tds = $tds.filter(function() { - return parseFloat($(this).text(), 10) <= parseFloat(data.max, 10)}); - } - } - - if(data.hasOwnProperty("class")) { - $tds.removeClass().removeAttr("style").addClass(data.class); - } - - if(data.hasOwnProperty("style")) { - $tds.removeAttr("style").attr("style", data.style); - } +Shiny.addCustomMessageHandler("updateTooltipOrPopover", function(data) { + if(data.action == "add") { + shinyBS.addTooltip(data.id, data.type, data.options); + } else if(data.action == "remove") { + shinyBS.removeTooltip(data.id, data.type) } -); +}) -Shiny.addCustomMessageHandler("highlightRows", - function(data) { +Shiny.addCustomMessageHandler("bsButtonUpdate", function(data) { + + var btn = $("button#" + data.id); + var ico = btn.find("i"); + + if(ico.length > 0) { + ico = ico[0].outerHTML; + } else { + ico = ""; + }; + + if(data.hasOwnProperty("label")) { + btn.html(ico + data.label); + }; - var $tab = $("#"+data.id).children("table"); - if($.isNumeric(data.column)) { - var ind = parseInt(data.column, 10); + if(data.hasOwnProperty("icon")) { + var ch = btn.children(); + if(ch.length == 0) { + btn.prepend(data.icon); } else { - var ind = $tab.find("tr:first-child").children("th").filter(function() { - return $.trim($(this).text()) == $.trim(data.column); - }).index(); - } - - var $trs = $tab.find("tr:not(:first-child)") - - if(data.hasOwnProperty("reset")) { - if(data.reset) { - $trs.removeClass().removeAttr("style"); - $trs.children("td").removeClass().removeAttr("style") - } - } - - if(data.hasOwnProperty("regex")) { - - $trs = $trs.filter(function() { - return $(this).children("td").eq(ind).get(0).textContent.match(data.regex); - }) - + btn.find("i").replaceWith(data.icon); + }; + }; + + if(data.hasOwnProperty("value")) { + if(btn.hasClass("sbs-toggle-button")) { + if(data.value != btn.hasClass("active")) { + btn.trigger("click"); + }; + }; + }; + + if(data.hasOwnProperty("style")) { + btn + .removeClass("btn-default btn-primary btn-success btn-info btn-warning btn-danger btn-link") + .addClass("btn-" + data.style); + }; + + if(data.hasOwnProperty("size")) { + btn.removeClass("btn-lg btn-sm btn-xs") + if(data.size != "default") { + btn.addClass(data.size); + }; + }; + + if(data.hasOwnProperty("block")) { + btn.toggleClass("btn-block", data.block); + }; + + if(data.hasOwnProperty("disabled")) { + if(data.disabled) { + btn.attr("disabled", "disabled") } else { - - if(data.hasOwnProperty("min")) { - $trs = $trs.filter(function() { - return parseFloat($(this).children("td").eq(ind).text(), 10) >= parseFloat(data.min, 10)}); - } - - if(data.hasOwnProperty("max")) { - $trs = $trs.filter(function() { - return parseFloat($(this).children("td").eq(ind).text(), 10) <= parseFloat(data.max, 10)}); - } - - } - - if(data.hasOwnProperty("class")) { - $trs.children("td").removeClass().removeAttr("style"); - $trs.removeClass().removeAttr("style").addClass(data.class); - } - if(data.hasOwnProperty("style")) { - $trs.children("td").removeAttr("style"); - $trs.removeAttr("style").attr("style", data.style); - } - + btn.attr("disabled", false) + }; + }; + }) \ No newline at end of file diff --git a/inst/www/typeahead_inputbinding.js b/inst/www/typeahead_inputbinding.js new file mode 100644 index 0000000..042bb05 --- /dev/null +++ b/inst/www/typeahead_inputbinding.js @@ -0,0 +1,69 @@ +//Creates input binding for TypeAhead Objects +var typeAheadBinding = new Shiny.InputBinding(); +$.extend(typeAheadBinding, { + find: function(scope) { + return $(scope).find('.typeahead'); + }, + getId: function(el) { + return Shiny.InputBinding.prototype.getId.call(this, el) || el.name; + }, + getValue: function(el) { + return el.value; + }, + setValue: function(el, value) { + el.value = value; + }, + initialize: function(el) { + $(el).typeahead(); + }, + subscribe: function(el, callback) { + $(el).on('keyup.typeAheadBinding input.typeAheadBinding', function(event) { + callback(true); + }); + $(el).on('change.typeAheadBinding', function(event) { + callback(false); + }); + }, + unsubscribe: function(el) { + $(el).off('.typeAheadBinding'); + }, + receiveMessage: function(el, data) { + if (data.hasOwnProperty('value')) { + this.setValue(el, data.value); + }; + if (data.hasOwnProperty('label')) { + $(el).parent().find('label[for=' + el.id + ']').text(data.label); + }; + if (data.hasOwnProperty('choices')) { + $(el).data('typeahead').source = data.choices; + }; + $(el).trigger('change'); + }, + getState: function(el) { + return { + label: $(el).parent().find('label[for=' + el.id + ']').text(), + value: el.value + }; + }, + getRatePolicy: function() { + return { + policy: 'debounce', + delay: 250 + }; + } +}); +Shiny.inputBindings.register(typeAheadBinding); + +Shiny.addCustomMessageHandler("typeaheadUpdate", function(data) { + var typeahead = $("input#" + data.id); + if (data.hasOwnProperty('value')) { + typeahead[0].value = data.value; + }; + if (data.hasOwnProperty('label')) { + typeahead.parent().find('label[for=' + data.id + ']').text(data.label); + }; + if (data.hasOwnProperty('choices')) { + typeahead.data('typeahead').source = data.choices; + }; + typeahead.trigger('change'); +}) \ No newline at end of file diff --git a/man-roxygen/footer.R b/man-roxygen/footer.R new file mode 100644 index 0000000..17615e5 --- /dev/null +++ b/man-roxygen/footer.R @@ -0,0 +1,8 @@ +#'@seealso \href{http://getbootstrap.com}{Twitter Bootstrap 3} +#' +#'@note +#' Run \code{bsExample("<%=family_name %>")} for an example +#' of \code{<%=item_name %>} functionality. +#' +#'@family <%=family_name %> +#'@name <%=item_name %> diff --git a/man-roxygen/item_details.R b/man-roxygen/item_details.R new file mode 100644 index 0000000..7bfbed0 --- /dev/null +++ b/man-roxygen/item_details.R @@ -0,0 +1,3 @@ +#'@details +#'See \link{<%=family_name %>} for more information about how to use \code{<%=item_name %>} with the +#'rest of the <%=family_name %> family. diff --git a/man/Alerts.Rd b/man/Alerts.Rd new file mode 100644 index 0000000..9c6c1be --- /dev/null +++ b/man/Alerts.Rd @@ -0,0 +1,96 @@ +% Generated by roxygen2 (4.1.0): do not edit by hand +% Please edit documentation in R/Alerts.R +\name{Alerts} +\alias{Alerts} +\title{Alerts} +\description{ +Alerts allow you to communicate information to the user on the fly. Standard +Bootstrap styling options give the user a hint at the type of information +contained in the Alert. +} +\details{ +To create alerts in your Shiny app you must place \code{bsAlert} in your ui. +This serves as an anchor that tells shinyBS where to place the alerts created +with \code{createAlert}. + +Use \code{createAlert} in your server script to add alerts to the anchor +you created with \code{bsAlert} in your ui. You can place \code{createAlert} +in observers, reactives, or outputs. A common usage may be to have logic that +validates a user's inputs. If they are valid produce the requested output, if +not use \code{createAlert} to give the user info about what they need to +change. +} +\note{ +Run \code{bsExample("Alerts")} for an example +of \code{Alerts} functionality. +} +\section{Components}{ + +There are three functions in the Alerts family: + \describe{ + \item{\code{\link{bsAlert}}}{Used in the UI to create an anchor where your + Alerts will be displayed.} + \item{\code{\link{createAlert}}}{Used in the Server logic to create + alerts. This would be used within a reactive context to display error + or success messages to the user based on the status of that context.} + \item{\code{\link{closeAlert}}}{Used in the Server logic to close an alert + that is already open. By default, Alerts are dismissable by the user, + but this offers you a way to close them programmatically.} + } +} + +\section{Changes}{ + +\code{style} was called \code{type} in previous versions of shinyBS. + +\code{anchorId} was called \code{inputId} in previous versions of shinyBS. + +\code{content} was called \code{message} in previous versions of shinyBS. +} +\examples{ +library(shiny) +library(shinyBS) +app = shinyApp( + ui = + fluidPage( + sidebarLayout( + sidebarPanel(textInput("num1", NULL, value = 100), + "divided by", textInput("num2", NULL, value = 20), + "equals", textOutput("exampleOutput")), + mainPanel( + bsAlert("alert") + ) + ) + ), + server = + function(input, output, session) { + output$exampleOutput <- renderText({ + num1 <- as.numeric(input$num1) + num2 <- as.numeric(input$num2) + + if(is.na(num1) | is.na(num2)) { + createAlert(session, "alert", "exampleAlert", title = "Oops", + content = "Both inputs should be numeric.", append = FALSE) + } else if(num2 == 0) { + createAlert(session, "alert", "exampleAlert", title = "Oops", + content = "You cannot divide by 0.", append = FALSE) + } else { + closeAlert(session, "exampleAlert") + return(num1/num2) + } + + }) + } +) + +\dontrun{ + runApp(app) +} +} +\seealso{ +\href{http://getbootstrap.com}{Twitter Bootstrap 3} + +Other Alerts: \code{\link{bsAlert}}; + \code{\link{closeAlert}}; \code{\link{createAlert}} +} + diff --git a/man/Buttons.Rd b/man/Buttons.Rd new file mode 100644 index 0000000..d1c773a --- /dev/null +++ b/man/Buttons.Rd @@ -0,0 +1,130 @@ +% Generated by roxygen2 (4.1.0): do not edit by hand +% Please edit documentation in R/Buttons.R +\name{Buttons} +\alias{Buttons} +\title{Buttons} +\description{ +Twitter Bootstrap gives many options for styling buttons that aren't made +available by standard Shiny. Use shinyBS to create buttons of different sizes, +shapes, and colors. +} +\details{ +Create a button in the UI with \code{\link{bsButton}}. If \code{type = "action"} +the button will behave like the standard \code{\link{actionButton}} in shiny. +If \code{type = "toggle"} the button will behave like a \code{\link{checkboxInput}} +with an on and off state. It will return \code{TRUE} or \code{FALSE} to the Server +depending on its state. + +You can update the style and state of a \code{\link{bsButton}} from the Server +logic with \code{\link{updateButton}}. For example, a button could be set to +\code{disabled = TRUE} until the user has made some other selections, then once +those selections have been made, an observer on the Server could use \code{\link{updateButton}} +to enable the button allowing the user to proceed. Alternatively, you could set +the button to \code{style = "success"} to let them know that the button is ready +to be clicked. +} +\note{ +Run \code{bsExample("Buttons")} for an example +of \code{Buttons} functionality. +} +\section{Components}{ + +There are two functions in the Buttons family: + \describe{ + \item{\code{\link{bsButton}}}{Used in the UI to create a button. Buttons + can be of the type \code{action} or \code{toggle}.} + \item{\code{\link{updateButton}}}{Used in the Server logic to modify the + state of a button created with \code{\link{bsButton}}} + } +} + +\section{Changes}{ + +\code{bsActionButton} and \code{bsToggleButton} were replaced with just +\code{\link{bsButton}} with a \code{type} argument. + +\code{icon} was added to allow placing an icon in the button. +} +\examples{ +library(shiny) +library(shinyBS) +app = shinyApp( + ui = + fluidPage( + sidebarLayout( + sidebarPanel( + sliderInput("bins", + "Move the slider to see its effect on the button below:", + min = 1, + max = 50, + value = 1), + bsButton("actTwo", label = "Click me if you dare!", icon = icon("ban")), + tags$p("Clicking the first button below changes the disabled state of the second button."), + bsButton("togOne", label = "Toggle button disabled status", + block = TRUE, type = "toggle", value = TRUE), + bsButton("actOne", label = "Block Action Button", block = TRUE) + + ), + mainPanel( + textOutput("exampleText") + ) + ) + ), + server = + function(input, output, session) { + observeEvent(input$togOne, ({ + updateButton(session, "actOne", disabled = !input$togOne) + })) + observeEvent(input$bins, ({ + + b <- input$bins + disabled = NULL + style = "default" + icon = "" + + if(b < 5) { + disabled = TRUE + icon <- icon("ban") + } else { + disabled = FALSE + } + + if(b < 15 | b > 35) { + style = "danger" + } else if(b < 20 | b > 30) { + style = "warning" + } else { + style = "default" + icon = icon("check") + } + + updateButton(session, "actTwo", disabled = disabled, style = style, icon = icon) + + })) + + output$exampleText <- renderText({ + input$actTwo + b <- isolate(input$bins) + txt = "" + if((b > 5 & b < 15) | b > 35) { + txt = "That was dangerous." + } else if((b > 5 & b < 20) | b > 30) { + txt = "I warned you about that." + } else if(b >= 20 & b <= 30) { + txt = "You have chosen... wisely." + } + return(txt) + }) + } +) +\dontrun{ + runApp(app) +} +} +\seealso{ +\href{http://getbootstrap.com}{Twitter Bootstrap 3} + +Other Buttons: \code{\link{bsButton}}; + \code{\link{updateButton}} +} + diff --git a/man/Collapses.Rd b/man/Collapses.Rd new file mode 100644 index 0000000..c348f66 --- /dev/null +++ b/man/Collapses.Rd @@ -0,0 +1,86 @@ +% Generated by roxygen2 (4.1.0): do not edit by hand +% Please edit documentation in R/Collapses.R +\name{Collapses} +\alias{Collapses} +\title{Collapses} +\description{ +Collapse panels allow you to reduce clutter in your Shiny app by making +panels of information that open and close with a user's click. Any type of +content can go in a collapse panel. Standard Bootstrap styling options are +available. +} +\details{ +Collapses are designed to mimic \code{\link{tabsetPanel}} in their implementation. +Start with \code{bsCollapse} to create a panel group, then fill it with panels +using \code{bsCollapsePanel}. + +\code{bsCollapse} acts as an input, so you can retrieve which panels are open +from the input object passed to the function in \code{\link{shinyServer}}. + +\code{updateCollapse} can be used within your server logic to open/close +collapse panels or to change their style. +} +\note{ +Run \code{bsExample("Collapses")} for an example +of \code{Collapses} functionality. +} +\section{Components}{ + +\describe{ + \item{\code{\link{bsCollapse}}}{A container for holder the individual panels created by \code{\link{bsCollapsePanel}}.} + \item{\code{\link{bsCollapsePanel}}}{Creates an individual Collapse Panel that resides within a \code{\link{bsCollapse}}.} + \item{\code{\link{updateCollapse}}}{Used within your server logic to open/close collapse panels or change their style.} +} +} + +\section{Changes}{ + +\code{style} is a new option that wasn't available in previous versions of +shinyBS. +} +\examples{ +library(shiny) +library(shinyBS) + +app = shinyApp( + ui = + fluidPage( + sidebarLayout( + sidebarPanel(HTML("This button will open Panel 1 using updateCollapse."), + actionButton("p1Button", "Push Me!"), + selectInput("styleSelect", "Select style for Panel 1", + c("default", "primary", "danger", "warning", "info", "success")) + ), + mainPanel( + bsCollapse(id = "collapseExample", open = "Panel 2", + bsCollapsePanel("Panel 1", "This is a panel with just text ", + "and has the default style. You can change the style in ", + "the sidebar.", style = "info"), + bsCollapsePanel("Panel 2", "This panel has a generic plot. ", + "and a 'success' style.", plotOutput("genericPlot"), style = "success") + ) + ) + ) + ), + server = + function(input, output, session) { + output$genericPlot <- renderPlot(plot(rnorm(100))) + observeEvent(input$p1Button, ({ + updateCollapse(session, "collapseExample", open = "Panel 1") + })) + observeEvent(input$styleSelect, ({ + updateCollapse(session, "collapseExample", style = list("Panel 1" = input$styleSelect)) + })) + } +) +\dontrun{ + runApp(app) +} +} +\seealso{ +\href{http://getbootstrap.com}{Twitter Bootstrap 3} + +Other Collapses: \code{\link{bsCollapsePanel}}; + \code{\link{bsCollapse}}; \code{\link{updateCollapse}} +} + diff --git a/man/Modals.Rd b/man/Modals.Rd new file mode 100644 index 0000000..bcdda74 --- /dev/null +++ b/man/Modals.Rd @@ -0,0 +1,108 @@ +% Generated by roxygen2 (4.1.0): do not edit by hand +% Please edit documentation in R/Modals.R +\name{Modals} +\alias{Modals} +\title{Modals} +\description{ +Modal windows are similar to popups but are rendered within the +original window. They can contain any combination of shiny inputs, shiny +outputs, and html. Possible uses include extra controls that you don't want +cluttering up the main app display or help pages to explain your apps +operation. +} +\details{ +Use \code{\link{bsModal}} in your UI to create a modal window. It works +like \code{\link{Collapses}} or \code{\link{tabPanel}}, any non-named arguments +will be passed as content for the modal. + +Create a button or link and assign its \code{inputId} as the \code{trigger} +in \code{\link{bsModal}}. +} +\note{ +Run \code{bsExample("Modals")} for an example +of \code{Modals} functionality. +} +\section{Components}{ + +There are only two functions in the Modals family: + \describe{ + \item{\code{\link{bsModal}}}{Used in the UI to create a modal window.} + \item{\code{\link{toggleModal}}}{Used in the Server logic to open or + close a modal window programmatically.} + } +} + +\section{Changes}{ + +There is now a \code{toggle} argument in \code{\link{toggleModal}} that allows +you to specify whether you want the modal to open or close. + +The \code{size} argument in \code{\link{bsModal}} allows you to specify the +size of the modal window. Either \code{small} or \code{large}. +} +\examples{ +library(shiny) +library(shinyBS) + +app = shinyApp( + ui = + fluidPage( + sidebarLayout( + sidebarPanel( + sliderInput("bins", + "Number of bins:", + min = 1, + max = 50, + value = 30), + actionButton("tabBut", "View Table") + ), + + mainPanel( + plotOutput("distPlot"), + bsModal("modalExample", "Data Table", "tabBut", size = "large", + dataTableOutput("distTable")) + ) + ) + ), + server = + function(input, output, session) { + + output$distPlot <- renderPlot({ + + x <- faithful[, 2] + bins <- seq(min(x), max(x), length.out = input$bins + 1) + + # draw the histogram with the specified number of bins + hist(x, breaks = bins, col = 'darkgray', border = 'white') + + }) + + output$distTable <- renderDataTable({ + + x <- faithful[, 2] + bins <- seq(min(x), max(x), length.out = input$bins + 1) + + # draw the histogram with the specified number of bins + tab <- hist(x, breaks = bins, plot = FALSE) + tab$breaks <- sapply(seq(length(tab$breaks) - 1), function(i) { + paste0(signif(tab$breaks[i], 3), "-", signif(tab$breaks[i+1], 3)) + }) + tab <- as.data.frame(do.call(cbind, tab)) + colnames(tab) <- c("Bins", "Counts", "Density") + return(tab[, 1:3]) + + }, options = list(pageLength=10)) + + } +) +\dontrun{ + runApp(app) +} +} +\seealso{ +\href{http://getbootstrap.com}{Twitter Bootstrap 3} + +Other Modals: \code{\link{bsModal}}; + \code{\link{toggleModal}} +} + diff --git a/man/Tooltips_and_Popovers.Rd b/man/Tooltips_and_Popovers.Rd new file mode 100644 index 0000000..1520004 --- /dev/null +++ b/man/Tooltips_and_Popovers.Rd @@ -0,0 +1,132 @@ +% Generated by roxygen2 (4.1.0): do not edit by hand +% Please edit documentation in R/Tooltips_and_Popovers.R +\name{Tooltips_and_Popovers} +\alias{Tooltips_and_Popovers} +\title{Tooltips and Popovers} +\description{ +Tooltips and Popovers allow you to add additional information about controls +or outputs without cluttering up your user interface. You can add a tooltip to +a button that displays on hover and better explains what the button will do, or +you could add a popover to an output providing further analysis of that output. +} +\details{ +You can create tooltips and popovers from either the UI script or within the +Server logic. \code{\link{bsTooltip}} and \code{\link{bsPopover}} are used in +the UI, and \code{\link{addTooltip}} and \code{\link{addPopover}} are used in +the Server logic. \code{\link{tipify}} and \code{\link{popify}} can be used +within the UI or from within a \code{\link{renderUI}} in the Server logic. They +also have the added advantage of not requiring that the UI element have an ID +attribute. +} +\note{ +Tooltips and Popovers cannot contain shiny inputs or outputs. + +There must be at least one \code{shinyBS} component in the UI of your +app in order for the necessary dependencies to be loaded. Because of this, +\code{\link{addTooltip}} and \code{\link{addPopover}} will not work if they +are the only shinyBS components in your app. + +Tooltips and popovers may not work on some of the more complex shiny inputs +or outputs. If you encounter a problem with tooltips or popovers not appearing +please file a issue on the github page so I can fix it. + +Run \code{bsExample("Tooltips_and_Popovers")} for an example +of \code{Tooltips_and_Popovers} functionality. +} +\section{Components}{ + +There are eight functions in the Tooltips and Popovers family: + \describe{ + \item{\code{\link{bsTooltip}}}{Used in the UI to add a tooltip to an element + in your UI.} + \item{\code{\link{bsPopover}}}{Used in the UI to add a popover to an element + in your UI.} + \item{\code{\link{tipify}}}{Wrap any UI element in \code{tipify} to add a + tooltip to the wrapped element. Preferred for elemented created with + \code{\link{renderUI}}.} + \item{\code{\link{popify}}}{Wrap any UI element in \code{popify} to add a + popover to the wrapped element. Preferred for elements created with + \code{\link{renderUI}}.} + \item{\code{\link{addTooltip}}}{Used in the Server logic to add a tooltip + to an element in your UI.} + \item{\code{\link{addPopover}}}{Used in the Server logic to add a popover + to an element in your UI.} + \item{\code{\link{removeTooltip}}}{Used in the Server logic to remove a + tooltip from an element in your UI.} + \item{\code{\link{removePopover}}}{Used in the Server logic to remove a + popover from an element in your UI.} + } +} + +\section{Changes}{ + +An \code{options} argument has been added to the creation functions to allow +advanced users more control over how the tooltips and popovers appear. See +the \href{http://getbootstrap.com}{Twitter Bootstrap 3 documentation} for more +details. +} +\examples{ +library(shiny) +library(shinyBS) + +app = shinyApp( + ui = + fluidPage( + sidebarLayout( + sidebarPanel( + sliderInput("bins", + "Number of bins:", + min = 1, + max = 50, + value = 30), + bsTooltip("bins", "The wait times will be broken into this many equally spaced bins", + "right", options = list(container = "body")) + ), + mainPanel( + plotOutput("distPlot"), + uiOutput("uiExample") + ) + ) + ), + server = + function(input, output, session) { + output$distPlot <- renderPlot({ + + # generate bins based on input$bins from ui.R + x <- faithful[, 2] + bins <- seq(min(x), max(x), length.out = input$bins + 1) + + # draw the histogram with the specified number of bins + hist(x, breaks = bins, col = 'darkgray', border = 'white') + + }) + output$uiExample <- renderUI({ + tags$span( + popify(bsButton("pointlessButton", "Button", style = "primary", size = "large"), + "A Pointless Button", + "This button is pointless. It does not do anything!"), + tipify(bsButton("pB2", "Button", style = "inverse", size = "extra-small"), + "This button is pointless too!") + ) + }) + addPopover(session, "distPlot", "Data", content = paste0("

    Waiting time between ", + "eruptions and the duration of the eruption for the Old Faithful geyser ", + "in Yellowstone National Park, Wyoming, USA.

    Azzalini, A. and ", + "Bowman, A. W. (1990). A look at some data on the Old Faithful geyser. ", + "Applied Statistics 39, 357-365.

    "), trigger = 'click') + } +) +\dontrun{ + runApp(app) +} +} +\seealso{ +\href{http://getbootstrap.com}{Twitter Bootstrap 3} + +Other Tooltips_and_Popovers: \code{\link{addPopover}}; + \code{\link{addTooltip}}; \code{\link{bsPopover}}; + \code{\link{bsTooltip}}; \code{\link{popify}}; + \code{\link{removePopover}}; \code{\link{removeTooltip}}; + \code{\link{tipify}} +} + diff --git a/man/addPopover.Rd b/man/addPopover.Rd new file mode 100644 index 0000000..36b3c6d --- /dev/null +++ b/man/addPopover.Rd @@ -0,0 +1,48 @@ +% Generated by roxygen2 (4.1.0): do not edit by hand +% Please edit documentation in R/addPopover.R +\name{addPopover} +\alias{addPopover} +\title{addPopover} +\usage{ +addPopover(session, id, title, content, placement = "bottom", + trigger = "hover", options = NULL) +} +\arguments{ +\item{session}{The session object passed to function given to shinyServer.} + +\item{id}{The id of the element to attach the popover to.} + +\item{title}{The title of the popover.} + +\item{content}{The main content of the popover.} + +\item{placement}{Where the popover should appear relative to its target +(\code{top}, \code{bottom}, \code{left}, or \code{right}). Defaults to \code{bottom}.} + +\item{trigger}{What action should cause the popover to appear? (\code{hover}, +\code{focus}, \code{click}, or \code{manual}). Defaults to \code{hover}.} + +\item{options}{A named list of additional options to be set on the popover.} +} +\description{ +\code{addPopover} is used within the Server logic of an app to add a popover to a Shiny +input or output. +} +\details{ +See \link{Tooltips_and_Popovers} for more information about how to use \code{addPopover} with the +rest of the Tooltips_and_Popovers family. +} +\note{ +Run \code{bsExample("Tooltips_and_Popovers")} for an example +of \code{addPopover} functionality. +} +\seealso{ +\href{http://getbootstrap.com}{Twitter Bootstrap 3} + +Other Tooltips_and_Popovers: \code{\link{Tooltips_and_Popovers}}; + \code{\link{addTooltip}}; \code{\link{bsPopover}}; + \code{\link{bsTooltip}}; \code{\link{popify}}; + \code{\link{removePopover}}; \code{\link{removeTooltip}}; + \code{\link{tipify}} +} + diff --git a/man/addTooltip.Rd b/man/addTooltip.Rd new file mode 100644 index 0000000..7049d87 --- /dev/null +++ b/man/addTooltip.Rd @@ -0,0 +1,46 @@ +% Generated by roxygen2 (4.1.0): do not edit by hand +% Please edit documentation in R/addTooltip.R +\name{addTooltip} +\alias{addTooltip} +\title{addTooltip} +\usage{ +addTooltip(session, id, title, placement = "bottom", trigger = "hover", + options = NULL) +} +\arguments{ +\item{session}{The session object passed to function given to shinyServer.} + +\item{id}{The id of the element to attach the tooltip to.} + +\item{title}{The content of the tooltip.} + +\item{placement}{Where the tooltip should appear relative to its target +(\code{top}, \code{bottom}, \code{left}, or \code{right}). Defaults to \code{"bottom"}.} + +\item{trigger}{What action should cause the tooltip to appear? (\code{hover}, +\code{focus}, \code{click}, or \code{manual}). Defaults to \code{"hover"}.} + +\item{options}{A named list of additional options to be set on the tooltip.} +} +\description{ +\code{addTooltip} is used within the Server logic of an app to add a tooltip to a Shiny +input or output. +} +\details{ +See \link{Tooltips_and_Popovers} for more information about how to use \code{addTooltip} with the +rest of the Tooltips_and_Popovers family. +} +\note{ +Run \code{bsExample("Tooltips_and_Popovers")} for an example +of \code{addTooltip} functionality. +} +\seealso{ +\href{http://getbootstrap.com}{Twitter Bootstrap 3} + +Other Tooltips_and_Popovers: \code{\link{Tooltips_and_Popovers}}; + \code{\link{addPopover}}; \code{\link{bsPopover}}; + \code{\link{bsTooltip}}; \code{\link{popify}}; + \code{\link{removePopover}}; \code{\link{removeTooltip}}; + \code{\link{tipify}} +} + diff --git a/man/alert.Rd b/man/alert.Rd deleted file mode 100644 index 763a124..0000000 --- a/man/alert.Rd +++ /dev/null @@ -1,92 +0,0 @@ -\name{createAlert} -\alias{bsAlert} -\alias{createAlert} -\alias{closeAlert} -\title{ - Twitter Bootstrap Alerts -} -\description{ - Functions to add and remove Twitter Bootstrap alerts in Shiny -} -\usage{ -bsAlert(inputId) - -createAlert(session, inputId, alertId = NULL, title = NULL, message = NULL, - type = NULL, dismiss = TRUE, block = NULL, append = TRUE) - -closeAlert(session, alertId) -} - -\arguments{ - \item{session}{ - The \code{session} object passed to function given to \code{shinyServer} - } - \item{inputId}{ - Id of alert anchor to create alert in - } - \item{alertId}{ - An id for the created alert. Optional, but necessary if you want to close - it later with \code{closeAlert} - } - \item{title}{ - A title for the alert. This text will be at the top of the alert and be in - larger, bold font - } - \item{message}{ - The main text of the alert - } - \item{type}{ - One of four options: \code{warning}, \code{danger}, \code{info}, or - /code{success} - } - \item{dismiss}{ - Should the user be able to dismiss the alert? \code{logical} - } - \item{block}{ - Should block formatting be applied to the alert? \code{logical} - } - \item{append}{ - Should the alert be added below other alerts already in the alert anchor - (\code{TRUE}), or should it replace and already existing alerts (\code{FALSE}) - } -} - -\details{ - By default each new alert will be added below any previously existing alerts. - If you want only one alert to appear at a time change \code{append} to - \code{FALSE}. This will cause new alerts to overwrite any previously existing - alerts. \cr \cr - Block style is an option discussed in the Twitter Bootstrap documentation, - though it doesn't make any difference that the author can see. -} - -\references{ - \href{http://getbootstrap.com/2.3.2/components.html}{Alerts for Twitter Bootstrap 2.3.2} -} - -\author{ -Eric Bailey -} - -\note{ - Run \code{bsDemo()} for a live example of alerts. -} - - -\examples{ -\dontrun{ - - ## In ui.R - ## Create an alert anchor: - bsAlert(inputId="aa") - - ## In server.R - ## Add an alert to the previously created alert anchor: - createAlert(inputId = "aa", alertId="a1", - title = "Oops!", - message="Something isn't right, please recheck your inputs.", - type = "danger") - ## Close the alert programatically - closeAlert(session, alertId = "a1") -} -} diff --git a/man/bsAlert.Rd b/man/bsAlert.Rd new file mode 100644 index 0000000..351fe5e --- /dev/null +++ b/man/bsAlert.Rd @@ -0,0 +1,30 @@ +% Generated by roxygen2 (4.1.0): do not edit by hand +% Please edit documentation in R/bsAlert.R +\name{bsAlert} +\alias{bsAlert} +\title{bsAlert} +\usage{ +bsAlert(anchorId) +} +\arguments{ +\item{anchorId}{A unique id the identifies the anchor.} +} +\description{ +\code{bsAlert} creates an anchor point in your UI definition. This anchor point +is where alerts created in your Server logic will be displayed. +} +\details{ +See \link{Alerts} for more information about how to use \code{bsAlert} with the +rest of the Alerts family. +} +\note{ +Run \code{bsExample("Alerts")} for an example +of \code{bsAlert} functionality. +} +\seealso{ +\href{http://getbootstrap.com}{Twitter Bootstrap 3} + +Other Alerts: \code{\link{Alerts}}; + \code{\link{closeAlert}}; \code{\link{createAlert}} +} + diff --git a/man/bsButton.Rd b/man/bsButton.Rd new file mode 100644 index 0000000..517fcf9 --- /dev/null +++ b/man/bsButton.Rd @@ -0,0 +1,54 @@ +% Generated by roxygen2 (4.1.0): do not edit by hand +% Please edit documentation in R/bsButton.R +\name{bsButton} +\alias{bsButton} +\title{bsButton} +\usage{ +bsButton(inputId, label, icon = NULL, ..., style = "default", + size = "default", type = "action", block = FALSE, disabled = FALSE, + value = FALSE) +} +\arguments{ +\item{inputId}{Specifies the input slot that will be used to access the +value.} + +\item{label}{The contents of the button or link--usually a text label, but +you could also use any other HTML, like an image.} + +\item{icon}{An optional \code{\link{icon}} to appear on the button.} + +\item{...}{Named attributes to be applied to the button or link.} + +\item{style}{A Bootstrap style to apply to the button. (\code{default}, \code{primary}, +\code{success}, \code{info}, \code{warning}, or \code{danger})} + +\item{size}{The size of the button (\code{extra-small}, \code{small}, +\code{default}, or \code{large})} + +\item{type}{The type of button to create. (\code{action} or \code{toggle})} + +\item{block}{\bold{logical} Should the button take the full width of the parent element?} + +\item{disabled}{\bold{logical} Should the button be disabled (un-clickable)?} + +\item{value}{\bold{logical} If \code{type = "toggle"}, the initial value of the button.} +} +\description{ +\code{bsButton} is used in your UI script to create customizable action and toggle +buttons. +} +\details{ +See \link{Buttons} for more information about how to use \code{bsButton} with the +rest of the Buttons family. +} +\note{ +Run \code{bsExample("Buttons")} for an example +of \code{bsButton} functionality. +} +\seealso{ +\href{http://getbootstrap.com}{Twitter Bootstrap 3} + +Other Buttons: \code{\link{Buttons}}; + \code{\link{updateButton}} +} + diff --git a/man/bsButtons.Rd b/man/bsButtons.Rd deleted file mode 100644 index 31c85a3..0000000 --- a/man/bsButtons.Rd +++ /dev/null @@ -1,119 +0,0 @@ -\name{Button Customizations} -\alias{bsButtonGroup} -\alias{bsActionButton} -\alias{bsButton} -\alias{bsButtonGroup} -\alias{bsToggleButton} -\alias{updateButton} -\alias{updateButtonGroup} - -\title{ - Shiny Button Customizations -} -\description{ - Functions for setting and changing the style, size, and state of various - buttons in a shiny app. -} -\usage{ -bsButton(inputId, label, value, style = NULL, size = NULL, block = FALSE, - disabled = FALSE) -bsActionButton(inputId, label, style = NULL, size = NULL, block = FALSE, - disabled = FALSE) -bsToggleButton(inputId, label, value, style = NULL, size = NULL, block = FALSE, - disabled = FALSE) -bsButtonGroup(inputId, ..., label, toggle = "checkbox", style, size, - value = NULL, disabled = FALSE, block = FALSE, vertical = FALSE) -updateButton(session, id, label = NULL, value = NULL, style = NULL, size = NULL, - block = NULL, disabled = NULL) -updateButtonGroup(session, id, toggle = NULL, style = NULL, size = NULL, - disabled = NULL, value = NULL) -} -%- maybe also 'usage' for other objects documented here. -\arguments{ - \item{session}{ - The \code{session} object passed to function given to \code{shinyServer} - } - \item{inputId}{ - Id to assign to the button or button group -} - \item{id}{ - The id of the button/button group you want to update - } - \item{\dots}{ - \code{bsButton()} objects to be added to the button group -} - \item{label}{ - For buttons, the text to appear inside the button. For button groups, an - optional label that will appear above the button group -} - \item{toggle}{ - The type of toggle behaviour the button group should have (See Details) -} - \item{style}{ - The bootstrap style the button(s) should take (See Details) -} - \item{size}{ - The bootstrap size the button(s) should take (See Details) -} - \item{block}{ - Should the button or button group be a block level element? (i.e., should it - span the width of its parent element) -} - \item{vertical}{ - Should the button group's buttons have a vertical orientation? - } - \item{value}{ - The value of the button/button group (See Details) -} - \item{disabled}{ - Should the button(s) be disabled? \code{logical} -} -} -\details{ - -\code{bsActionButton()} creates an action button that behaves just as a standard shiny action button does. It has the added functionality of being able to changed its style and size. It can also be disabled/enabled.\cr - -\code{toggle} can take a value of either \code{radio} or \code{checkbox}. \code{radio} will allow only one button in the button group to be selected at a time. \code{checkbox} will allow any number of buttons to be selected at a time. \cr - -\code{style} can be any of the styles described in the Twitter Bootstrap 2.3.2 documentation. Acceptable values are currently: primary, info, success, warning, danger, inverse, or link. Additionally, when calling one of the update functions, style can be set to \code{default} to return to the default button style.\cr - -\code{size} can be any of the sizes described in the Twitter Bootstrap 2.3.2 documentation. Accepatble values are currently: large, small, or mini. Additionally, when calling one of the update functions, style can be set to \code{default} to return to the default size.\cr - -For toggle buttons, \code{value} can be \code{TRUE} or \code{FALSE} and corresponds to whether the button is currently 'clicked.' For \code{bsButton}, \code{value} is used to set the value that will be returned by containing \code{bsButtonGroup} object when the button is clicked. For button groups, \code{value} is used to set the current value to be returned by the group and should correspond to values assigned to buttons contained in the button group.\cr - -\code{vertical} and \code{block} for button groups are experimental. They do not work well together and may not work under all browsers. -} - -\references{ - \href{http://getbootstrap.com/2.3.2/components.html}{Alerts for Twitter Bootstrap 2.3.2} -} - -\author{ -Eric Bailey -} - -\note{ - Run \code{bsDemo()} for a live example of alerts. -} - -\examples{ -\dontrun{ - - # Create an action button, toggle button and a button group - # with three buttons with default styling in ui.R - bsActionButton("ab1", label = "bsActionButton"), - bsToggleButton("tb1", label = "bsToggleButton"), tags$p(), - bsButtonGroup("btngrp1", label = "bsButtonGroup", toggle = "radio", value = "right", - bsButton("btn1", label = "Left", value = "left"), - bsButton("btn2", label = "Middle", value = "middle"), - bsButton("btn3", label = "Right", value = "right") - ) - - # Update the previous buttons/button group to be small - # and of primary style in server.R - updateButton(session, "ab1", style = "primary", size = "small") - updateButton(session, "tb1", style = "primary", size = "small") - updateButtonGroup(session, "btngrp1", style = "primary", size = "small") -} -} - diff --git a/man/bsCollapse.Rd b/man/bsCollapse.Rd new file mode 100644 index 0000000..8d887df --- /dev/null +++ b/man/bsCollapse.Rd @@ -0,0 +1,40 @@ +% Generated by roxygen2 (4.1.0): do not edit by hand +% Please edit documentation in R/bsCollapse.R +\name{bsCollapse} +\alias{bsCollapse} +\title{bsCollapse} +\usage{ +bsCollapse(..., id = NULL, multiple = FALSE, open = NULL) +} +\arguments{ +\item{id}{\bold{Optional} You can use \code{input$id} in your Server logic to +determine which panels are open, and \code{\link{updateCollapse}} to open/close +panels.} + +\item{multiple}{Can more than one panel be open at a time? Defaults to \code{FALSE}.} + +\item{open}{The \code{value}, (or if none was supplied, the \code{title}) of +the panel(s) you want open on load.} + +\item{\dots}{\code{\link{bsCollapsePanel}} elements to include in the Collapse.} +} +\description{ +\code{bsCollapse} is used in your UI to create a collapse panel group. Use +\code{\link{bsCollapsePanel}} to populate this object with panels. +} +\details{ +See \link{Collapses} for more information about how to use \code{bsCollapse} with the +rest of the Collapses family. +} +\note{ +Run \code{bsExample("Collapses")} for an example +of \code{bsCollapse} functionality. +} +\seealso{ +\href{http://getbootstrap.com}{Twitter Bootstrap 3} + +Other Collapses: \code{\link{Collapses}}; + \code{\link{bsCollapsePanel}}; + \code{\link{updateCollapse}} +} + diff --git a/man/bsCollapsePanel.Rd b/man/bsCollapsePanel.Rd new file mode 100644 index 0000000..2f1d410 --- /dev/null +++ b/man/bsCollapsePanel.Rd @@ -0,0 +1,35 @@ +% Generated by roxygen2 (4.1.0): do not edit by hand +% Please edit documentation in R/bsCollapsePanel.R +\name{bsCollapsePanel} +\alias{bsCollapsePanel} +\title{bsCollapsePanel} +\usage{ +bsCollapsePanel(title, ..., value = title, style = NULL) +} +\arguments{ +\item{title}{The title to display at the top of the panel.} + +\item{value}{\bold{Optional} The value to return when this panel is open. Defaults to \code{title}.} + +\item{style}{\bold{Optional} A Bootstrap style to apply to the panel. (\code{primary}, \code{danger}, \code{warning}, \code{info}, or \code{success})} + +\item{\dots}{UI elements to include within the panel.} +} +\description{ +\code{bsCollapsePanel} creates individual panels within a \code{\link{bsCollapse}} object. +} +\details{ +See \link{Collapses} for more information about how to use \code{bsCollapsePanel} with the +rest of the Collapses family. +} +\note{ +Run \code{bsExample("Collapses")} for an example +of \code{bsCollapsePanel} functionality. +} +\seealso{ +\href{http://getbootstrap.com}{Twitter Bootstrap 3} + +Other Collapses: \code{\link{Collapses}}; + \code{\link{bsCollapse}}; \code{\link{updateCollapse}} +} + diff --git a/man/bsExample.Rd b/man/bsExample.Rd new file mode 100644 index 0000000..624b627 --- /dev/null +++ b/man/bsExample.Rd @@ -0,0 +1,32 @@ +% Generated by roxygen2 (4.1.0): do not edit by hand +% Please edit documentation in R/bsExample.R +\name{bsExample} +\alias{bsExample} +\title{bsExample} +\usage{ +bsExample(family, display.mode = "showcase", ...) +} +\arguments{ +\item{family}{A shinyBS family name} + +\item{display.mode}{The display mode to use when running the example. See +\code{\link{runApp}}.} + +\item{\dots}{Other parameters to pass to \code{\link{runApp}}.} +} +\description{ +A function to view examples of shinyBS functionality. Will run the examples +found in the examples sections of shinyBS documentation. Use this instead of +\code{example}. +} +\details{ +This function is just a wrapper for \code{\link{runApp}} that runs copies of the +examples found in the family documention pages of \code{shinyBS}. By default, +\code{display.mode} is set to \code{showcase} so you can see the code while +the app is running. +} +\examples{ +\dontrun{ + bsExample("Alerts")} +} + diff --git a/man/bsMedia.Rd b/man/bsMedia.Rd deleted file mode 100644 index d661a45..0000000 --- a/man/bsMedia.Rd +++ /dev/null @@ -1,63 +0,0 @@ -\name{bsMedia} -\alias{bsMedia} -\title{ - Twitter Bootstrap Media Objects -} -\description{ - Creates a Twitter Bootstrap Media object, which has an image on the left, a title at the top right, and text on the buttom right. Looks similar to comments on many websites. -} -\usage{ -bsMedia(id, heading, text, image) -} -%- maybe also 'usage' for other objects documented here. -\arguments{ - \item{id}{ - An id for the media object -} - \item{heading}{ - Large text that will appear on the upper right of the object -} - \item{text}{ - the main content of the media object -} - \item{image}{ - the url of an image to place on the left side of the object -} -} -\details{ - \code{bsMedia} was mainly created to produce a more content rich version of - the dropdown object. A shiny programmer can provide a named list of - \code{bsMedia} object to the choice argument of the bsNavDropDown and have - them rendered in the dropdown menu. -} -\references{ - \href{http://getbootstrap.com/2.3.2/components.html}{Media object for Twitter Bootstrap 2.3.2} -} - -\author{ -Eric Bailey -} - -\note{ - Run \code{bsNavDemo()} for a live example of media objects in a dropdown. -} - -\examples{ -\dontrun{ - - # Create a list to provide to the choices argument in bsNavDropDown - media <- list(GI = bsMedia(id = "GI", header = "Gary IITRI", - text = "Gary IITRI has been an active monitor since 1998...", - img = "GI_map.png"), - NE = bsMedia(id = "NE", header = "Falls of the Ohio", - text = "The Falls of the Ohio air toxics monitor is ...", - img = "NE_map.png")) - - # Create a media object styled navbar dropdown - bsNavBar("mainnb", "navBar Demo", - bsNavDropDown("ndd2", "Monitors", media) - ) - - -} -} diff --git a/man/bsModal.Rd b/man/bsModal.Rd index a4f8784..0ae2e2f 100644 --- a/man/bsModal.Rd +++ b/man/bsModal.Rd @@ -1,62 +1,37 @@ -\name{Modal Windows} +% Generated by roxygen2 (4.1.0): do not edit by hand +% Please edit documentation in R/bsModal.R +\name{bsModal} \alias{bsModal} -\alias{toggleModal} -\title{ - Modal Windows for Shiny Apps -} -\description{ - Create Twitter Bootstrap modal windows for shiny apps -} +\title{bsModal} \usage{ -bsModal(id, title, trigger, ..., href) -toggleModal(session, modalId) +bsModal(id, title, trigger, ..., size) } \arguments{ - \item{session}{ - The \code{session} object passed to function given to \code{shinyServer} -} - \item{id}{ - Id to assign to the modal window -} - \item{modalId}{ - The Id of the modal you want to open/close -} - \item{title}{ - The title of the modal window -} - \item{trigger}{ - The Id of a button or anchor that will be used to open the window -} - \item{\dots}{ - Elements to add to the body of the modal window -} - \item{href}{ - Location of an html file that will provide contents of modal body +\item{id}{A unique identifier for the modal window} + +\item{title}{The title to appear at the top of the modal} + +\item{trigger}{The id of a button or link that will open the modal.} + +\item{size}{\bold{Optional} What size should the modal be? (\code{small} or \code{large})} + +\item{\dots}{UI elements to include within the modal} } +\description{ +\code{bsModal} is used within the UI to create a modal window. } \details{ - Modals can contain any combination of html, shiny inputs, or shiny outputs.\cr\cr - \code{toggleModal} will open the model if it is closed, or close it if it is open. +See \link{Modals} for more information about how to use \code{bsModal} with the +rest of the Modals family. } - -\references{ - \href{http://getbootstrap.com/2.3.2/javascript.html}{Modals for Twitter Bootstrap 2.3.2} -} - -\author{ -Eric Bailey -} - \note{ - Run \code{bsDemo()} for a live example of modals. +Run \code{bsExample("Modals")} for an example +of \code{bsModal} functionality. } +\seealso{ +\href{http://getbootstrap.com}{Twitter Bootstrap 3} -\examples{ -\dontrun{ - - # Create the button that will trigger the modal - bsButton("moTrig", "Open Modal", style = "primary"), - # Create a modal with the title 'A Remote Modal' that loads its contents from moDemo.html - bsModal("moMod2", "A Remote Modal", trigger = "moTrig", href = "moDemo.html") -} +Other Modals: \code{\link{Modals}}; + \code{\link{toggleModal}} } + diff --git a/man/bsPopover.Rd b/man/bsPopover.Rd new file mode 100644 index 0000000..3cdc3af --- /dev/null +++ b/man/bsPopover.Rd @@ -0,0 +1,46 @@ +% Generated by roxygen2 (4.1.0): do not edit by hand +% Please edit documentation in R/bsPopover.R +\name{bsPopover} +\alias{bsPopover} +\title{bsPopover} +\usage{ +bsPopover(id, title, content, placement = "bottom", trigger = "hover", + options = NULL) +} +\arguments{ +\item{id}{The id of the element to attach the popover to.} + +\item{title}{The title of the popover.} + +\item{content}{The main content of the popover.} + +\item{placement}{Where the popover should appear relative to its target +(\code{top}, \code{bottom}, \code{left}, or \code{right}). Defaults to \code{"bottom"}.} + +\item{trigger}{What action should cause the popover to appear? (\code{hover}, +\code{focus}, \code{click}, or \code{manual}). Defaults to \code{"hover"}.} + +\item{options}{A named list of additional options to be set on the popover.} +} +\description{ +\code{bsPopover} is used within the UI of an app to add a popover to a Shiny +input or output. +} +\details{ +See \link{Tooltips_and_Popovers} for more information about how to use \code{bsPopover} with the +rest of the Tooltips_and_Popovers family. +} +\note{ +Run \code{bsExample("Tooltips_and_Popovers")} for an example +of \code{bsPopover} functionality. +} +\seealso{ +\href{http://getbootstrap.com}{Twitter Bootstrap 3} + +Other Tooltips_and_Popovers: \code{\link{Tooltips_and_Popovers}}; + \code{\link{addPopover}}; \code{\link{addTooltip}}; + \code{\link{bsTooltip}}; \code{\link{popify}}; + \code{\link{removePopover}}; \code{\link{removeTooltip}}; + \code{\link{tipify}} +} + diff --git a/man/bsTooltip.Rd b/man/bsTooltip.Rd new file mode 100644 index 0000000..1494de7 --- /dev/null +++ b/man/bsTooltip.Rd @@ -0,0 +1,44 @@ +% Generated by roxygen2 (4.1.0): do not edit by hand +% Please edit documentation in R/bsTooltip.R +\name{bsTooltip} +\alias{bsTooltip} +\title{bsTooltip} +\usage{ +bsTooltip(id, title, placement = "bottom", trigger = "hover", + options = NULL) +} +\arguments{ +\item{id}{The id of the element to attach the tooltip to.} + +\item{title}{The content of the tooltip.} + +\item{placement}{Where the tooltip should appear relative to its target +(\code{top}, \code{bottom}, \code{left}, or \code{right}). Defaults to \code{"bottom"}.} + +\item{trigger}{What action should cause the tooltip to appear? (\code{hover}, +\code{focus}, \code{click}, or \code{manual}). Defaults to \code{"hover"}.} + +\item{options}{A named list of additional options to be set on the tooltip.} +} +\description{ +\code{bsTooltip} is used within the UI of an app to add a tooltip to a Shiny +input or output. +} +\details{ +See \link{Tooltips_and_Popovers} for more information about how to use \code{bsTooltip} with the +rest of the Tooltips_and_Popovers family. +} +\note{ +Run \code{bsExample("Tooltips_and_Popovers")} for an example +of \code{bsTooltip} functionality. +} +\seealso{ +\href{http://getbootstrap.com}{Twitter Bootstrap 3} + +Other Tooltips_and_Popovers: \code{\link{Tooltips_and_Popovers}}; + \code{\link{addPopover}}; \code{\link{addTooltip}}; + \code{\link{bsPopover}}; \code{\link{popify}}; + \code{\link{removePopover}}; \code{\link{removeTooltip}}; + \code{\link{tipify}} +} + diff --git a/man/bsTypeahead.Rd b/man/bsTypeahead.Rd new file mode 100644 index 0000000..baf5243 --- /dev/null +++ b/man/bsTypeahead.Rd @@ -0,0 +1,32 @@ +% Generated by roxygen2 (4.1.0): do not edit by hand +% Please edit documentation in R/bsTypeahead.R +\name{bsTypeahead} +\alias{bsTypeahead} +\title{bsTypeahead} +\usage{ +bsTypeahead(inputId, label, value = "", choices, items = 8, minLength = 1) +} +\arguments{ +\item{inputId}{Input variable to assign the control's value to} + +\item{label}{Display label for the control} + +\item{value}{Initial value} + +\item{choices}{Array of strings to match against. Can also be JavaScript +function. Use htmlwidgets::JS() to indicate JavaScript. The length of \code{choices} must no exceed 131370.} + +\item{items}{The max number of items to display in the dropdown. Can also be +set to 'all'} + +\item{minLength}{The minimum character length needed before triggering +autocomplete suggestions. You can set it to 0 so suggestion are shown even +when there is no text when lookup function is called.} +} +\description{ +\code{typeaheadInput} creates a textinput with type ahead function buttons. +} +\seealso{ +\code{\link{updateTypeaheadInput}} +} + diff --git a/man/closeAlert.Rd b/man/closeAlert.Rd new file mode 100644 index 0000000..707330f --- /dev/null +++ b/man/closeAlert.Rd @@ -0,0 +1,32 @@ +% Generated by roxygen2 (4.1.0): do not edit by hand +% Please edit documentation in R/closeAlert.R +\name{closeAlert} +\alias{closeAlert} +\title{closeAlert} +\usage{ +closeAlert(session, alertId) +} +\arguments{ +\item{session}{The session object passed to function given to shinyServer.} + +\item{alertId}{The id of the alert to be dismissed.} +} +\description{ +\code{closeAlert} is used within your Server logic to close an alert that you +created with \code{\link{createAlert}}. +} +\details{ +See \link{Alerts} for more information about how to use \code{closeAlert} with the +rest of the Alerts family. +} +\note{ +Run \code{bsExample("Alerts")} for an example +of \code{closeAlert} functionality. +} +\seealso{ +\href{http://getbootstrap.com}{Twitter Bootstrap 3} + +Other Alerts: \code{\link{Alerts}}; \code{\link{bsAlert}}; + \code{\link{createAlert}} +} + diff --git a/man/collapse.Rd b/man/collapse.Rd deleted file mode 100644 index 004261a..0000000 --- a/man/collapse.Rd +++ /dev/null @@ -1,84 +0,0 @@ -\name{collapse} -\alias{bsCollapse} -\alias{bsCollapsePanel} -\alias{updateCollapse} -\title{ -Twitter Bootstrap Collapse Panels -} -\description{ -Create Twitter Boostrap-style collapse panels (sometimes called accordion -panels) in shiny. -} -\usage{ -bsCollapse(..., id = NULL, multiple = FALSE, open = NULL) -bsCollapsePanel(title, ..., id = NULL, value = NULL) -updateCollapse(session, id, open = NULL, close = NULL, multiple = NULL) -} -%- maybe also 'usage' for other objects documented here. -\arguments{ - \item{\dots}{ - for \code{bsCollapse} a series of \code{bsCollapsePanels} to include in - the object for \code{bsCollapsePanel} as series of UI elements to add to - the panel -} - \item{id}{ - a name for the object. Optional -} - \item{multiple}{ - if \code{TRUE} then opening one panel will not close other panels -} - \item{open}{ - The id of the panel(s) you want to open -} - \item{close}{ - The id of the panel(s) you want to close -} - \item{title}{ - The title to appear at the top of the panel -} - \item{value}{ - The value that is returned by the \code{bsCollapse} object when this panel - is open -} - \item{session}{ - The \code{session} object passed to function given to \code{shinyServer} - } -} -\details{ - \code{bsCollapse} works very similarly to \code{tabsetPanel} and may be useful - in similar situations.\cr\cr - Like \code{tabsetPanel}s, \code{bsCollapse} can return values indicating which - panels are open or \code{NULL} if no panels are open. - -} -\references{ - \href{http://getbootstrap.com/2.3.2/javascript.html}{Collapse for Twitter - Bootstrap 2.3.2} -} -\author{ - Eric Bailey -} -\note{ - Collapse panels didn't render properly when bsDemo() was run in Internet Explorer 10.\cr\cr - Run \code{bsDemo()} for a live example of collapse panels. -} -\examples{ -\dontrun{ - - ## This code, placed inside ui.R, creates the collapse group with 3 panels: - bsCollapse(multiple = FALSE, open = "col1", id = "collapse1", - bsCollapsePanel("Collapse #1", "Cell treachery spearwife night\'s - watch, tower suckling ...", - id="col1", value="test1"), - bsCollapsePanel("Collapse #2", actionButton("btn123", "A Button"), - textInput("txt1234", "A Text Input"), - id="col2", value="test2"), - bsCollapsePanel("Collapse #3", plotOutput("testPlot1"), - id="col3", value="test3") - ) - - ## This code, placed inside server.R, will change multiple to TRUE and open - ## the first and third panels: - updateCollapse(session, "collapse1", multiple = TRUE, - open = c("col1", "col2")) -}} diff --git a/man/createAlert.Rd b/man/createAlert.Rd new file mode 100644 index 0000000..5b6217e --- /dev/null +++ b/man/createAlert.Rd @@ -0,0 +1,46 @@ +% Generated by roxygen2 (4.1.0): do not edit by hand +% Please edit documentation in R/createAlert.R +\name{createAlert} +\alias{createAlert} +\title{createAlert} +\usage{ +createAlert(session, anchorId, alertId = NULL, title = NULL, + content = NULL, style = NULL, dismiss = TRUE, append = TRUE) +} +\arguments{ +\item{session}{The session object passed to function given to shinyServer.} + +\item{anchorId}{The unique identifier of the anchor where the alert should be +displayed.} + +\item{alertId}{\bold{Optional} A unique identifier for the Alert.} + +\item{title}{\bold{Optional} A title for the Alert.} + +\item{content}{The main body of the Alert. HTML tags are allowed.} + +\item{style}{A bootstrap style to apply. Defaults to \code{info}.} + +\item{dismiss}{\code{logical} Should the Alert be user dismissable? Defaults to \code{TRUE}.} + +\item{append}{\code{logical} Should the Alert be appended below existing Alerts? Default to \code{TRUE}.} +} +\description{ +\code{createAlert} is used within the Server logic of your Shiny app to display +an alert to the user. +} +\details{ +See \link{Alerts} for more information about how to use \code{createAlert} with the +rest of the Alerts family. +} +\note{ +Run \code{bsExample("Alerts")} for an example +of \code{createAlert} functionality. +} +\seealso{ +\href{http://getbootstrap.com}{Twitter Bootstrap 3} + +Other Alerts: \code{\link{Alerts}}; \code{\link{bsAlert}}; + \code{\link{closeAlert}} +} + diff --git a/man/demo.Rd b/man/demo.Rd deleted file mode 100644 index a5bd620..0000000 --- a/man/demo.Rd +++ /dev/null @@ -1,47 +0,0 @@ -\name{shinyBS Examples} -\alias{bsDemo} -\alias{bsNavDemo} -\title{ - Examples of shinyBS functionality -} -\description{ - Example app that shows functionality of shinyBS. -} -\usage{ - bsDemo(port = NULL, - launch.browser = getOption("shiny.launch.browser", interactive())) - bsNavDemo(port = NULL, - launch.browser = getOption("shiny.launch.browser", interactive())) - -} -\arguments{ - \item{port}{ - The TCP port that the application should listen on. Defaults to choosing a - random port. -} - \item{launch.browser}{ - If true, the system's default web browser will be launched automatically - after the app is started. Defaults to true in interactive sessions only. - This value of this parameter can also be a function to call with the - application's URL. -} -} -\author{ - Eric Bailey -} -\note{ - Just a wrapper for shiny's \code{runApp} to make demoing easier -} - -\seealso{ - \code{\link{runApp}} - \cr - \code{\link{runExample}} -} -\examples{ - -\dontrun{ - bsDemo() - bsNavDemo() - } -} diff --git a/man/divider.Rd b/man/divider.Rd deleted file mode 100644 index cdce966..0000000 --- a/man/divider.Rd +++ /dev/null @@ -1,26 +0,0 @@ -\name{bsNavDivider} -\alias{bsNavDivider} -\title{ - Twitter Bootstrap Navbar Divider -} -\description{ - Adds a vertical line to navbar to help set off other navbar elements -} -\usage{ -bsNavDivider() -} - -\references{ -\href{http://getbootstrap.com/2.3.2/components.html}{Navbars for Twitter Bootstrap 2.3.2} -} -\author{ -Eric Bailey -} - -\examples{ -\dontrun{ - - ##In ui.R - bsNavDivider() - } -} \ No newline at end of file diff --git a/man/dropdown.Rd b/man/dropdown.Rd deleted file mode 100644 index ffea94e..0000000 --- a/man/dropdown.Rd +++ /dev/null @@ -1,67 +0,0 @@ -\name{DropDowns} -\alias{updateDropDown} -\alias{bsNavDropDown} -\title{ - Twitter Bootstrap NavBar Dropdowns -} -\description{ - Add and update Twitter Bootstrap NavBar Dropdowns in shiny. -} -\usage{ -bsNavDropDown(inputId, label, choices, selected="") -updateDropDown(session, inputId, label = NULL, choices = NULL, selected = NULL) -} -%- maybe also 'usage' for other objects documented here. -\arguments{ - \item{session}{ - The \code{session} object passed to function given to \code{shinyServer} - } - - \item{inputId}{ - Input variable to assign the control's value to - } - - \item{label}{ - The label that will appear on the object - } - \item{choices}{ - A list of values to appear in the dropdown -} - \item{selected}{ - The value to set for the input object -} -} -\details{ - Dropdowns are an alternative to \code{\link{selectInput}} objects that can appear in a navBar. The structure of the function to create and update them has been modeled after that function.\cr\cr - A dropdown returns the value of the last dropdown element in its \code{choices} link that has been clicked. -} - -\references{ -\href{http://getbootstrap.com/2.3.2/components.html}{Navbars for Twitter Bootstrap 2.3.2} -\href{http://getbootstrap.com/2.3.2/components.html}{Dropdowns for Twitter Bootstrap 2.3.2} -} -\author{ - Eric Bailey -} -\note{ - Run \code{bsDemo()} for a live example of alerts. -} -\seealso{ - \code{\link{selectInput}} -} -\examples{ -\dontrun{ - - ## In ui.R - ## Create a dropdown - bsNavDropDown(inputId = "dd1", label = "Distribution", - choices = c("Normal", "Lognormal", "Gamma"), - selected = "Normal") - - ## In server.R - ## Add another distribution to the list - updateDropDown("dd1" choices = c("Normal", "Lognormal", "Gamma", "Exponential")) -} - - -} diff --git a/man/glyph.Rd b/man/glyph.Rd deleted file mode 100644 index 699a28f..0000000 --- a/man/glyph.Rd +++ /dev/null @@ -1,38 +0,0 @@ -\name{bsGlyph} -\alias{bsGlyph} - -\title{ - Glyphicons -} -\description{ - Add glyphicons to shiny applications -} -\usage{ -bsGlyph(name, white = FALSE) -} -\arguments{ - \item{name}{ - The name of the glyphicon to be used -} - \item{white}{ - Should the white version be used. (\code{logical}) -} -} -\details{ - See the references to find names of available icons -} -\references{ - \href{http://getbootstrap.com/2.3.2/base-css.html}{Glyphicons for Twitter Bootstrap 2.3.2} - \href{http://glyphicons.com/}{Glyphicons} -} -\author{ -Eric Bailey -} - -\examples{ -\dontrun{ - - ##Add a bsNavLink with a question mark graphic - bsNavLink("link1", label = bsGlyph("icon-question-sign")) - } -} \ No newline at end of file diff --git a/man/link.Rd b/man/link.Rd deleted file mode 100644 index 9a62c9c..0000000 --- a/man/link.Rd +++ /dev/null @@ -1,49 +0,0 @@ -\name{bsNavLink} -\alias{bsNavLink} - -\title{ - Twitter Boostrap Navbar Links -} -\description{ - Functions to create Twitter Bootstrap Navbar Links -} -\usage{ -bsNavLink(inputId, label, href = "#") -} -\arguments{ - \item{inputId}{ - The id of the input object. - } - \item{label}{ - The label that will appear on the link/button. - } - \item{href}{ - Optional web address for the link - } -} -\details{ - Works as an \link{actionButton} but can also be used as a regular web link if \code{href} is provided. -} - -\references{ -\href{http://getbootstrap.com/2.3.2/components.html}{Navbars for Twitter Bootstrap 2.3.2} -} -\author{ -Eric Bailey -} - - -\note{ - Run \code{bsDemo()} for a live example of navLinks. -} - -\examples{ -\dontrun{ - - ## In ui.R - ## Create a navLink that acts as an action button: - bsNavLink(inputId = "link1", label="Run Example") - ## Create a navLink that acts as a link: - bsNavLink(inputId = "link2", label="Google", href="http://www.google.com") -} -} diff --git a/man/navbar.Rd b/man/navbar.Rd deleted file mode 100644 index 79c4058..0000000 --- a/man/navbar.Rd +++ /dev/null @@ -1,64 +0,0 @@ -\name{bsNavBar} -\alias{bsNavBar} -\alias{updateNavBar} -\title{ - Twitter Bootstrap Navbar -} -\description{ - Create and modify a shell for a Twitter Bootstrap Navbar that can hold shiny input (and output) elements. -} -\usage{ -bsNavBar(inputId, brand, ..., rightItems, fixed = FALSE, inverse = FALSE) -updateNavBar(session, inputId, brand=NULL, fixed=NULL, inverse=NULL) -} -%- maybe also 'usage' for other objects documented here. -\arguments{ - \item{session}{ - The \code{session} object passed to function given to \code{shinyServer} - } - - \item{inputId}{ - Input variable to assign the control's value to - } - \item{brand}{ - A word or two that will appear at the left of the navbar -} - \item{\dots}{ - UI elements to include within the navbar. These will align to the left -} - \item{rightItems}{ - a \code{list} of UI elements you wish to align to the right -} - \item{fixed}{ - Should the navbar be fixed to the top of the page \code{logical} -} - \item{inverse}{ - Should the inverse navbar style be used \code{logical} -} - -} - -\references{ - \href{http://getbootstrap.com/2.3.2/components.html}{Navbars for Twitter Bootstrap 2.3.2} -} -\author{ - Eric Bailey -} -\note{ - Run \code{bsDemo()} for a live example of navBars. -} - -\examples{ -\dontrun{ - - ## In ui.R - ## Create a navBar with the brand "shinyBS" that is fixed to the top of the page - bsNavBar("nb1", brand="shinyBS", fixed=TRUE, - leftItems = list(), - rightItems = list()) - - ## In server.R - ## Change to the inverse style of navBar - modifyNavBar(session, inputId="nb1", inverse=TRUE) -} -} diff --git a/man/navinputs.Rd b/man/navinputs.Rd deleted file mode 100644 index b8c4a33..0000000 --- a/man/navinputs.Rd +++ /dev/null @@ -1,88 +0,0 @@ -\name{NavBar Inputs} -\alias{bsNavDateRangeInput} -\alias{bsNavDateInput} -\alias{bsNavTextInput} -\alias{bsNavButton} -\title{ - NavBar Versions of Shiny Inputs -} -\description{ - These are stanard shiny inputs that have been slightly reworked to fit better - into navBars -} -\usage{ -bsNavDateRangeInput(inputId, label, start = NULL, end = NULL, min = NULL, - max = NULL, format = "yyyy-mm-dd", startview = "month", - weekstart = 0, language = "en", width = NULL) -bsNavDateInput(inputId, label, value = NULL, min = NULL, max = NULL, - format = "yyyy-mm-dd", startview = "month", weekstart = 0, - language = "en", width = NULL) -bsNavTextInput(inputId, label, value = "", width=NULL) -bsNavButton(inputId, label) -} -%- maybe also 'usage' for other objects documented here. -\arguments{ - \item{inputId}{ - Input variable to assign the control's value to - } - \item{label}{ - Text to appear as placeholder in text object -} - \item{start}{ - See \code{\link{dateRangeInput}} -} - \item{end}{ - See \code{\link{dateRangeInput}} -} - \item{value}{ - See \code{\link{dateInput}} or \code{\link{textInput}} - } - \item{min}{ - See \code{\link{dateRangeInput}} or \code{\link{dateInput}} -} - \item{max}{ - See \code{\link{dateRangeInput}} or \code{\link{dateInput}} -} - \item{format}{ - See \code{\link{dateRangeInput}} or \code{\link{dateInput}} -} - \item{startview}{ - See \code{\link{dateRangeInput}} or \code{\link{dateInput}} -} - \item{weekstart}{ - See \code{\link{dateRangeInput}} or \code{\link{dateInput}} -} - \item{language}{ - See \code{\link{dateRangeInput}} or \code{\link{dateInput}} -} - \item{width}{ - Optional width of element in pixels -} -} -\details{ - These are identical to the regular shiny inputs with the exception of an - added 'width' arguement that allows the designer more control over their - size and removal of labels in favor of 'placeholder' text which also saves - room in the navbar. \cr \cr - The update functions for the standard inputs also work for their navBar - versions. -} - -\author{ - Eric Bailey -} - -\seealso{ - \code{\link{dateInput}} \cr - \code{\link{dateRangeInput}} \cr - \code{\link{textInput}} \cr - \code{\link{actionButton}} \cr -} - -\note{ - Run \code{bsDemo()} for a live example of navBar elements. -} - -\examples{ -\dontrun{See original versions for examples} -} \ No newline at end of file diff --git a/man/page.Rd b/man/page.Rd deleted file mode 100644 index 23703c1..0000000 --- a/man/page.Rd +++ /dev/null @@ -1,26 +0,0 @@ -\name{pageWithNavBar} -\alias{pageWithNavBar} -\title{ -Create a page with a NavBar -} -\description{ -Create a shiny UI that contains a navbar for input controls and a main area for outputs. -} -\usage{ -pageWithNavBar(title = "", navbar, mainContent) -} -%- maybe also 'usage' for other objects documented here. -\arguments{ - \item{title}{ - The title to appear in the browsers application bar. -} - \item{navbar}{ - A navbar created with \code{\link{bsNavBar}} -} - \item{mainContent}{ - Outputs for the application -} -} -\author{ - Eric Bailey -} diff --git a/man/popify.Rd b/man/popify.Rd new file mode 100644 index 0000000..180135d --- /dev/null +++ b/man/popify.Rd @@ -0,0 +1,47 @@ +% Generated by roxygen2 (4.1.0): do not edit by hand +% Please edit documentation in R/popify.R +\name{popify} +\alias{popify} +\title{popify} +\usage{ +popify(el, title, content, placement = "bottom", trigger = "hover", + options = NULL) +} +\arguments{ +\item{el}{A shiny UI element.} + +\item{title}{The title of the popover.} + +\item{content}{The main content of the popover.} + +\item{placement}{Where the popover should appear relative to its target +(\code{top}, \code{bottom}, \code{left}, or \code{right}). Defaults to \code{"bottom"}.} + +\item{trigger}{What action should cause the popover to appear? (\code{hover}, +\code{focus}, \code{click}, or \code{manual}). Defaults to \code{"hover"}.} + +\item{options}{A named list of additional options to be set on the popover.} +} +\description{ +\code{popify} can be wrapped around any shiny UI element to add a popover to the +wrapped element. This should be a safer way to add popovers to elements created with +\code{\link{renderUI}}. +} +\details{ +See \link{Tooltips_and_Popovers} for more information about how to use \code{popify} with the +rest of the Tooltips_and_Popovers family. +} +\note{ +Run \code{bsExample("Tooltips_and_Popovers")} for an example +of \code{popify} functionality. +} +\seealso{ +\href{http://getbootstrap.com}{Twitter Bootstrap 3} + +Other Tooltips_and_Popovers: \code{\link{Tooltips_and_Popovers}}; + \code{\link{addPopover}}; \code{\link{addTooltip}}; + \code{\link{bsPopover}}; \code{\link{bsTooltip}}; + \code{\link{removePopover}}; \code{\link{removeTooltip}}; + \code{\link{tipify}} +} + diff --git a/man/popover.Rd b/man/popover.Rd deleted file mode 100644 index c0fe0e6..0000000 --- a/man/popover.Rd +++ /dev/null @@ -1,70 +0,0 @@ -\name{addPopover} -\alias{addPopover} -\alias{bsPopover} -\alias{removePopover} -\title{ - Twitter Bootstrap Popovers -} -\description{ - Functions to add Twitter Bootstrap popovers in shiny. -} -\usage{ - addPopover(session, id, title = "", content, - placement = "right", trigger = "click") - bsPopover(id, title = "", content, - placement = "right", trigger = "click") - removePopover(session, id) -} -%- maybe also 'usage' for other objects documented here. -\arguments{ - \item{session}{ - The \code{session} object passed to function given to \code{shinyServer} - } - \item{id}{ - The \code{inputId} of the object to add the popover to - } - \item{title}{ - The title of the popover - } - \item{content}{ - The main content of the popover - } - \item{placement}{ - Where the popover should appear in relation to the object. Acceptable values are \code{bottom}, \code{top}, \code{left}, and \code{right}. -} - \item{trigger}{ - What action will make the popover appear. Common values are \code{hover} or \code{click}. -} -} -\details{ - \code{bsPopover} is called from \code{ui.R} and will add a \code{