mirror of
https://github.com/rstudio/shiny.git
synced 2026-01-11 07:58:11 -05:00
Compare commits
99 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6c711b76b0 | ||
|
|
9c914f10c4 | ||
|
|
eda56d118a | ||
|
|
02c7351c6d | ||
|
|
ab618235f1 | ||
|
|
ffead9ed70 | ||
|
|
36aefadced | ||
|
|
75ccfe38ce | ||
|
|
e3cb3fe2e4 | ||
|
|
983e7e9b75 | ||
|
|
3db47c076c | ||
|
|
eeff285b33 | ||
|
|
029595f8ea | ||
|
|
ea2ec27724 | ||
|
|
f6bf4a416f | ||
|
|
af978a68e3 | ||
|
|
89dc1323e1 | ||
|
|
a4b5f63deb | ||
|
|
feaa6ccff4 | ||
|
|
7159293337 | ||
|
|
4a5b31e3a7 | ||
|
|
6f1dc89fb3 | ||
|
|
29dd405fe5 | ||
|
|
0f0b0cd3d8 | ||
|
|
262528e36a | ||
|
|
597e86dd57 | ||
|
|
b604dba948 | ||
|
|
1837a64bd2 | ||
|
|
9b413de4d8 | ||
|
|
3d77cbd677 | ||
|
|
62176c3218 | ||
|
|
d7a01c32cc | ||
|
|
cc493fd545 | ||
|
|
6b8679454d | ||
|
|
1b68d61e54 | ||
|
|
418de862e6 | ||
|
|
413653858e | ||
|
|
f0886a7556 | ||
|
|
0e2666948f | ||
|
|
d2fc851816 | ||
|
|
e1fb29c8c5 | ||
|
|
fe3158fdd6 | ||
|
|
721b26f80b | ||
|
|
d3ecfb22ee | ||
|
|
27a98020c9 | ||
|
|
ab56b72f39 | ||
|
|
8063f66958 | ||
|
|
bf270b9adb | ||
|
|
972db08740 | ||
|
|
6326c7cbaa | ||
|
|
4152ace514 | ||
|
|
038221408c | ||
|
|
9f76def7ce | ||
|
|
1b83770c5c | ||
|
|
3458d924ca | ||
|
|
0749b9500c | ||
|
|
b1dfc18a8c | ||
|
|
7b25c282c0 | ||
|
|
a128ceaf2d | ||
|
|
f266cab580 | ||
|
|
23bf9aaf17 | ||
|
|
1983f60ec6 | ||
|
|
27f8909406 | ||
|
|
9988206911 | ||
|
|
31fe1fdfa6 | ||
|
|
77b125ce2d | ||
|
|
6e68e07aa2 | ||
|
|
86bb010a93 | ||
|
|
4a623b596b | ||
|
|
bcf098ea7d | ||
|
|
4bfb226fb5 | ||
|
|
691615108b | ||
|
|
858ab00e36 | ||
|
|
7023f5b145 | ||
|
|
eb4fabeac6 | ||
|
|
a5e09f9ce4 | ||
|
|
c2fe4e8b6d | ||
|
|
5d22648d34 | ||
|
|
066fd15184 | ||
|
|
fe90c230d5 | ||
|
|
0b5ae92136 | ||
|
|
1c5565aaee | ||
|
|
69c177a3ec | ||
|
|
0645b3f65b | ||
|
|
9e7471fcc0 | ||
|
|
c520f53799 | ||
|
|
0bf1386802 | ||
|
|
b2ab3797aa | ||
|
|
ede0ca8bd1 | ||
|
|
81e35f0cc3 | ||
|
|
237522a1f7 | ||
|
|
0cd1644cf1 | ||
|
|
f31bb56ea6 | ||
|
|
cf3b805c46 | ||
|
|
517283ca58 | ||
|
|
f416b7ba47 | ||
|
|
973190b7a1 | ||
|
|
f536a9d3d3 | ||
|
|
1348ec3bcf |
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/NEWS merge=union
|
||||
10
.travis.yml
10
.travis.yml
@@ -10,11 +10,13 @@ install:
|
||||
- sudo apt-add-repository -y "deb http://cran.rstudio.com/bin/linux/ubuntu `lsb_release -cs`/"
|
||||
- sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys E084DAB9
|
||||
- sudo apt-add-repository -y ppa:marutter/c2d4u
|
||||
- sudo apt-get update
|
||||
- sudo apt-get install r-base-dev r-cran-shiny r-cran-cairo r-cran-markdown
|
||||
- sudo apt-get -qq update
|
||||
- sudo apt-get -qq install r-base r-cran-shiny r-cran-cairo r-cran-markdown r-cran-knitr
|
||||
- "[ ! -d ~/R ] && mkdir ~/R"
|
||||
- Rscript -e "install.packages(c('xtable', 'knitr', 'htmltools'), repos = 'http://cran.rstudio.org')"
|
||||
- Rscript -e "install.packages('$R_MY_PKG', dep = TRUE, repos = 'http://cran.rstudio.org')"
|
||||
- echo "options(repos = c(CRAN = 'http://cran.rstudio.com'))" > ~/.Rprofile
|
||||
- Rscript -e "install.packages(c('xtable'), quiet = TRUE)"
|
||||
- Rscript -e "update.packages(instlib = '~/R', ask = FALSE, quiet = TRUE)"
|
||||
- Rscript -e "install.packages('$R_MY_PKG', dep = TRUE, quiet = TRUE)"
|
||||
|
||||
# run tests
|
||||
script:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
Package: shiny
|
||||
Type: Package
|
||||
Title: Web Application Framework for R
|
||||
Version: 0.10.0
|
||||
Version: 0.10.1
|
||||
Date: 2014-06-13
|
||||
Author: RStudio, Inc.
|
||||
Maintainer: Winston Chang <winston@rstudio.com>
|
||||
|
||||
@@ -181,10 +181,10 @@ export(wellPanel)
|
||||
export(withMathJax)
|
||||
export(withReactiveDomain)
|
||||
export(withTags)
|
||||
import(RJSONIO)
|
||||
import(caTools)
|
||||
import(digest)
|
||||
import(htmltools)
|
||||
import(httpuv)
|
||||
import(methods)
|
||||
import(xtable)
|
||||
importFrom(RJSONIO,fromJSON)
|
||||
|
||||
31
NEWS
31
NEWS
@@ -1,3 +1,30 @@
|
||||
shiny 0.10.1
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
* Added Unicode support for Windows. Shiny apps running on Windows must use the
|
||||
UTF-8 encoding for ui.R and server.R (also the optional global.R) if they
|
||||
contain non-ASCII characters. See this article for details and examples:
|
||||
http://shiny.rstudio.com/gallery/unicode-characters.html (#516)
|
||||
|
||||
* `runGitHub()` also allows the 'username/repo' syntax now, which is equivalent
|
||||
to `runGitHub('repo', 'username')`. (#427)
|
||||
|
||||
* `navbarPage()` now accepts a `windowTitle` parameter to set the web browser
|
||||
page title to something other than the title displayed in the navbar.
|
||||
|
||||
* Added an `inline` argument to `textOutput()`, `imageOutput()`, `plotOutput()`,
|
||||
and `htmlOutput()`. When `inline = TRUE`, these outputs will be put in
|
||||
`span()` instead of the default `div()`. This occurs automatically when these
|
||||
outputs are created via the inline expressions (e.g. `r textOutput(expr)`) in
|
||||
R Markdown documents. See an R Markdown example at
|
||||
http://shiny.rstudio.com/gallery/inline-output.html (#512)
|
||||
|
||||
* Added support for option groups in the select/selectize inputs. When the
|
||||
`choices` argument for `selectInput()`/`selectizeInput()` is a list of
|
||||
sub-lists and any sub-list is of length greater than 1, the HTML tag
|
||||
`<optgroup>` will be used. See an example at
|
||||
http://shiny.rstudio.com/gallery/option-groups-for-selectize-input.html (#542)
|
||||
|
||||
shiny 0.10.0
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
@@ -64,6 +91,10 @@ shiny 0.10.0
|
||||
* Fixed #220: the zip file for a directory created by some programs may not have
|
||||
the directory name as its first entry, in which case runUrl() can fail. (#220)
|
||||
|
||||
* `runGitHub()` can also take a value of the form "username/repo" in its first
|
||||
argument, e.g. both runGitHub("shiny_example", "rstudio") and
|
||||
runGitHub("rstudio/shiny_example") are valid ways to run the GitHub repo.
|
||||
|
||||
shiny 0.9.1
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
|
||||
55
R/app.R
55
R/app.R
@@ -69,7 +69,7 @@ shinyApp <- function(ui, server, onStart=NULL, options=list(), uiPattern="/") {
|
||||
|
||||
renderPage(uiValue, textConn)
|
||||
html <- paste(textConnectionValue(textConn), collapse='\n')
|
||||
return(httpResponse(200, content=html))
|
||||
return(httpResponse(200, content=enc2utf8(html)))
|
||||
}
|
||||
|
||||
serverFuncSource <- function() {
|
||||
@@ -112,9 +112,7 @@ shinyAppDir <- function(appDir, options=list()) {
|
||||
# If not, then take the last expression that's returned from ui.R.
|
||||
.globals$ui <- NULL
|
||||
on.exit(.globals$ui <- NULL, add = FALSE)
|
||||
ui <- source(uiR,
|
||||
local = new.env(parent = globalenv()),
|
||||
keep.source = TRUE)$value
|
||||
ui <- sourceUTF8(uiR, local = new.env(parent = globalenv()))$value
|
||||
if (!is.null(.globals$ui)) {
|
||||
ui <- .globals$ui[[1]]
|
||||
}
|
||||
@@ -137,11 +135,7 @@ shinyAppDir <- function(appDir, options=list()) {
|
||||
# server.R.
|
||||
.globals$server <- NULL
|
||||
on.exit(.globals$server <- NULL, add = TRUE)
|
||||
result <- source(
|
||||
serverR,
|
||||
local = new.env(parent = globalenv()),
|
||||
keep.source = TRUE
|
||||
)$value
|
||||
result <- sourceUTF8(serverR, local = new.env(parent = globalenv()))$value
|
||||
if (!is.null(.globals$server)) {
|
||||
result <- .globals$server[[1]]
|
||||
}
|
||||
@@ -169,7 +163,7 @@ shinyAppDir <- function(appDir, options=list()) {
|
||||
oldwd <<- getwd()
|
||||
setwd(appDir)
|
||||
if (file.exists(file.path.ci(appDir, "global.R")))
|
||||
source(file.path.ci(appDir, "global.R"), keep.source = TRUE)
|
||||
sourceUTF8(file.path.ci(appDir, "global.R"))
|
||||
}
|
||||
onEnd <- function() {
|
||||
setwd(oldwd)
|
||||
@@ -249,26 +243,33 @@ as.tags.shiny.appobj <- function(x, ...) {
|
||||
#' @param ... Additional knit_print arguments
|
||||
NULL
|
||||
|
||||
# If there's an R Markdown runtime option set but it isn't set to Shiny, then
|
||||
# return a warning indicating the runtime is inappropriate for this object.
|
||||
# Returns NULL in all other cases.
|
||||
shiny_rmd_warning <- function() {
|
||||
runtime <- knitr::opts_knit$get("rmarkdown.runtime")
|
||||
if (!is.null(runtime) && runtime != "shiny")
|
||||
# note that the RStudio IDE checks for this specific string to detect Shiny
|
||||
# applications in static document
|
||||
list(structure(
|
||||
"Shiny application in a static R Markdown document",
|
||||
class = "rmd_warning"))
|
||||
else
|
||||
NULL
|
||||
}
|
||||
|
||||
#' @rdname knitr_methods
|
||||
#' @export
|
||||
knit_print.shiny.appobj <- function(x, ...) {
|
||||
opts <- x$options %OR% list()
|
||||
width <- if (is.null(opts$width)) "100%" else opts$width
|
||||
height <- if (is.null(opts$height)) "400" else opts$height
|
||||
shiny_warning <- NULL
|
||||
# if there's an R Markdown runtime option set but it isn't set to Shiny, then
|
||||
# emit a warning indicating the runtime is inappropriate for this object
|
||||
|
||||
runtime <- knitr::opts_knit$get("rmarkdown.runtime")
|
||||
if (!is.null(runtime) && runtime != "shiny") {
|
||||
# note that the RStudio IDE checks for this specific string to detect Shiny
|
||||
# applications in static document
|
||||
shiny_warning <- list(structure(
|
||||
"Shiny application in a static R Markdown document",
|
||||
class = "rmd_warning"))
|
||||
|
||||
# create a box exactly the same dimensions as the Shiny app would have had
|
||||
# (so the document continues to flow as it would have with the app), and
|
||||
# display a diagnostic message
|
||||
# If not rendering to a Shiny document, create a box exactly the same
|
||||
# dimensions as the Shiny app would have had (so the document continues to
|
||||
# flow as it would have with the app), and display a diagnostic message
|
||||
width <- validateCssUnit(width)
|
||||
height <- validateCssUnit(height)
|
||||
output <- tags$div(
|
||||
@@ -289,15 +290,19 @@ knit_print.shiny.appobj <- function(x, ...) {
|
||||
# for now it's not an issue, so just return the HTML and warning.
|
||||
|
||||
knitr::asis_output(htmlPreserve(format(output, indent=FALSE)),
|
||||
meta = shiny_warning, cacheable = FALSE)
|
||||
meta = shiny_rmd_warning(), cacheable = FALSE)
|
||||
}
|
||||
|
||||
# Lets us use a nicer syntax in knitr chunks than literally
|
||||
# Let us use a nicer syntax in knitr chunks than literally
|
||||
# calling output$value <- renderFoo(...) and fooOutput().
|
||||
#' @rdname knitr_methods
|
||||
#' @param inline Whether the object is printed inline.
|
||||
#' @export
|
||||
knit_print.shiny.render.function <- function(x, ...) {
|
||||
knit_print.shiny.render.function <- function(x, ..., inline = FALSE) {
|
||||
x <- htmltools::as.tags(x, inline = inline)
|
||||
output <- knitr::knit_print(tagList(x))
|
||||
attr(output, "knit_cacheable") <- FALSE
|
||||
attr(output, "knit_meta") <- append(attr(output, "knit_meta"),
|
||||
shiny_rmd_warning())
|
||||
output
|
||||
}
|
||||
|
||||
249
R/bootstrap.R
249
R/bootstrap.R
@@ -160,6 +160,8 @@ pageWithSidebar <- function(headerPanel,
|
||||
#' @param theme Alternative Bootstrap stylesheet (normally a css file within the
|
||||
#' www directory). For example, to use the theme located at
|
||||
#' \code{www/bootstrap.css} you would use \code{theme = "bootstrap.css"}.
|
||||
#' @param windowTitle The title that should be displayed by the browser window.
|
||||
#' Useful if \code{title} is not a string.
|
||||
#' @param icon Optional icon to appear on a \code{navbarMenu} tab.
|
||||
#'
|
||||
#' @return A UI defintion that can be passed to the \link{shinyUI} function.
|
||||
@@ -194,7 +196,8 @@ navbarPage <- function(title,
|
||||
collapsable = FALSE,
|
||||
fluid = TRUE,
|
||||
responsive = TRUE,
|
||||
theme = NULL) {
|
||||
theme = NULL,
|
||||
windowTitle = title) {
|
||||
|
||||
# alias title so we can avoid conflicts w/ title in withTags
|
||||
pageTitle <- title
|
||||
@@ -259,7 +262,7 @@ navbarPage <- function(title,
|
||||
|
||||
# build the page
|
||||
bootstrapPage(
|
||||
title = title,
|
||||
title = windowTitle,
|
||||
responsive = responsive,
|
||||
theme = theme,
|
||||
div(class=navbarClass,
|
||||
@@ -381,6 +384,11 @@ mainPanel <- function(..., width = 8) {
|
||||
#' determine whether the panel should be displayed.
|
||||
#' @param ... Elements to include in the panel.
|
||||
#'
|
||||
#' @note You are not recommended to use special JavaScript characters such as a
|
||||
#' period \code{.} in the input id's, but if you do use them anyway, for
|
||||
#' example, \code{inputId = "foo.bar"}, you will have to use
|
||||
#' \code{input["foo.bar"]} instead of \code{input.foo.bar} to read the input
|
||||
#' value.
|
||||
#' @examples
|
||||
#' sidebarPanel(
|
||||
#' selectInput(
|
||||
@@ -576,31 +584,13 @@ checkboxGroupInput <- function(inputId, label, choices, selected = NULL, inline
|
||||
if (!is.null(selected))
|
||||
selected <- validateSelected(selected, choices, inputId)
|
||||
|
||||
# Create tags for each of the options
|
||||
ids <- paste0(inputId, seq_along(choices))
|
||||
|
||||
checkboxes <- mapply(ids, choices, names(choices),
|
||||
SIMPLIFY = FALSE, USE.NAMES = FALSE,
|
||||
FUN = function(id, value, name) {
|
||||
inputTag <- tags$input(type = "checkbox",
|
||||
name = inputId,
|
||||
id = id,
|
||||
value = value)
|
||||
|
||||
if (value %in% selected)
|
||||
inputTag$attribs$checked <- "checked"
|
||||
|
||||
tags$label(class = if (inline) "checkbox inline" else "checkbox",
|
||||
inputTag,
|
||||
tags$span(name))
|
||||
}
|
||||
)
|
||||
options <- generateOptions(inputId, choices, selected, inline)
|
||||
|
||||
# return label and select tag
|
||||
tags$div(id = inputId,
|
||||
class = "control-group shiny-input-checkboxgroup",
|
||||
controlLabel(inputId, label),
|
||||
checkboxes)
|
||||
options)
|
||||
}
|
||||
|
||||
# Before shiny 0.9, `selected` refers to names/labels of `choices`; now it
|
||||
@@ -608,11 +598,12 @@ checkboxGroupInput <- function(inputId, label, choices, selected = NULL, inline
|
||||
validateSelected <- function(selected, choices, inputId) {
|
||||
# drop names, otherwise toJSON() keeps them too
|
||||
selected <- unname(selected)
|
||||
if (is.list(choices)) {
|
||||
# <optgroup> is not there yet
|
||||
if (any(sapply(choices, length) > 1)) return(selected)
|
||||
choices <- unlist(choices)
|
||||
}
|
||||
# if you are using optgroups, you're using shiny > 0.10.0, and you should
|
||||
# already know that `selected` must be a value instead of a label
|
||||
if (needOptgroup(choices)) return(selected)
|
||||
|
||||
if (is.list(choices)) choices <- unlist(choices)
|
||||
|
||||
nms <- names(choices)
|
||||
# labels and values are identical, no need to validate
|
||||
if (identical(nms, unname(choices))) return(selected)
|
||||
@@ -630,6 +621,29 @@ validateSelected <- function(selected, choices, inputId) {
|
||||
selected
|
||||
}
|
||||
|
||||
# generate options for radio buttons and checkbox groups (type = 'checkbox' or
|
||||
# 'radio')
|
||||
generateOptions <- function(inputId, choices, selected, inline, type = 'checkbox') {
|
||||
# create tags for each of the options
|
||||
ids <- paste0(inputId, seq_along(choices))
|
||||
# generate a list of <input type=? [checked] />
|
||||
mapply(
|
||||
ids, choices, names(choices),
|
||||
FUN = function(id, value, name) {
|
||||
inputTag <- tags$input(
|
||||
type = type, name = inputId, id = id, value = value
|
||||
)
|
||||
if (value %in% selected)
|
||||
inputTag$attribs$checked <- "checked"
|
||||
tags$label(
|
||||
class = paste(type, if (inline) "inline"),
|
||||
inputTag, tags$span(name)
|
||||
)
|
||||
},
|
||||
SIMPLIFY = FALSE, USE.NAMES = FALSE
|
||||
)
|
||||
}
|
||||
|
||||
#' Create a help text element
|
||||
#'
|
||||
#' Create help text which can be added to an input form to provide additional
|
||||
@@ -654,20 +668,43 @@ controlLabel <- function(controlName, label) {
|
||||
# Takes a vector or list, and adds names (same as the value) to any entries
|
||||
# without names.
|
||||
choicesWithNames <- function(choices) {
|
||||
if (is.null(choices)) return(choices) # ignore NULL
|
||||
# Take a vector or list, and convert to list. Also, if any children are
|
||||
# vectors with length > 1, convert those to list. If the list is unnamed,
|
||||
# convert it to a named list with blank names.
|
||||
listify <- function(obj) {
|
||||
# If a list/vector is unnamed, give it blank names
|
||||
makeNamed <- function(x) {
|
||||
if (is.null(names(x))) names(x) <- character(length(x))
|
||||
x
|
||||
}
|
||||
|
||||
# get choice names
|
||||
choiceNames <- names(choices)
|
||||
if (is.null(choiceNames))
|
||||
choiceNames <- character(length(choices))
|
||||
res <- lapply(obj, function(val) {
|
||||
if (is.list(val))
|
||||
listify(val)
|
||||
else if (length(val) == 1)
|
||||
val
|
||||
else
|
||||
makeNamed(as.list(val))
|
||||
})
|
||||
|
||||
makeNamed(res)
|
||||
}
|
||||
|
||||
choices <- listify(choices)
|
||||
if (length(choices) == 0) return(choices)
|
||||
|
||||
# Recurse into any subgroups
|
||||
choices <- mapply(choices, names(choices), FUN = function(choice, name) {
|
||||
if (!is.list(choice)) return(choice)
|
||||
if (name == "") stop('All sub-lists in "choices" must be named.')
|
||||
choicesWithNames(choice)
|
||||
}, SIMPLIFY = FALSE)
|
||||
|
||||
# default missing names to choice values
|
||||
missingNames <- choiceNames == ""
|
||||
choiceNames[missingNames] <- paste(choices)[missingNames]
|
||||
names(choices) <- choiceNames
|
||||
missing <- names(choices) == ""
|
||||
names(choices)[missing] <- as.character(choices)[missing]
|
||||
|
||||
# return choices
|
||||
return (choices)
|
||||
choices
|
||||
}
|
||||
|
||||
#' Create a select list input control
|
||||
@@ -707,21 +744,11 @@ selectInput <- function(inputId, label, choices, selected = NULL,
|
||||
|
||||
# default value if it's not specified
|
||||
if (is.null(selected)) {
|
||||
if (!multiple) selected <- choices[[1]]
|
||||
if (!multiple) selected <- firstChoice(choices)
|
||||
} else selected <- validateSelected(selected, choices, inputId)
|
||||
|
||||
# Create tags for each of the options
|
||||
options <- HTML(paste("<option value=\"",
|
||||
htmlEscape(choices),
|
||||
"\"",
|
||||
ifelse(choices %in% selected, " selected", ""),
|
||||
">",
|
||||
htmlEscape(names(choices)),
|
||||
"</option>",
|
||||
sep = "", collapse = "\n"));
|
||||
|
||||
# create select tag and add options
|
||||
selectTag <- tags$select(id = inputId, options)
|
||||
selectTag <- tags$select(id = inputId, selectOptions(choices, selected))
|
||||
if (multiple)
|
||||
selectTag$attribs$multiple <- "multiple"
|
||||
|
||||
@@ -731,6 +758,44 @@ selectInput <- function(inputId, label, choices, selected = NULL,
|
||||
selectizeIt(inputId, res, NULL, width, nonempty = !multiple && !("" %in% choices))
|
||||
}
|
||||
|
||||
firstChoice <- function(choices) {
|
||||
if (length(choices) == 0L) return()
|
||||
choice <- choices[[1]]
|
||||
if (is.list(choice)) firstChoice(choice) else choice
|
||||
}
|
||||
|
||||
# Create tags for each of the options; use <optgroup> if necessary.
|
||||
# This returns a HTML string instead of tags, because of the 'selected'
|
||||
# attribute.
|
||||
selectOptions <- function(choices, selected = NULL) {
|
||||
html <- mapply(choices, names(choices), FUN = function(choice, label) {
|
||||
if (is.list(choice)) {
|
||||
# If sub-list, create an optgroup and recurse into the sublist
|
||||
sprintf(
|
||||
'<optgroup label="%s">\n%s\n</optgroup>',
|
||||
htmlEscape(label),
|
||||
selectOptions(choice, selected)
|
||||
)
|
||||
|
||||
} else {
|
||||
# If single item, just return option string
|
||||
sprintf(
|
||||
'<option value="%s"%s>%s</option>',
|
||||
htmlEscape(choice),
|
||||
if (choice %in% selected) ' selected' else '',
|
||||
htmlEscape(label)
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
HTML(paste(html, collapse = '\n'))
|
||||
}
|
||||
|
||||
# need <optgroup> when choices contains sub-lists
|
||||
needOptgroup <- function(choices) {
|
||||
any(vapply(choices, is.list, logical(1)))
|
||||
}
|
||||
|
||||
#' @rdname selectInput
|
||||
#' @param ... Arguments passed to \code{selectInput()}.
|
||||
#' @param options A list of options. See the documentation of \pkg{selectize.js}
|
||||
@@ -812,33 +877,14 @@ radioButtons <- function(inputId, label, choices, selected = NULL, inline = FALS
|
||||
selected <- if (is.null(selected)) choices[[1]] else {
|
||||
validateSelected(selected, choices, inputId)
|
||||
}
|
||||
if (length(selected) > 1) stop("The 'selected' argument must be of length 1")
|
||||
|
||||
# Create tags for each of the options
|
||||
ids <- paste0(inputId, seq_along(choices))
|
||||
|
||||
inputTags <- mapply(ids, choices, names(choices),
|
||||
SIMPLIFY = FALSE, USE.NAMES = FALSE,
|
||||
FUN = function(id, value, name) {
|
||||
inputTag <- tags$input(type = "radio",
|
||||
name = inputId,
|
||||
id = id,
|
||||
value = value)
|
||||
|
||||
if (identical(value, selected))
|
||||
inputTag$attribs$checked = "checked"
|
||||
|
||||
# Put the label text in a span
|
||||
tags$label(class = if (inline) "radio inline" else "radio",
|
||||
inputTag,
|
||||
tags$span(name)
|
||||
)
|
||||
}
|
||||
)
|
||||
options <- generateOptions(inputId, choices, selected, inline, type = 'radio')
|
||||
|
||||
tags$div(id = inputId,
|
||||
class = 'control-group shiny-input-radiogroup',
|
||||
label %AND% tags$label(class = "control-label", `for` = inputId, label),
|
||||
inputTags)
|
||||
options)
|
||||
}
|
||||
|
||||
#' Create a submit button
|
||||
@@ -1490,13 +1536,15 @@ buildTabset <- function(tabs,
|
||||
#' text will be included within an HTML \code{div} tag by default.
|
||||
#' @param outputId output variable to read the value from
|
||||
#' @param container a function to generate an HTML element to contain the text
|
||||
#' @param inline use an inline (\code{span()}) or block container (\code{div()})
|
||||
#' for the output
|
||||
#' @return A text output element that can be included in a panel
|
||||
#' @details Text is HTML-escaped prior to rendering. This element is often used
|
||||
#' to display \link{renderText} output variables.
|
||||
#' to display \link{renderText} output variables.
|
||||
#' @examples
|
||||
#' h3(textOutput("caption"))
|
||||
#' @export
|
||||
textOutput <- function(outputId, container = div) {
|
||||
textOutput <- function(outputId, container = if (inline) span else div, inline = FALSE) {
|
||||
container(id = outputId, class = "shiny-text-output")
|
||||
}
|
||||
|
||||
@@ -1530,6 +1578,7 @@ verbatimTextOutput <- function(outputId) {
|
||||
#' \code{"400px"}, \code{"auto"}) or a number, which will be coerced to a
|
||||
#' string and have \code{"px"} appended.
|
||||
#' @param height Image height
|
||||
#' @inheritParams textOutput
|
||||
#' @return An image output element that can be included in a panel
|
||||
#' @examples
|
||||
#' # Show an image
|
||||
@@ -1537,38 +1586,45 @@ verbatimTextOutput <- function(outputId) {
|
||||
#' imageOutput("dataImage")
|
||||
#' )
|
||||
#' @export
|
||||
imageOutput <- function(outputId, width = "100%", height="400px") {
|
||||
imageOutput <- function(outputId, width = "100%", height="400px", inline=FALSE) {
|
||||
style <- paste("width:", validateCssUnit(width), ";",
|
||||
"height:", validateCssUnit(height))
|
||||
div(id = outputId, class = "shiny-image-output", style = style)
|
||||
container <- if (inline) span else div
|
||||
container(id = outputId, class = "shiny-image-output", style = style)
|
||||
}
|
||||
|
||||
#' Create an plot output element
|
||||
#'
|
||||
#' Render a \link{renderPlot} within an application page.
|
||||
#' @param outputId output variable to read the plot from
|
||||
#' @param width Plot width. Must be a valid CSS unit (like \code{"100\%"},
|
||||
#' \code{"400px"}, \code{"auto"}) or a number, which will be coerced to a
|
||||
#' string and have \code{"px"} appended.
|
||||
#' @param height Plot height
|
||||
#' @param width,height Plot width/height. Must be a valid CSS unit (like
|
||||
#' \code{"100\%"}, \code{"400px"}, \code{"auto"}) or a number, which will be
|
||||
#' coerced to a string and have \code{"px"} appended. These two arguments are
|
||||
#' ignored when \code{inline = TRUE}, in which case the width/height of a plot
|
||||
#' must be specified in \code{renderPlot()}.
|
||||
#' @param clickId If not \code{NULL}, the plot will send coordinates to the
|
||||
#' server whenever it is clicked. This information will be accessible on the
|
||||
#' \code{input} object using \code{input$}\emph{\code{clickId}}. The value will be a
|
||||
#' named list or vector with \code{x} and \code{y} elements indicating the
|
||||
#' mouse position in user units.
|
||||
#' \code{input} object using \code{input$}\emph{\code{clickId}}. The value
|
||||
#' will be a named list or vector with \code{x} and \code{y} elements
|
||||
#' indicating the mouse position in user units.
|
||||
#' @param hoverId If not \code{NULL}, the plot will send coordinates to the
|
||||
#' server whenever the mouse pauses on the plot for more than the number of
|
||||
#' milliseconds determined by \code{hoverTimeout}. This information will be
|
||||
# accessible on the \code{input} object using \code{input$}\emph{\code{clickId}}.
|
||||
#' The value will be \code{NULL} if the user is not hovering, and a named
|
||||
#' list or vector with \code{x} and \code{y} elements indicating the mouse
|
||||
#' position in user units.
|
||||
#' accessible on the \code{input} object using
|
||||
#' \code{input$}\emph{\code{clickId}}. The value will be \code{NULL} if the
|
||||
#' user is not hovering, and a named list or vector with \code{x} and \code{y}
|
||||
#' elements indicating the mouse position in user units.
|
||||
#' @param hoverDelay The delay for hovering, in milliseconds.
|
||||
#' @param hoverDelayType The type of algorithm for limiting the number of hover
|
||||
#' events. Use \code{"throttle"} to limit the number of hover events to one
|
||||
#' every \code{hoverDelay} milliseconds. Use \code{"debounce"} to suspend
|
||||
#' events while the cursor is moving, and wait until the cursor has been at
|
||||
#' rest for \code{hoverDelay} milliseconds before sending an event.
|
||||
#' @inheritParams textOutput
|
||||
#' @note The arguments \code{clickId} and \code{hoverId} only work for R base
|
||||
#' graphics (see the \pkg{\link{graphics}} package). They do not work for
|
||||
#' \pkg{\link[grid:grid-package]{grid}}-based graphics, such as \pkg{ggplot2},
|
||||
#' \pkg{lattice}, and so on.
|
||||
#' @return A plot output element that can be included in a panel
|
||||
#' @examples
|
||||
#' # Show a plot of the generated distribution
|
||||
@@ -1578,7 +1634,7 @@ imageOutput <- function(outputId, width = "100%", height="400px") {
|
||||
#' @export
|
||||
plotOutput <- function(outputId, width = "100%", height="400px",
|
||||
clickId = NULL, hoverId = NULL, hoverDelay = 300,
|
||||
hoverDelayType = c("debounce", "throttle")) {
|
||||
hoverDelayType = c("debounce", "throttle"), inline = FALSE) {
|
||||
if (is.null(clickId) && is.null(hoverId)) {
|
||||
hoverDelay <- NULL
|
||||
hoverDelayType <- NULL
|
||||
@@ -1586,9 +1642,12 @@ plotOutput <- function(outputId, width = "100%", height="400px",
|
||||
hoverDelayType <- match.arg(hoverDelayType)[[1]]
|
||||
}
|
||||
|
||||
style <- paste("width:", validateCssUnit(width), ";",
|
||||
"height:", validateCssUnit(height))
|
||||
div(id = outputId, class = "shiny-plot-output", style = style,
|
||||
style <- if (!inline) {
|
||||
paste("width:", validateCssUnit(width), ";", "height:", validateCssUnit(height))
|
||||
}
|
||||
|
||||
container <- if (inline) span else div
|
||||
container(id = outputId, class = "shiny-plot-output", style = style,
|
||||
`data-click-id` = clickId,
|
||||
`data-hover-id` = hoverId,
|
||||
`data-hover-delay` = hoverDelay,
|
||||
@@ -1640,19 +1699,19 @@ dataTableOutput <- function(outputId) {
|
||||
#' server side. It is currently just an alias for \code{htmlOutput}.
|
||||
#'
|
||||
#' @param outputId output variable to read the value from
|
||||
#' @inheritParams textOutput
|
||||
#' @return An HTML output element that can be included in a panel
|
||||
#' @examples
|
||||
#' htmlOutput("summary")
|
||||
#' @export
|
||||
htmlOutput <- function(outputId) {
|
||||
div(id = outputId, class="shiny-html-output")
|
||||
htmlOutput <- function(outputId, inline = FALSE) {
|
||||
container <- if (inline) span else div
|
||||
container(id = outputId, class="shiny-html-output")
|
||||
}
|
||||
|
||||
#' @rdname htmlOutput
|
||||
#' @export
|
||||
uiOutput <- function(outputId) {
|
||||
htmlOutput(outputId)
|
||||
}
|
||||
uiOutput <- htmlOutput
|
||||
|
||||
#' Create a download button or link
|
||||
#'
|
||||
|
||||
@@ -55,7 +55,7 @@ renderReactLog <- function() {
|
||||
}
|
||||
|
||||
.graphAppend <- function(logEntry, domain = getDefaultReactiveDomain()) {
|
||||
if (isTRUE(getOption('shiny.reactlog', FALSE)))
|
||||
if (isTRUE(getOption('shiny.reactlog')))
|
||||
.graphEnv$log <- c(.graphEnv$log, list(logEntry))
|
||||
|
||||
if (!is.null(domain)) {
|
||||
|
||||
@@ -34,7 +34,7 @@ plotPNG <- function(func, filename=tempfile(fileext='.png'),
|
||||
# Finally, if neither quartz nor Cairo, use png().
|
||||
if (capabilities("aqua")) {
|
||||
pngfun <- png
|
||||
} else if (getOption('shiny.usecairo', TRUE) &&
|
||||
} else if ((getOption('shiny.usecairo') %OR% TRUE) &&
|
||||
nchar(system.file(package = "Cairo"))) {
|
||||
pngfun <- Cairo::CairoPNG
|
||||
} else {
|
||||
|
||||
@@ -5,7 +5,7 @@ reactLogHandler <- function(req) {
|
||||
if (!identical(req$PATH_INFO, '/reactlog'))
|
||||
return(NULL)
|
||||
|
||||
if (!getOption('shiny.reactlog', FALSE)) {
|
||||
if (!isTRUE(getOption('shiny.reactlog'))) {
|
||||
return(NULL)
|
||||
}
|
||||
|
||||
|
||||
@@ -281,7 +281,7 @@ HandlerManager <- setRefClass("HandlerManager",
|
||||
createHttpuvApp = function() {
|
||||
list(
|
||||
onHeaders = function(req) {
|
||||
maxSize <- getOption('shiny.maxRequestSize', 5 * 1024 * 1024)
|
||||
maxSize <- getOption('shiny.maxRequestSize') %OR% (5 * 1024 * 1024)
|
||||
if (maxSize <= 0)
|
||||
return(NULL)
|
||||
|
||||
@@ -306,7 +306,7 @@ HandlerManager <- setRefClass("HandlerManager",
|
||||
function (req) {
|
||||
return(handlers$invoke(req))
|
||||
},
|
||||
getOption('shiny.sharedSecret', NULL)
|
||||
getOption('shiny.sharedSecret')
|
||||
),
|
||||
onWSOpen = function(ws) {
|
||||
return(wsHandlers$invoke(ws))
|
||||
@@ -314,7 +314,7 @@ HandlerManager <- setRefClass("HandlerManager",
|
||||
)
|
||||
},
|
||||
.httpServer = function(handler, sharedSecret) {
|
||||
filter <- getOption('shiny.http.response.filter', NULL)
|
||||
filter <- getOption('shiny.http.response.filter')
|
||||
if (is.null(filter))
|
||||
filter <- function(req, response) response
|
||||
|
||||
@@ -329,11 +329,11 @@ HandlerManager <- setRefClass("HandlerManager",
|
||||
response <- handler(req)
|
||||
if (is.null(response))
|
||||
response <- httpResponse(404, content="<h1>Not Found</h1>")
|
||||
|
||||
|
||||
if (inherits(response, "httpResponse")) {
|
||||
headers <- as.list(response$headers)
|
||||
headers$'Content-Type' <- response$content_type
|
||||
|
||||
|
||||
response <- filter(req, response)
|
||||
return(list(status=response$status,
|
||||
body=response$content,
|
||||
|
||||
@@ -98,7 +98,7 @@ ReactiveEnvironment <- setRefClass(
|
||||
},
|
||||
currentContext = function() {
|
||||
if (is.null(.currentContext)) {
|
||||
if (isTRUE(getOption('shiny.suppressMissingContextError', FALSE))) {
|
||||
if (isTRUE(getOption('shiny.suppressMissingContextError'))) {
|
||||
return(getDummyContext())
|
||||
} else {
|
||||
stop('Operation not allowed without an active reactive context. ',
|
||||
@@ -138,7 +138,7 @@ ReactiveEnvironment <- setRefClass(
|
||||
reactiveEnvironment <<- ReactiveEnvironment$new()
|
||||
return(reactiveEnvironment)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
# Causes any pending invalidations to run.
|
||||
flushReact <- function() {
|
||||
|
||||
@@ -75,6 +75,7 @@ createMockDomain <- function() {
|
||||
#
|
||||
## ------------------------------------------------------------------------
|
||||
|
||||
#' @name domains
|
||||
#' @rdname domains
|
||||
#' @export
|
||||
getDefaultReactiveDomain <- function() {
|
||||
|
||||
179
R/run-url.R
179
R/run-url.R
@@ -1,112 +1,22 @@
|
||||
#' Run a Shiny application from https://gist.github.com
|
||||
#'
|
||||
#' Download and launch a Shiny application that is hosted on GitHub as a gist.
|
||||
#'
|
||||
#' @param gist The identifier of the gist. For example, if the gist is
|
||||
#' https://gist.github.com/jcheng5/3239667, then \code{3239667},
|
||||
#' \code{'3239667'}, and \code{'https://gist.github.com/jcheng5/3239667'}
|
||||
#' are all valid values.
|
||||
#' @param port The TCP port that the application should listen on. Defaults to
|
||||
#' choosing a random port.
|
||||
#' @param 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.
|
||||
#'
|
||||
#' @examples
|
||||
#' \dontrun{
|
||||
#' runGist(3239667)
|
||||
#' runGist("https://gist.github.com/jcheng5/3239667")
|
||||
#'
|
||||
#' # Old URL format without username
|
||||
#' runGist("https://gist.github.com/3239667")
|
||||
#' }
|
||||
#'
|
||||
#' @export
|
||||
runGist <- function(gist,
|
||||
port=NULL,
|
||||
launch.browser=getOption('shiny.launch.browser',
|
||||
interactive())) {
|
||||
|
||||
gistUrl <- if (is.numeric(gist) || grepl('^[0-9a-f]+$', gist)) {
|
||||
sprintf('https://gist.github.com/%s/download', gist)
|
||||
} else if(grepl('^https://gist.github.com/([^/]+/)?([0-9a-f]+)$', gist)) {
|
||||
paste(gist, '/download', sep='')
|
||||
} else {
|
||||
stop('Unrecognized gist identifier format')
|
||||
}
|
||||
|
||||
runUrl(gistUrl, filetype=".tar.gz", subdir=NULL, port=port,
|
||||
launch.browser=launch.browser)
|
||||
}
|
||||
|
||||
|
||||
#' Run a Shiny application from a GitHub repository
|
||||
#'
|
||||
#' Download and launch a Shiny application that is hosted in a GitHub repository.
|
||||
#'
|
||||
#' @param repo Name of the repository
|
||||
#' @param username GitHub username
|
||||
#' @param ref Desired git reference. Could be a commit, tag, or branch
|
||||
#' name. Defaults to \code{"master"}.
|
||||
#' @param subdir A subdirectory in the repository that contains the app. By
|
||||
#' default, this function will run an app from the top level of the repo, but
|
||||
#' you can use a path such as `\code{"inst/shinyapp"}.
|
||||
#' @param port The TCP port that the application should listen on. Defaults to
|
||||
#' choosing a random port.
|
||||
#' @param 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.
|
||||
#'
|
||||
#' @examples
|
||||
#' \dontrun{
|
||||
#' runGitHub("shiny_example", "rstudio")
|
||||
#'
|
||||
#' # Can run an app from a subdirectory in the repo
|
||||
#' runGitHub("shiny_example", "rstudio", subdir = "inst/shinyapp/")
|
||||
#' }
|
||||
#'
|
||||
#' @export
|
||||
runGitHub <- function(repo, username = getOption("github.user"),
|
||||
ref = "master", subdir = NULL, port = NULL,
|
||||
launch.browser = getOption('shiny.launch.browser', interactive())) {
|
||||
|
||||
if (is.null(ref)) {
|
||||
stop("Must specify either a ref. ")
|
||||
}
|
||||
|
||||
message("Downloading github repo(s) ",
|
||||
paste(repo, ref, sep = "/", collapse = ", "),
|
||||
" from ",
|
||||
paste(username, collapse = ", "))
|
||||
name <- paste(username, "-", repo, sep = "")
|
||||
|
||||
url <- paste("https://github.com/", username, "/", repo, "/archive/",
|
||||
ref, ".tar.gz", sep = "")
|
||||
|
||||
runUrl(url, subdir=subdir, port=port, launch.browser=launch.browser)
|
||||
}
|
||||
|
||||
|
||||
#' Run a Shiny application from a URL
|
||||
#'
|
||||
#' Download and launch a Shiny application that is hosted at a downloadable
|
||||
#' URL. The Shiny application must be saved in a .zip, .tar, or .tar.gz file.
|
||||
#' The Shiny application files must be contained in a subdirectory in the
|
||||
#' archive. For example, the files might be \code{myapp/server.r} and
|
||||
#' \code{myapp/ui.r}.
|
||||
#'
|
||||
#' \code{runUrl()} downloads and launches a Shiny application that is hosted at
|
||||
#' a downloadable URL. The Shiny application must be saved in a .zip, .tar, or
|
||||
#' .tar.gz file. The Shiny application files must be contained in the root
|
||||
#' directory or a subdirectory in the archive. For example, the files might be
|
||||
#' \code{myapp/server.r} and \code{myapp/ui.r}. The functions \code{runGitHub()}
|
||||
#' and \code{runGist()} are based on \code{runUrl()}, using URL's from GitHub
|
||||
#' (\url{https://github.com}) and GitHub gists (\url{https://gist.github.com}),
|
||||
#' respectively.
|
||||
#' @param url URL of the application.
|
||||
#' @param filetype The file type (\code{".zip"}, \code{".tar"}, or
|
||||
#' \code{".tar.gz"}. Defaults to the file extension taken from the url.
|
||||
#' @param subdir A subdirectory in the repository that contains the app. By
|
||||
#' default, this function will run an app from the top level of the repo, but
|
||||
#' you can use a path such as `\code{"inst/shinyapp"}.
|
||||
#' @param port The TCP port that the application should listen on. Defaults to
|
||||
#' choosing a random port.
|
||||
#' @param 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.
|
||||
#'
|
||||
#' @param ... Other arguments to be passed to \code{\link{runApp}()}, such as
|
||||
#' \code{port} and \code{launch.browser}.
|
||||
#' @export
|
||||
#' @examples
|
||||
#' \dontrun{
|
||||
#' runUrl('https://github.com/rstudio/shiny_example/archive/master.tar.gz')
|
||||
@@ -115,10 +25,7 @@ runGitHub <- function(repo, username = getOption("github.user"),
|
||||
#' runUrl("https://github.com/rstudio/shiny_example/archive/master.zip",
|
||||
#' subdir = "inst/shinyapp/")
|
||||
#' }
|
||||
#'
|
||||
#' @export
|
||||
runUrl <- function(url, filetype = NULL, subdir = NULL, port = NULL,
|
||||
launch.browser = getOption('shiny.launch.browser', interactive())) {
|
||||
runUrl <- function(url, filetype = NULL, subdir = NULL, ...) {
|
||||
|
||||
if (!is.null(subdir) && ".." %in% strsplit(subdir, '/')[[1]])
|
||||
stop("'..' not allowed in subdir")
|
||||
@@ -163,5 +70,65 @@ runUrl <- function(url, filetype = NULL, subdir = NULL, port = NULL,
|
||||
if (!file_test('-d', appdir)) appdir <- dirname(appdir)
|
||||
|
||||
if (!is.null(subdir)) appdir <- file.path(appdir, subdir)
|
||||
runApp(appdir, port=port, launch.browser=launch.browser)
|
||||
runApp(appdir, ...)
|
||||
}
|
||||
|
||||
#' @rdname runUrl
|
||||
#' @param gist The identifier of the gist. For example, if the gist is
|
||||
#' https://gist.github.com/jcheng5/3239667, then \code{3239667},
|
||||
#' \code{'3239667'}, and \code{'https://gist.github.com/jcheng5/3239667'} are
|
||||
#' all valid values.
|
||||
#' @export
|
||||
#' @examples
|
||||
#' \dontrun{
|
||||
#' runGist(3239667)
|
||||
#' runGist("https://gist.github.com/jcheng5/3239667")
|
||||
#'
|
||||
#' # Old URL format without username
|
||||
#' runGist("https://gist.github.com/3239667")
|
||||
#' }
|
||||
#'
|
||||
runGist <- function(gist, ...) {
|
||||
|
||||
gistUrl <- if (is.numeric(gist) || grepl('^[0-9a-f]+$', gist)) {
|
||||
sprintf('https://gist.github.com/%s/download', gist)
|
||||
} else if(grepl('^https://gist.github.com/([^/]+/)?([0-9a-f]+)$', gist)) {
|
||||
paste(gist, '/download', sep='')
|
||||
} else {
|
||||
stop('Unrecognized gist identifier format')
|
||||
}
|
||||
|
||||
runUrl(gistUrl, filetype=".tar.gz", ...)
|
||||
}
|
||||
|
||||
|
||||
#' @rdname runUrl
|
||||
#' @param repo Name of the repository.
|
||||
#' @param username GitHub username. If \code{repo} is of the form
|
||||
#' \code{"username/repo"}, \code{username} will be taken from \code{repo}.
|
||||
#' @param ref Desired git reference. Could be a commit, tag, or branch name.
|
||||
#' Defaults to \code{"master"}.
|
||||
#' @export
|
||||
#' @examples
|
||||
#' \dontrun{
|
||||
#' runGitHub("shiny_example", "rstudio")
|
||||
#' # or runGitHub("rstudio/shiny_example")
|
||||
#'
|
||||
#' # Can run an app from a subdirectory in the repo
|
||||
#' runGitHub("shiny_example", "rstudio", subdir = "inst/shinyapp/")
|
||||
#' }
|
||||
runGitHub <- function(repo, username = getOption("github.user"),
|
||||
ref = "master", subdir = NULL, ...) {
|
||||
|
||||
if (grepl('/', repo)) {
|
||||
res <- strsplit(repo, '/')[[1]]
|
||||
if (length(res) != 2) stop("'repo' must be of the form 'username/repo'")
|
||||
username <- res[1]
|
||||
repo <- res[2]
|
||||
}
|
||||
|
||||
url <- paste("https://github.com/", username, "/", repo, "/archive/",
|
||||
ref, ".tar.gz", sep = "")
|
||||
|
||||
runUrl(url, subdir=subdir, ...)
|
||||
}
|
||||
|
||||
15
R/server.R
15
R/server.R
@@ -249,8 +249,11 @@ decodeMessage <- function(data) {
|
||||
packBits(rawToBits(data[pos:(pos+3)]), type='integer')
|
||||
}
|
||||
|
||||
if (readInt(1) != 0x01020202L)
|
||||
return(fromJSON(rawToChar(data), asText=TRUE, simplify=FALSE))
|
||||
if (readInt(1) != 0x01020202L) {
|
||||
# use native encoding for the message
|
||||
nativeData <- iconv(rawToChar(data), 'UTF-8')
|
||||
return(fromJSON(nativeData, asText=TRUE, simplify=FALSE))
|
||||
}
|
||||
|
||||
i <- 5
|
||||
parts <- list()
|
||||
@@ -278,7 +281,7 @@ createAppHandlers <- function(httpHandlers, serverFuncSource) {
|
||||
# This value, if non-NULL, must be present on all HTTP and WebSocket
|
||||
# requests as the Shiny-Shared-Secret header or else access will be
|
||||
# denied (403 response for HTTP, and instant close for websocket).
|
||||
sharedSecret <- getOption('shiny.sharedSecret', NULL)
|
||||
sharedSecret <- getOption('shiny.sharedSecret')
|
||||
|
||||
appHandlers <- list(
|
||||
http = joinHandlers(c(
|
||||
@@ -303,7 +306,7 @@ createAppHandlers <- function(httpHandlers, serverFuncSource) {
|
||||
if (is.character(msg))
|
||||
msg <- charToRaw(msg)
|
||||
|
||||
if (getOption('shiny.trace', FALSE)) {
|
||||
if (isTRUE(getOption('shiny.trace'))) {
|
||||
if (binary)
|
||||
message("RECV ", '$$binary data$$')
|
||||
else
|
||||
@@ -634,7 +637,9 @@ runApp <- function(appDir=getwd(),
|
||||
if (is.character(appDir)) {
|
||||
desc <- file.path.ci(appDir, "DESCRIPTION")
|
||||
if (file.exists(desc)) {
|
||||
settings <- read.dcf(desc)
|
||||
con <- file(desc, encoding = checkEncoding(desc))
|
||||
on.exit(close(con), add = TRUE)
|
||||
settings <- read.dcf(con)
|
||||
if ("DisplayMode" %in% colnames(settings)) {
|
||||
mode <- settings[1,"DisplayMode"]
|
||||
if (mode == "Showcase") {
|
||||
|
||||
15
R/shiny.R
15
R/shiny.R
@@ -15,7 +15,8 @@ NULL
|
||||
#' @name shiny-package
|
||||
#' @aliases shiny
|
||||
#' @docType package
|
||||
#' @import htmltools httpuv caTools RJSONIO xtable digest methods
|
||||
#' @import htmltools httpuv caTools xtable digest methods
|
||||
#' @importFrom RJSONIO fromJSON
|
||||
NULL
|
||||
|
||||
createUniqueId <- function(bytes, prefix = "", suffix = "") {
|
||||
@@ -31,6 +32,10 @@ createUniqueId <- function(bytes, prefix = "", suffix = "") {
|
||||
})
|
||||
}
|
||||
|
||||
toJSON <- function(x, ..., digits = getOption("shiny.json.digits", 16)) {
|
||||
RJSONIO::toJSON(x, digits = digits, ...)
|
||||
}
|
||||
|
||||
# Call the workerId func with no args to get the worker id, and with an arg to
|
||||
# set it.
|
||||
#
|
||||
@@ -488,11 +493,13 @@ ShinySession <- setRefClass(
|
||||
if (closed){
|
||||
return()
|
||||
}
|
||||
if (getOption('shiny.trace', FALSE))
|
||||
if (isTRUE(getOption('shiny.trace')))
|
||||
message('SEND ',
|
||||
gsub('(?m)base64,[a-zA-Z0-9+/=]+','[base64 data]',json,perl=TRUE))
|
||||
if (getOption('shiny.transcode.json', TRUE))
|
||||
json <- iconv(json, to='UTF-8')
|
||||
# first convert to native encoding, then to UTF8, otherwise we may get the
|
||||
# error in Chrome "WebSocket connection failed: Could not decode a text
|
||||
# frame as UTF-8"
|
||||
json <- enc2utf8(enc2native(json))
|
||||
.websocket$send(json)
|
||||
},
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ renderPage <- function(ui, connection, showcase=0) {
|
||||
|
||||
deps <- c(
|
||||
list(
|
||||
htmlDependency("json2", "2014.02.04", c(href="shared"), script = "json2-min.js"),
|
||||
htmlDependency("jquery", "1.11.0", c(href="shared"), script = "jquery.js"),
|
||||
htmlDependency("shiny", packageVersion("shiny"), c(href="shared"),
|
||||
script = "shiny.js", stylesheet = "shiny.css")
|
||||
@@ -128,6 +129,6 @@ uiHttpHandler <- function(ui, path = "/") {
|
||||
ui
|
||||
renderPage(uiValue, textConn, showcaseMode)
|
||||
html <- paste(textConnectionValue(textConn), collapse='\n')
|
||||
return(httpResponse(200, content=html))
|
||||
return(httpResponse(200, content=enc2utf8(html)))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,24 +16,26 @@ globalVariables('func')
|
||||
#'
|
||||
#' @export
|
||||
markRenderFunction <- function(uiFunc, renderFunc) {
|
||||
class(renderFunc) <- c("shiny.render.function", "function")
|
||||
attr(renderFunc, "outputFunc") <- uiFunc
|
||||
renderFunc
|
||||
structure(renderFunc,
|
||||
class = c("shiny.render.function", "function"),
|
||||
outputFunc = uiFunc)
|
||||
}
|
||||
|
||||
useRenderFunction <- function(renderFunc) {
|
||||
useRenderFunction <- function(renderFunc, inline = FALSE) {
|
||||
outputFunction <- attr(renderFunc, "outputFunc")
|
||||
id <- createUniqueId(8, "out")
|
||||
o <- getDefaultReactiveDomain()$output
|
||||
if (!is.null(o))
|
||||
o[[id]] <- renderFunc
|
||||
return(outputFunction(id))
|
||||
if (is.logical(formals(outputFunction)[["inline"]])) {
|
||||
outputFunction(id, inline = inline)
|
||||
} else outputFunction(id)
|
||||
}
|
||||
|
||||
#' @export
|
||||
#' @method as.tags shiny.render.function
|
||||
as.tags.shiny.render.function <- function(x, ...) {
|
||||
useRenderFunction(x)
|
||||
as.tags.shiny.render.function <- function(x, ..., inline = FALSE) {
|
||||
useRenderFunction(x, inline = inline)
|
||||
}
|
||||
|
||||
#' Plot Output
|
||||
@@ -48,16 +50,13 @@ as.tags.shiny.render.function <- function(x, ...) {
|
||||
#' the output, see \code{\link{plotPNG}}.
|
||||
#'
|
||||
#' @param expr An expression that generates a plot.
|
||||
#' @param width The width of the rendered plot, in pixels; or \code{'auto'} to
|
||||
#' use the \code{offsetWidth} of the HTML element that is bound to this plot.
|
||||
#' You can also pass in a function that returns the width in pixels or
|
||||
#' \code{'auto'}; in the body of the function you may reference reactive
|
||||
#' values and functions.
|
||||
#' @param height The height of the rendered plot, in pixels; or \code{'auto'} to
|
||||
#' use the \code{offsetHeight} of the HTML element that is bound to this plot.
|
||||
#' You can also pass in a function that returns the width in pixels or
|
||||
#' \code{'auto'}; in the body of the function you may reference reactive
|
||||
#' values and functions.
|
||||
#' @param width,height The width/height of the rendered plot, in pixels; or
|
||||
#' \code{'auto'} to use the \code{offsetWidth}/\code{offsetHeight} of the HTML
|
||||
#' element that is bound to this plot. You can also pass in a function that
|
||||
#' returns the width/height in pixels or \code{'auto'}; in the body of the
|
||||
#' function you may reference reactive values and functions. When rendering an
|
||||
#' inline plot, you must provide numeric values (in pixels) to both
|
||||
#' \code{width} and \code{height}.
|
||||
#' @param res Resolution of resulting plot, in pixels per inch. This value is
|
||||
#' passed to \code{\link{png}}. Note that this affects the resolution of PNG
|
||||
#' rendering in R; it won't change the actual ppi of the browser.
|
||||
@@ -94,10 +93,8 @@ renderPlot <- function(expr, width='auto', height='auto', res=72, ...,
|
||||
# div needs to adapt to the height of renderPlot. By default, plotOutput
|
||||
# sets the height to 400px, so to make it adapt we need to override it
|
||||
# with NULL.
|
||||
outputFunc <- if (identical(height, 'auto'))
|
||||
plotOutput
|
||||
else
|
||||
function(outputId) plotOutput(outputId, height = NULL)
|
||||
outputFunc <- plotOutput
|
||||
if (!identical(height, 'auto')) formals(outputFunc)['height'] <- list(NULL)
|
||||
|
||||
return(markRenderFunction(outputFunc, function(shinysession, name, ...) {
|
||||
if (!is.null(widthWrapper))
|
||||
@@ -124,9 +121,13 @@ renderPlot <- function(expr, width='auto', height='auto', res=72, ...,
|
||||
|
||||
coordmap <- NULL
|
||||
plotFunc <- function() {
|
||||
# Actually perform the plotting: use capture.output() to suppress output
|
||||
# to console, and print func() if it returns a visible value
|
||||
capture.output(func())
|
||||
# Actually perform the plotting
|
||||
result <- withVisible(func())
|
||||
if (result$visible) {
|
||||
# Use capture.output to squelch printing to the actual console; we
|
||||
# are only interested in plot output
|
||||
capture.output(print(result$value))
|
||||
}
|
||||
|
||||
# Now capture some graphics device info before we close it
|
||||
usrCoords <- par('usr')
|
||||
@@ -316,7 +317,7 @@ renderTable <- function(expr, ..., env=parent.frame(), quoted=FALSE, func=NULL)
|
||||
}
|
||||
|
||||
markRenderFunction(tableOutput, function() {
|
||||
classNames <- getOption('shiny.table.class', 'data table table-bordered table-condensed')
|
||||
classNames <- getOption('shiny.table.class') %OR% 'data table table-bordered table-condensed'
|
||||
data <- func()
|
||||
|
||||
if (is.null(data) || identical(data, data.frame()))
|
||||
|
||||
@@ -50,7 +50,7 @@ showcaseHead <- function() {
|
||||
href="shared/shiny-showcase.css"),
|
||||
if (file.exists(mdfile))
|
||||
script(type="text/markdown", id="showcase-markdown-content",
|
||||
paste(readLines(mdfile, warn = FALSE), collapse="\n"))
|
||||
paste(readUTF8(mdfile), collapse="\n"))
|
||||
else ""
|
||||
))
|
||||
|
||||
@@ -106,8 +106,7 @@ showcaseCodeTabs <- function(codeLicense) {
|
||||
# we need to prevent the indentation of <code> ... </code>
|
||||
HTML(format(tags$code(
|
||||
class="language-r",
|
||||
paste(readLines(file.path.ci(getwd(), rFile), warn=FALSE),
|
||||
collapse="\n")
|
||||
paste(readUTF8(file.path.ci(getwd(), rFile)), collapse="\n")
|
||||
), indent = FALSE))))
|
||||
})),
|
||||
codeLicense))
|
||||
@@ -121,7 +120,9 @@ showcaseAppInfo <- function() {
|
||||
readmemd <- file.path.ci(getwd(), "Readme.md")
|
||||
hasReadme <- file.exists(readmemd)
|
||||
if (hasDesc) {
|
||||
desc <- read.dcf(descfile)
|
||||
con <- textConnection(readUTF8(descfile))
|
||||
on.exit(close(con), add = TRUE)
|
||||
desc <- read.dcf(con)
|
||||
}
|
||||
with(tags,
|
||||
div(class="container-fluid shiny-code-container well",
|
||||
|
||||
2
R/tar.R
2
R/tar.R
@@ -141,7 +141,7 @@ untar2 <- function(tarfile, files = NULL, list = FALSE, exdir = ".")
|
||||
warning(gettextf("failed to copy %s to %s", sQuote(name2), sQuote(name)), domain = NA)
|
||||
}
|
||||
} else {
|
||||
if(.Platform$OS.type == "windows") {
|
||||
if(isWindows()) {
|
||||
## this will not work for links to dirs
|
||||
from <- file.path(dirname(name), name2)
|
||||
if (!file.copy(from, name))
|
||||
|
||||
@@ -118,7 +118,7 @@ updateSliderInput <- updateTextInput
|
||||
#' }
|
||||
#' @export
|
||||
updateDateInput <- function(session, inputId, label = NULL, value = NULL,
|
||||
min = NULL, max = NULL) {
|
||||
min = NULL, max = NULL) {
|
||||
|
||||
# If value is a date object, convert it to a string with yyyy-mm-dd format
|
||||
# Same for min and max
|
||||
@@ -163,8 +163,8 @@ updateDateInput <- function(session, inputId, label = NULL, value = NULL,
|
||||
#' }
|
||||
#' @export
|
||||
updateDateRangeInput <- function(session, inputId, label = NULL,
|
||||
start = NULL, end = NULL, min = NULL, max = NULL) {
|
||||
|
||||
start = NULL, end = NULL, min = NULL,
|
||||
max = NULL) {
|
||||
# Make sure start and end are strings, not date objects. This is for
|
||||
# consistency across different locales.
|
||||
if (inherits(start, "Date")) start <- format(start, '%Y-%m-%d')
|
||||
@@ -256,13 +256,28 @@ updateNumericInput <- function(session, inputId, label = NULL, value = NULL,
|
||||
session$sendInputMessage(inputId, message)
|
||||
}
|
||||
|
||||
updateInputOptions <- function(session, inputId, label = NULL, choices = NULL,
|
||||
selected = NULL, inline = FALSE,
|
||||
type = 'checkbox') {
|
||||
|
||||
choices <- choicesWithNames(choices)
|
||||
if (!is.null(selected))
|
||||
selected <- validateSelected(selected, choices, inputId)
|
||||
|
||||
options <- if (length(choices))
|
||||
format(tagList(
|
||||
generateOptions(inputId, choices, selected, inline, type = type)
|
||||
))
|
||||
|
||||
message <- dropNulls(list(label = label, options = options, value = selected))
|
||||
|
||||
session$sendInputMessage(inputId, message)
|
||||
}
|
||||
|
||||
#' Change the value of a checkbox group input on the client
|
||||
#'
|
||||
#' @template update-input
|
||||
#' @param choices A named vector or named list of options. For each item, the
|
||||
#' name will be used as the label, and the value will be used as the value.
|
||||
#' @param selected A vector or list of options (values) which will be selected.
|
||||
#' @inheritParams checkboxGroupInput
|
||||
#'
|
||||
#' @seealso \code{\link{checkboxGroupInput}}
|
||||
#'
|
||||
@@ -295,27 +310,16 @@ updateNumericInput <- function(session, inputId, label = NULL, value = NULL,
|
||||
#' }
|
||||
#' @export
|
||||
updateCheckboxGroupInput <- function(session, inputId, label = NULL,
|
||||
choices = NULL, selected = NULL) {
|
||||
|
||||
choices <- choicesWithNames(choices)
|
||||
if (!is.null(selected))
|
||||
selected <- validateSelected(selected, choices, inputId)
|
||||
|
||||
options <- if (length(choices))
|
||||
columnToRowData(list(value = choices, label = names(choices)))
|
||||
|
||||
message <- dropNulls(list(label = label, options = options, value = selected))
|
||||
|
||||
session$sendInputMessage(inputId, message)
|
||||
choices = NULL, selected = NULL,
|
||||
inline = FALSE) {
|
||||
updateInputOptions(session, inputId, label, choices, selected, inline)
|
||||
}
|
||||
|
||||
|
||||
#' Change the value of a radio input on the client
|
||||
#'
|
||||
#' @template update-input
|
||||
#' @param choices A named vector or named list of options. For each item, the
|
||||
#' name will be used as the label, and the value will be used as the value.
|
||||
#' @param selected A vector or list of options (values) which will be selected.
|
||||
#' @inheritParams radioButtons
|
||||
#'
|
||||
#' @seealso \code{\link{radioButtons}}
|
||||
#'
|
||||
@@ -345,15 +349,18 @@ updateCheckboxGroupInput <- function(session, inputId, label = NULL,
|
||||
#' })
|
||||
#' }
|
||||
#' @export
|
||||
updateRadioButtons <- updateCheckboxGroupInput
|
||||
updateRadioButtons <- function(session, inputId, label = NULL, choices = NULL,
|
||||
selected = NULL, inline = FALSE) {
|
||||
# you must select at least one radio button
|
||||
if (is.null(selected) && !is.null(choices)) selected <- choices[[1]]
|
||||
updateInputOptions(session, inputId, label, choices, selected, inline, type = 'radio')
|
||||
}
|
||||
|
||||
|
||||
#' Change the value of a select input on the client
|
||||
#'
|
||||
#' @template update-input
|
||||
#' @param choices A named vector or named list of options. For each item, the
|
||||
#' name will be used as the label, and the value will be used as the value.
|
||||
#' @param selected A vector or list of options (values) which will be selected.
|
||||
#' @inheritParams selectInput
|
||||
#'
|
||||
#' @seealso \code{\link{selectInput}}
|
||||
#'
|
||||
@@ -386,19 +393,26 @@ updateRadioButtons <- updateCheckboxGroupInput
|
||||
#' })
|
||||
#' }
|
||||
#' @export
|
||||
updateSelectInput <- updateCheckboxGroupInput
|
||||
updateSelectInput <- function(session, inputId, label = NULL, choices = NULL,
|
||||
selected = NULL) {
|
||||
choices <- choicesWithNames(choices)
|
||||
if (!is.null(selected))
|
||||
selected <- validateSelected(selected, choices, inputId)
|
||||
options <- if (length(choices)) selectOptions(choices, selected)
|
||||
message <- dropNulls(list(label = label, options = options, value = selected))
|
||||
session$sendInputMessage(inputId, message)
|
||||
}
|
||||
|
||||
#' @rdname updateSelectInput
|
||||
#' @param options a list of options (see \code{\link{selectizeInput}})
|
||||
#' @inheritParams selectizeInput
|
||||
#' @param server whether to store \code{choices} on the server side, and load
|
||||
#' the select options dynamically on searching, instead of writing all
|
||||
#' \code{choices} into the page at once (i.e., only use the client-side
|
||||
#' version of \pkg{selectize.js})
|
||||
#' @export
|
||||
updateSelectizeInput <- function(
|
||||
session, inputId, label = NULL, choices = NULL, selected = NULL,
|
||||
options = list(), server = FALSE
|
||||
) {
|
||||
updateSelectizeInput <- function(session, inputId, label = NULL, choices = NULL,
|
||||
selected = NULL, options = list(),
|
||||
server = FALSE) {
|
||||
if (length(options)) {
|
||||
res <- checkAsIs(options)
|
||||
cfg <- tags$script(
|
||||
@@ -407,7 +421,7 @@ updateSelectizeInput <- function(
|
||||
`data-eval` = if (length(res$eval)) HTML(toJSON(res$eval)),
|
||||
HTML(toJSON(res$options))
|
||||
)
|
||||
session$sendInputMessage(inputId, list(newOptions = as.character(cfg)))
|
||||
session$sendInputMessage(inputId, list(config = as.character(cfg)))
|
||||
}
|
||||
if (!server) {
|
||||
return(updateSelectInput(session, inputId, label, choices, selected))
|
||||
|
||||
81
R/utils.R
81
R/utils.R
@@ -185,7 +185,7 @@ resolve <- function(dir, relpath) {
|
||||
abs.path <- normalizePath(abs.path, winslash='/', mustWork=TRUE)
|
||||
dir <- normalizePath(dir, winslash='/', mustWork=TRUE)
|
||||
# trim the possible trailing slash under Windows (#306)
|
||||
if (.Platform$OS.type == 'windows') dir <- sub('/$', '', dir)
|
||||
if (isWindows()) dir <- sub('/$', '', dir)
|
||||
if (nchar(abs.path) <= nchar(dir) + 1)
|
||||
return(NULL)
|
||||
if (substr(abs.path, 1, nchar(dir)) != dir ||
|
||||
@@ -195,6 +195,8 @@ resolve <- function(dir, relpath) {
|
||||
return(abs.path)
|
||||
}
|
||||
|
||||
isWindows <- function() .Platform$OS.type == 'windows'
|
||||
|
||||
# This is a wrapper for download.file and has the same interface.
|
||||
# The only difference is that, if the protocol is https, it changes the
|
||||
# download settings, depending on platform.
|
||||
@@ -203,7 +205,7 @@ download <- function(url, ...) {
|
||||
if (grepl('^https?://', url)) {
|
||||
|
||||
# If Windows, call setInternet2, then use download.file with defaults.
|
||||
if (.Platform$OS.type == "windows") {
|
||||
if (isWindows()) {
|
||||
# If we directly use setInternet2, R CMD CHECK gives a Note on Mac/Linux
|
||||
mySI2 <- `::`(utils, 'setInternet2')
|
||||
# Store initial settings
|
||||
@@ -487,7 +489,7 @@ shinyCallingHandlers <- function(expr) {
|
||||
shinyDeprecated <- function(new=NULL, msg=NULL,
|
||||
old=as.character(sys.call(sys.parent()))[1L]) {
|
||||
|
||||
if (getOption("shiny.deprecation.messages", default=TRUE) == FALSE)
|
||||
if (getOption("shiny.deprecation.messages") %OR% TRUE == FALSE)
|
||||
return(invisible())
|
||||
|
||||
if (is.null(msg)) {
|
||||
@@ -736,18 +738,6 @@ cachedFuncWithFile <- function(dir, file, func, case.sensitive = FALSE) {
|
||||
}
|
||||
}
|
||||
|
||||
# Returns a function that sources the file and caches the result for subsequent
|
||||
# calls, unless the file's mtime changes.
|
||||
cachedSource <- function(dir, file, case.sensitive = FALSE) {
|
||||
dir <- normalizePath(dir, mustWork=TRUE)
|
||||
cachedFuncWithFile(dir, file, function(fname, ...) {
|
||||
if (file.exists(fname))
|
||||
return(source(fname, ...))
|
||||
else
|
||||
return(NULL)
|
||||
})
|
||||
}
|
||||
|
||||
# turn column-based data to row-based data (mainly for JSON), e.g. data.frame(x
|
||||
# = 1:10, y = 10:1) ==> list(list(x = 1, y = 10), list(x = 2, y = 9), ...)
|
||||
columnToRowData <- function(data) {
|
||||
@@ -928,3 +918,64 @@ setServerInfo <- function(...) {
|
||||
infoOld[names(infoNew)] <- infoNew
|
||||
.globals$serverInfo <- infoOld
|
||||
}
|
||||
|
||||
# see if the file can be read as UTF-8 on Windows, and converted from UTF-8 to
|
||||
# native encoding; if the conversion fails, it will produce NA's in the results
|
||||
checkEncoding <- function(file) {
|
||||
# skip *nix because its locale is normally UTF-8 based (e.g. en_US.UTF-8), and
|
||||
# *nix users have to make a conscious effort to save a file with an encoding
|
||||
# that is not UTF-8; if they choose to do so, we cannot do much about it
|
||||
# except sitting back and seeing them punished after they choose to escape a
|
||||
# world of consistency (falling back to getOption('encoding') will not help
|
||||
# because native.enc is also normally UTF-8 based on *nix)
|
||||
if (!isWindows()) return('UTF-8')
|
||||
# an empty file?
|
||||
size <- file.info(file)[, 'size']
|
||||
if (size == 0) return('UTF-8')
|
||||
|
||||
x <- readLines(file, encoding = 'UTF-8', warn = FALSE)
|
||||
# if conversion is successful and there are no embedded nul's, use UTF-8
|
||||
if (!any(is.na(iconv(x, 'UTF-8'))) &&
|
||||
!any(readBin(file, 'raw', size) == as.raw(0))) return('UTF-8')
|
||||
|
||||
# check if there is a BOM character: this is also skipped on *nix, because R
|
||||
# on *nix simply ignores this meaningless character if present, but it hurts
|
||||
# on Windows
|
||||
if (identical(charToRaw(readChar(file, 3L, TRUE)), charToRaw('\UFEFF'))) {
|
||||
warning('You should not include the Byte Order Mark (BOM) in ', file, '. ',
|
||||
'Please re-save it in UTF-8 without BOM. See ',
|
||||
'http://shiny.rstudio.com/articles/unicode.html for more info.')
|
||||
if (getRversion() < '3.0.0')
|
||||
stop('R does not support UTF-8-BOM before 3.0.0. Please upgrade R.')
|
||||
return('UTF-8-BOM')
|
||||
}
|
||||
|
||||
enc <- getOption('encoding')
|
||||
msg <- c(sprintf('The file "%s" is not encoded in UTF-8. ', file),
|
||||
'Please convert its encoding to UTF-8 ',
|
||||
'(e.g. use the menu `File -> Save with Encoding` in RStudio). ',
|
||||
'See http://shiny.rstudio.com/articles/unicode.html for more info.')
|
||||
if (enc == 'UTF-8') stop(msg)
|
||||
# if you publish the app to ShinyApps.io, you will be in trouble
|
||||
warning(c(msg, ' Falling back to the encoding "', enc, '".'))
|
||||
|
||||
enc
|
||||
}
|
||||
|
||||
# try to read a file using UTF-8 (fall back to getOption('encoding') in case of
|
||||
# failure, which defaults to native.enc, i.e. native encoding)
|
||||
readUTF8 <- function(file) {
|
||||
enc <- checkEncoding(file)
|
||||
# readLines() does not support UTF-8-BOM directly; has to go through file()
|
||||
if (enc == 'UTF-8-BOM') {
|
||||
file <- base::file(file, encoding = enc)
|
||||
on.exit(close(file), add = TRUE)
|
||||
}
|
||||
x <- readLines(file, encoding = enc, warn = FALSE)
|
||||
enc2native(x)
|
||||
}
|
||||
|
||||
# similarly, try to source() a file with UTF-8
|
||||
sourceUTF8 <- function(file, ...) {
|
||||
source(file, ..., keep.source = TRUE, encoding = checkEncoding(file))
|
||||
}
|
||||
|
||||
@@ -127,8 +127,6 @@ sd_section("Running",
|
||||
c(
|
||||
"runApp",
|
||||
"runExample",
|
||||
"runGist",
|
||||
"runGitHub",
|
||||
"runUrl",
|
||||
"stopApp"
|
||||
)
|
||||
@@ -152,7 +150,8 @@ sd_section("Utility functions",
|
||||
"parseQueryString",
|
||||
"plotPNG",
|
||||
"repeatable",
|
||||
"shinyDeprecated"
|
||||
"shinyDeprecated",
|
||||
"serverInfo"
|
||||
)
|
||||
)
|
||||
sd_section("Embedding",
|
||||
|
||||
@@ -43,3 +43,105 @@ test_that("Repeated names for selectInput and radioButtons choices", {
|
||||
expect_equal(choices[[2]][[3]]$children[[1]]$attribs$value, 'x3')
|
||||
expect_equal(choices[[2]][[3]]$children[[1]]$attribs$checked, NULL)
|
||||
})
|
||||
|
||||
|
||||
test_that("Choices are correctly assigned names", {
|
||||
# Unnamed vector
|
||||
expect_identical(
|
||||
choicesWithNames(c("a","b","3")),
|
||||
list(a="a", b="b", "3"="3")
|
||||
)
|
||||
# Unnamed list
|
||||
expect_identical(
|
||||
choicesWithNames(list("a","b",3)),
|
||||
list(a="a", b="b", "3"=3)
|
||||
)
|
||||
# Vector, with some named, some not
|
||||
expect_identical(
|
||||
choicesWithNames(c(A="a", "b", C="3", "4")),
|
||||
list(A="a", "b"="b", C="3", "4"="4")
|
||||
)
|
||||
# List, with some named, some not
|
||||
expect_identical(
|
||||
choicesWithNames(list(A="a", "b", C=3, 4)),
|
||||
list(A="a", "b"="b", C=3, "4"=4)
|
||||
)
|
||||
# List, named, with a sub-vector
|
||||
expect_identical(
|
||||
choicesWithNames(list(A="a", B="b", C=c("d", "e"))),
|
||||
list(A="a", B="b", C=list(d="d", e="e"))
|
||||
)
|
||||
# List, named, with sublist
|
||||
expect_identical(
|
||||
choicesWithNames(list(A="a", B="b", C=list("d", "e"))),
|
||||
list(A="a", B="b", C=list(d="d", e="e"))
|
||||
)
|
||||
# List, some named, with sublist
|
||||
expect_identical(
|
||||
choicesWithNames(list(A="a", "b", C=list("d", E="e"))),
|
||||
list(A="a", b="b", C=list(d="d", E="e"))
|
||||
)
|
||||
# Deeper nesting
|
||||
expect_identical(
|
||||
choicesWithNames(list(A="a", "b", C=list(D=list("e", "f"), G=c(H="h", "i")))),
|
||||
list(A="a", b="b", C=list(D=list(e="e", f="f"), G=list(H="h", i="i")))
|
||||
)
|
||||
# Error when sublist is unnamed
|
||||
expect_error(choicesWithNames(list(A="a", "b", list(1,2))))
|
||||
})
|
||||
|
||||
|
||||
test_that("selectOptions returns correct HTML", {
|
||||
# None selected
|
||||
expect_identical(
|
||||
selectOptions(choicesWithNames(list("a", "b")), list()),
|
||||
HTML("<option value=\"a\">a</option>\n<option value=\"b\">b</option>")
|
||||
)
|
||||
# One selected
|
||||
expect_identical(
|
||||
selectOptions(choicesWithNames(list("a", "b")), "a"),
|
||||
HTML("<option value=\"a\" selected>a</option>\n<option value=\"b\">b</option>")
|
||||
)
|
||||
# One selected, with named items
|
||||
expect_identical(
|
||||
selectOptions(choicesWithNames(list(A="a", B="b")), "a"),
|
||||
HTML("<option value=\"a\" selected>A</option>\n<option value=\"b\">B</option>")
|
||||
)
|
||||
# Two selected, with optgroup
|
||||
expect_identical(
|
||||
selectOptions(choicesWithNames(list("a", B=list("c", D="d"))), c("a", "d")),
|
||||
HTML("<option value=\"a\" selected>a</option>\n<optgroup label=\"B\">\n<option value=\"c\">c</option>\n<option value=\"d\" selected>D</option>\n</optgroup>")
|
||||
)
|
||||
|
||||
# Escape HTML in strings
|
||||
expect_identical(
|
||||
selectOptions(choicesWithNames(list("<A>"="a", B="b")), "a"),
|
||||
HTML("<option value=\"a\" selected><A></option>\n<option value=\"b\">B</option>")
|
||||
)
|
||||
})
|
||||
|
||||
test_that("selectInput selects items by default", {
|
||||
# None specified as selected (defaults to first)
|
||||
expect_true(grepl(
|
||||
'<option value="a" selected>',
|
||||
selectInput('x', 'x', list("a", "b"))
|
||||
))
|
||||
|
||||
# Nested list (optgroup)
|
||||
expect_true(grepl(
|
||||
'<option value="a" selected>',
|
||||
selectInput('x', 'x', list(A=list("a", "b"), "c"))
|
||||
))
|
||||
|
||||
# Nothing selected when choices=NULL
|
||||
expect_identical(
|
||||
'<select id="x"></select>',
|
||||
format(selectInput('x', NULL, NULL, selectize = FALSE))
|
||||
)
|
||||
|
||||
# None specified as selected. With multiple=TRUE, none selected by default.
|
||||
expect_true(grepl(
|
||||
'<option value="a">',
|
||||
selectInput('x', 'x', list("a", "b"), multiple = TRUE)
|
||||
))
|
||||
})
|
||||
|
||||
@@ -6,7 +6,7 @@ test_that("All man pages have an entry in staticdocs/index.r", {
|
||||
return()
|
||||
}
|
||||
# Known not to be indexed
|
||||
known_unindexed <- c("shiny-package", "knitr_methods")
|
||||
known_unindexed <- c("shiny-package", "knitr_methods", "knitr_methods_htmltools")
|
||||
|
||||
indexed_topics <- local({
|
||||
result <- character(0)
|
||||
|
||||
22
inst/www/shared/json2-min.js
vendored
Normal file
22
inst/www/shared/json2-min.js
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
("object"!=typeof JSON||JSON.stringify("\uf977").length>3)&&(JSON={}),function(){"use strict"
|
||||
function f(t){return 10>t?"0"+t:t}function quote(t){return escapable.lastIndex=0,escapable.test(t)?'"'+t.replace(escapable,function(t){var e=meta[t]
|
||||
return"string"==typeof e?e:"\\u"+("0000"+t.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+t+'"'}function str(t,e){var n,r,o,f,u,p=gap,a=e[t]
|
||||
switch(a&&"object"==typeof a&&"function"==typeof a.toJSON&&(a=a.toJSON(t)),"function"==typeof rep&&(a=rep.call(e,t,a)),typeof a){case"string":return quote(a)
|
||||
case"number":return isFinite(a)?a+"":"null"
|
||||
case"boolean":case"null":return a+""
|
||||
case"object":if(!a)return"null"
|
||||
if(gap+=indent,u=[],"[object Array]"===Object.prototype.toString.apply(a)){for(f=a.length,n=0;f>n;n+=1)u[n]=str(n,a)||"null"
|
||||
return o=0===u.length?"[]":gap?"[\n"+gap+u.join(",\n"+gap)+"\n"+p+"]":"["+u.join(",")+"]",gap=p,o}if(rep&&"object"==typeof rep)for(f=rep.length,n=0;f>n;n+=1)"string"==typeof rep[n]&&(r=rep[n],o=str(r,a),o&&u.push(quote(r)+(gap?": ":":")+o))
|
||||
else for(r in a)Object.prototype.hasOwnProperty.call(a,r)&&(o=str(r,a),o&&u.push(quote(r)+(gap?": ":":")+o))
|
||||
return o=0===u.length?"{}":gap?"{\n"+gap+u.join(",\n"+gap)+"\n"+p+"}":"{"+u.join(",")+"}",gap=p,o}}"function"!=typeof Date.prototype.toJSON&&(Date.prototype.toJSON=function(){return isFinite(this.valueOf())?this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+"Z":null},String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(){return this.valueOf()})
|
||||
var cx,escapable,gap,indent,meta,rep
|
||||
"function"!=typeof JSON.stringify&&(escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,meta={"\b":"\\b"," ":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},JSON.stringify=function(t,e,n){var r
|
||||
if(gap="",indent="","number"==typeof n)for(r=0;n>r;r+=1)indent+=" "
|
||||
else"string"==typeof n&&(indent=n)
|
||||
if(rep=e,e&&"function"!=typeof e&&("object"!=typeof e||"number"!=typeof e.length))throw Error("JSON.stringify")
|
||||
return str("",{"":t})}),"function"!=typeof JSON.parse&&(cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,JSON.parse=function(text,reviver){function walk(t,e){var n,r,o=t[e]
|
||||
if(o&&"object"==typeof o)for(n in o)Object.prototype.hasOwnProperty.call(o,n)&&(r=walk(o,n),void 0!==r?o[n]=r:delete o[n])
|
||||
return reviver.call(t,e,o)}var j
|
||||
if(text+="",cx.lastIndex=0,cx.test(text)&&(text=text.replace(cx,function(t){return"\\u"+("0000"+t.charCodeAt(0).toString(16)).slice(-4)})),/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"")))return j=eval("("+text+")"),"function"==typeof reviver?walk({"":j},""):j
|
||||
throw new SyntaxError("JSON.parse")})}()
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -85,6 +85,11 @@
|
||||
var code = document.getElementById(srcfile.replace(/\./g, "_") + "_code");
|
||||
var start = findTextPoint(code, ref[0], ref[4]);
|
||||
var end = findTextPoint(code, ref[2], ref[5]);
|
||||
|
||||
// If the insertion point can't be found, bail out now
|
||||
if (start.element === null || end.element === null)
|
||||
return;
|
||||
|
||||
var range = document.createRange();
|
||||
// If the text points are inside different <SPAN>s, we may not be able to
|
||||
// surround them without breaking apart the elements to keep the DOM tree
|
||||
|
||||
@@ -34,9 +34,14 @@
|
||||
var x;
|
||||
if (el.currentStyle)
|
||||
x = el.currentStyle[styleProp];
|
||||
else if (window.getComputedStyle)
|
||||
x = document.defaultView.getComputedStyle(el, null)
|
||||
.getPropertyValue(styleProp);
|
||||
else if (window.getComputedStyle) {
|
||||
// getComputedStyle can return null when we're inside a hidden iframe on
|
||||
// Firefox; don't attempt to retrieve style props in this case.
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=548397
|
||||
var style = document.defaultView.getComputedStyle(el, null);
|
||||
if (style)
|
||||
x = style.getPropertyValue(styleProp);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
@@ -2091,37 +2096,20 @@
|
||||
|
||||
// This will replace all the options
|
||||
if (data.hasOwnProperty('options')) {
|
||||
// Clear existing options and add each new one
|
||||
$el.empty();
|
||||
selectize = this._selectize(el);
|
||||
if (selectize !== undefined) {
|
||||
selectize.clearOptions();
|
||||
// Selectize.js doesn't maintain insertion order on Chrome on Mac
|
||||
// with >10 items if inserted using addOption (versus being present
|
||||
// in the DOM at selectize() time). Putting $order on each option
|
||||
// makes it work.
|
||||
$.each(data.options, function(i, opt) {
|
||||
opt.$order = i;
|
||||
});
|
||||
selectize.addOption(data.options);
|
||||
}
|
||||
for (var i = 0; i < data.options.length; i++) {
|
||||
var in_opt = data.options[i];
|
||||
|
||||
var $newopt = $('<option/>', {
|
||||
value: in_opt.value,
|
||||
text: in_opt.label
|
||||
});
|
||||
|
||||
$el.append($newopt);
|
||||
}
|
||||
// Must destroy selectize before appending new options, otherwise
|
||||
// selectize will restore the original select
|
||||
if (selectize) selectize.destroy();
|
||||
// Clear existing options and add each new one
|
||||
$el.empty().append(data.options);
|
||||
this._selectize(el);
|
||||
}
|
||||
|
||||
// re-initialize selectize
|
||||
if (data.hasOwnProperty('newOptions')) {
|
||||
if (data.hasOwnProperty('config')) {
|
||||
$el.parent()
|
||||
.find('script[data-for="' + $escape(el.id) + '"]')
|
||||
.replaceWith(data.newOptions);
|
||||
.replaceWith(data.config);
|
||||
this._selectize(el, true);
|
||||
}
|
||||
|
||||
@@ -2253,22 +2241,7 @@
|
||||
if (data.hasOwnProperty('options')) {
|
||||
// Clear existing options and add each new one
|
||||
$el.find('label.radio').remove();
|
||||
for (var i = 0; i < data.options.length; i++) {
|
||||
var in_opt = data.options[i];
|
||||
|
||||
var $newopt = $('<label class="radio"/>');
|
||||
var $radio = $('<input/>', {
|
||||
type: "radio",
|
||||
name: el.id,
|
||||
id: el.id + (i+1).toString(),
|
||||
value: in_opt.value
|
||||
});
|
||||
|
||||
$newopt.append($radio);
|
||||
$newopt.append('<span>' + in_opt.label + '</span>');
|
||||
|
||||
$el.append($newopt);
|
||||
}
|
||||
$el.append(data.options);
|
||||
}
|
||||
|
||||
if (data.hasOwnProperty('value'))
|
||||
@@ -2378,22 +2351,7 @@
|
||||
if (data.hasOwnProperty('options')) {
|
||||
// Clear existing options and add each new one
|
||||
$el.find('label.checkbox').remove();
|
||||
for (var i = 0; i < data.options.length; i++) {
|
||||
var in_opt = data.options[i];
|
||||
|
||||
var $newopt = $('<label class="checkbox"/>');
|
||||
var $checkbox = $('<input/>', {
|
||||
type: "checkbox",
|
||||
name: el.id,
|
||||
id: el.id + (i+1).toString(),
|
||||
value: in_opt.value
|
||||
});
|
||||
|
||||
$newopt.append($checkbox);
|
||||
$newopt.append('<span>' + in_opt.label + '</span>');
|
||||
|
||||
$el.append($newopt);
|
||||
}
|
||||
$el.append(data.options);
|
||||
}
|
||||
|
||||
if (data.hasOwnProperty('value'))
|
||||
|
||||
@@ -23,6 +23,13 @@ example, if you have an input with an id of \code{foo}, then you can use
|
||||
\code{input.foo} to read its value. (Be sure not to modify the input/output
|
||||
objects, as this may cause unpredictable behavior.)
|
||||
}
|
||||
\note{
|
||||
You are not recommended to use special JavaScript characters such as a
|
||||
period \code{.} in the input id's, but if you do use them anyway, for
|
||||
example, \code{inputId = "foo.bar"}, you will have to use
|
||||
\code{input["foo.bar"]} instead of \code{input.foo.bar} to read the input
|
||||
value.
|
||||
}
|
||||
\examples{
|
||||
sidebarPanel(
|
||||
selectInput(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
% Generated by roxygen2 (4.0.1): do not edit by hand
|
||||
\name{getDefaultReactiveDomain}
|
||||
\name{domains}
|
||||
\alias{domains}
|
||||
\alias{getDefaultReactiveDomain}
|
||||
\alias{onReactiveDomainEnded}
|
||||
|
||||
@@ -4,12 +4,15 @@
|
||||
\alias{uiOutput}
|
||||
\title{Create an HTML output element}
|
||||
\usage{
|
||||
htmlOutput(outputId)
|
||||
htmlOutput(outputId, inline = FALSE)
|
||||
|
||||
uiOutput(outputId)
|
||||
uiOutput(outputId, inline = FALSE)
|
||||
}
|
||||
\arguments{
|
||||
\item{outputId}{output variable to read the value from}
|
||||
|
||||
\item{inline}{use an inline (\code{span()}) or block container (\code{div()})
|
||||
for the output}
|
||||
}
|
||||
\value{
|
||||
An HTML output element that can be included in a panel
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
\alias{imageOutput}
|
||||
\title{Create a image output element}
|
||||
\usage{
|
||||
imageOutput(outputId, width = "100\%", height = "400px")
|
||||
imageOutput(outputId, width = "100\%", height = "400px", inline = FALSE)
|
||||
}
|
||||
\arguments{
|
||||
\item{outputId}{output variable to read the image from}
|
||||
@@ -13,6 +13,9 @@ imageOutput(outputId, width = "100\%", height = "400px")
|
||||
string and have \code{"px"} appended.}
|
||||
|
||||
\item{height}{Image height}
|
||||
|
||||
\item{inline}{use an inline (\code{span()}) or block container (\code{div()})
|
||||
for the output}
|
||||
}
|
||||
\value{
|
||||
An image output element that can be included in a panel
|
||||
|
||||
@@ -7,12 +7,14 @@
|
||||
\usage{
|
||||
knit_print.shiny.appobj(x, ...)
|
||||
|
||||
knit_print.shiny.render.function(x, ...)
|
||||
knit_print.shiny.render.function(x, ..., inline = FALSE)
|
||||
}
|
||||
\arguments{
|
||||
\item{x}{Object to knit_print}
|
||||
|
||||
\item{...}{Additional knit_print arguments}
|
||||
|
||||
\item{inline}{Whether the object is printed inline.}
|
||||
}
|
||||
\description{
|
||||
These S3 methods are necessary to help Shiny applications and UI chunks embed
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
\usage{
|
||||
navbarPage(title, ..., id = NULL, header = NULL, footer = NULL,
|
||||
inverse = FALSE, collapsable = FALSE, fluid = TRUE, responsive = TRUE,
|
||||
theme = NULL)
|
||||
theme = NULL, windowTitle = title)
|
||||
|
||||
navbarMenu(title, ..., icon = NULL)
|
||||
}
|
||||
@@ -43,6 +43,9 @@ and resize page elements based on the size of the viewing device)}
|
||||
www directory). For example, to use the theme located at
|
||||
\code{www/bootstrap.css} you would use \code{theme = "bootstrap.css"}.}
|
||||
|
||||
\item{windowTitle}{The title that should be displayed by the browser window.
|
||||
Useful if \code{title} is not a string.}
|
||||
|
||||
\item{icon}{Optional icon to appear on a \code{navbarMenu} tab.}
|
||||
}
|
||||
\value{
|
||||
|
||||
@@ -5,29 +5,30 @@
|
||||
\usage{
|
||||
plotOutput(outputId, width = "100\%", height = "400px", clickId = NULL,
|
||||
hoverId = NULL, hoverDelay = 300, hoverDelayType = c("debounce",
|
||||
"throttle"))
|
||||
"throttle"), inline = FALSE)
|
||||
}
|
||||
\arguments{
|
||||
\item{outputId}{output variable to read the plot from}
|
||||
|
||||
\item{width}{Plot width. Must be a valid CSS unit (like \code{"100\%"},
|
||||
\code{"400px"}, \code{"auto"}) or a number, which will be coerced to a
|
||||
string and have \code{"px"} appended.}
|
||||
|
||||
\item{height}{Plot height}
|
||||
\item{width,height}{Plot width/height. Must be a valid CSS unit (like
|
||||
\code{"100\%"}, \code{"400px"}, \code{"auto"}) or a number, which will be
|
||||
coerced to a string and have \code{"px"} appended. These two arguments are
|
||||
ignored when \code{inline = TRUE}, in which case the width/height of a plot
|
||||
must be specified in \code{renderPlot()}.}
|
||||
|
||||
\item{clickId}{If not \code{NULL}, the plot will send coordinates to the
|
||||
server whenever it is clicked. This information will be accessible on the
|
||||
\code{input} object using \code{input$}\emph{\code{clickId}}. The value will be a
|
||||
named list or vector with \code{x} and \code{y} elements indicating the
|
||||
mouse position in user units.}
|
||||
\code{input} object using \code{input$}\emph{\code{clickId}}. The value
|
||||
will be a named list or vector with \code{x} and \code{y} elements
|
||||
indicating the mouse position in user units.}
|
||||
|
||||
\item{hoverId}{If not \code{NULL}, the plot will send coordinates to the
|
||||
server whenever the mouse pauses on the plot for more than the number of
|
||||
milliseconds determined by \code{hoverTimeout}. This information will be
|
||||
The value will be \code{NULL} if the user is not hovering, and a named
|
||||
list or vector with \code{x} and \code{y} elements indicating the mouse
|
||||
position in user units.}
|
||||
accessible on the \code{input} object using
|
||||
\code{input$}\emph{\code{clickId}}. The value will be \code{NULL} if the
|
||||
user is not hovering, and a named list or vector with \code{x} and \code{y}
|
||||
elements indicating the mouse position in user units.}
|
||||
|
||||
\item{hoverDelay}{The delay for hovering, in milliseconds.}
|
||||
|
||||
@@ -36,6 +37,9 @@ events. Use \code{"throttle"} to limit the number of hover events to one
|
||||
every \code{hoverDelay} milliseconds. Use \code{"debounce"} to suspend
|
||||
events while the cursor is moving, and wait until the cursor has been at
|
||||
rest for \code{hoverDelay} milliseconds before sending an event.}
|
||||
|
||||
\item{inline}{use an inline (\code{span()}) or block container (\code{div()})
|
||||
for the output}
|
||||
}
|
||||
\value{
|
||||
A plot output element that can be included in a panel
|
||||
@@ -43,6 +47,12 @@ A plot output element that can be included in a panel
|
||||
\description{
|
||||
Render a \link{renderPlot} within an application page.
|
||||
}
|
||||
\note{
|
||||
The arguments \code{clickId} and \code{hoverId} only work for R base
|
||||
graphics (see the \pkg{\link{graphics}} package). They do not work for
|
||||
\pkg{\link[grid:grid-package]{grid}}-based graphics, such as \pkg{ggplot2},
|
||||
\pkg{lattice}, and so on.
|
||||
}
|
||||
\examples{
|
||||
# Show a plot of the generated distribution
|
||||
mainPanel(
|
||||
|
||||
@@ -9,17 +9,13 @@ renderPlot(expr, width = "auto", height = "auto", res = 72, ...,
|
||||
\arguments{
|
||||
\item{expr}{An expression that generates a plot.}
|
||||
|
||||
\item{width}{The width of the rendered plot, in pixels; or \code{'auto'} to
|
||||
use the \code{offsetWidth} of the HTML element that is bound to this plot.
|
||||
You can also pass in a function that returns the width in pixels or
|
||||
\code{'auto'}; in the body of the function you may reference reactive
|
||||
values and functions.}
|
||||
|
||||
\item{height}{The height of the rendered plot, in pixels; or \code{'auto'} to
|
||||
use the \code{offsetHeight} of the HTML element that is bound to this plot.
|
||||
You can also pass in a function that returns the width in pixels or
|
||||
\code{'auto'}; in the body of the function you may reference reactive
|
||||
values and functions.}
|
||||
\item{width,height}{The width/height of the rendered plot, in pixels; or
|
||||
\code{'auto'} to use the \code{offsetWidth}/\code{offsetHeight} of the HTML
|
||||
element that is bound to this plot. You can also pass in a function that
|
||||
returns the width/height in pixels or \code{'auto'}; in the body of the
|
||||
function you may reference reactive values and functions. When rendering an
|
||||
inline plot, you must provide numeric values (in pixels) to both
|
||||
\code{width} and \code{height}.}
|
||||
|
||||
\item{res}{Resolution of resulting plot, in pixels per inch. This value is
|
||||
passed to \code{\link{png}}. Note that this affects the resolution of PNG
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
% Generated by roxygen2 (4.0.1): do not edit by hand
|
||||
\name{runGist}
|
||||
\alias{runGist}
|
||||
\title{Run a Shiny application from https://gist.github.com}
|
||||
\usage{
|
||||
runGist(gist, port = NULL,
|
||||
launch.browser = getOption("shiny.launch.browser", interactive()))
|
||||
}
|
||||
\arguments{
|
||||
\item{gist}{The identifier of the gist. For example, if the gist is
|
||||
https://gist.github.com/jcheng5/3239667, then \code{3239667},
|
||||
\code{'3239667'}, and \code{'https://gist.github.com/jcheng5/3239667'}
|
||||
are all valid values.}
|
||||
|
||||
\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.}
|
||||
}
|
||||
\description{
|
||||
Download and launch a Shiny application that is hosted on GitHub as a gist.
|
||||
}
|
||||
\examples{
|
||||
\dontrun{
|
||||
runGist(3239667)
|
||||
runGist("https://gist.github.com/jcheng5/3239667")
|
||||
|
||||
# Old URL format without username
|
||||
runGist("https://gist.github.com/3239667")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
% Generated by roxygen2 (4.0.1): do not edit by hand
|
||||
\name{runGitHub}
|
||||
\alias{runGitHub}
|
||||
\title{Run a Shiny application from a GitHub repository}
|
||||
\usage{
|
||||
runGitHub(repo, username = getOption("github.user"), ref = "master",
|
||||
subdir = NULL, port = NULL,
|
||||
launch.browser = getOption("shiny.launch.browser", interactive()))
|
||||
}
|
||||
\arguments{
|
||||
\item{repo}{Name of the repository}
|
||||
|
||||
\item{username}{GitHub username}
|
||||
|
||||
\item{ref}{Desired git reference. Could be a commit, tag, or branch
|
||||
name. Defaults to \code{"master"}.}
|
||||
|
||||
\item{subdir}{A subdirectory in the repository that contains the app. By
|
||||
default, this function will run an app from the top level of the repo, but
|
||||
you can use a path such as `\code{"inst/shinyapp"}.}
|
||||
|
||||
\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.}
|
||||
}
|
||||
\description{
|
||||
Download and launch a Shiny application that is hosted in a GitHub repository.
|
||||
}
|
||||
\examples{
|
||||
\dontrun{
|
||||
runGitHub("shiny_example", "rstudio")
|
||||
|
||||
# Can run an app from a subdirectory in the repo
|
||||
runGitHub("shiny_example", "rstudio", subdir = "inst/shinyapp/")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
% Generated by roxygen2 (4.0.1): do not edit by hand
|
||||
\name{runUrl}
|
||||
\alias{runGist}
|
||||
\alias{runGitHub}
|
||||
\alias{runUrl}
|
||||
\title{Run a Shiny application from a URL}
|
||||
\usage{
|
||||
runUrl(url, filetype = NULL, subdir = NULL, port = NULL,
|
||||
launch.browser = getOption("shiny.launch.browser", interactive()))
|
||||
runUrl(url, filetype = NULL, subdir = NULL, ...)
|
||||
|
||||
runGist(gist, ...)
|
||||
|
||||
runGitHub(repo, username = getOption("github.user"), ref = "master",
|
||||
subdir = NULL, ...)
|
||||
}
|
||||
\arguments{
|
||||
\item{url}{URL of the application.}
|
||||
@@ -16,19 +22,31 @@ runUrl(url, filetype = NULL, subdir = NULL, port = NULL,
|
||||
default, this function will run an app from the top level of the repo, but
|
||||
you can use a path such as `\code{"inst/shinyapp"}.}
|
||||
|
||||
\item{port}{The TCP port that the application should listen on. Defaults to
|
||||
choosing a random port.}
|
||||
\item{...}{Other arguments to be passed to \code{\link{runApp}()}, such as
|
||||
\code{port} and \code{launch.browser}.}
|
||||
|
||||
\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.}
|
||||
\item{gist}{The identifier of the gist. For example, if the gist is
|
||||
https://gist.github.com/jcheng5/3239667, then \code{3239667},
|
||||
\code{'3239667'}, and \code{'https://gist.github.com/jcheng5/3239667'} are
|
||||
all valid values.}
|
||||
|
||||
\item{repo}{Name of the repository.}
|
||||
|
||||
\item{username}{GitHub username. If \code{repo} is of the form
|
||||
\code{"username/repo"}, \code{username} will be taken from \code{repo}.}
|
||||
|
||||
\item{ref}{Desired git reference. Could be a commit, tag, or branch name.
|
||||
Defaults to \code{"master"}.}
|
||||
}
|
||||
\description{
|
||||
Download and launch a Shiny application that is hosted at a downloadable
|
||||
URL. The Shiny application must be saved in a .zip, .tar, or .tar.gz file.
|
||||
The Shiny application files must be contained in a subdirectory in the
|
||||
archive. For example, the files might be \code{myapp/server.r} and
|
||||
\code{myapp/ui.r}.
|
||||
\code{runUrl()} downloads and launches a Shiny application that is hosted at
|
||||
a downloadable URL. The Shiny application must be saved in a .zip, .tar, or
|
||||
.tar.gz file. The Shiny application files must be contained in the root
|
||||
directory or a subdirectory in the archive. For example, the files might be
|
||||
\code{myapp/server.r} and \code{myapp/ui.r}. The functions \code{runGitHub()}
|
||||
and \code{runGist()} are based on \code{runUrl()}, using URL's from GitHub
|
||||
(\url{https://github.com}) and GitHub gists (\url{https://gist.github.com}),
|
||||
respectively.
|
||||
}
|
||||
\examples{
|
||||
\dontrun{
|
||||
@@ -38,5 +56,19 @@ runUrl('https://github.com/rstudio/shiny_example/archive/master.tar.gz')
|
||||
runUrl("https://github.com/rstudio/shiny_example/archive/master.zip",
|
||||
subdir = "inst/shinyapp/")
|
||||
}
|
||||
\dontrun{
|
||||
runGist(3239667)
|
||||
runGist("https://gist.github.com/jcheng5/3239667")
|
||||
|
||||
# Old URL format without username
|
||||
runGist("https://gist.github.com/3239667")
|
||||
}
|
||||
\dontrun{
|
||||
runGitHub("shiny_example", "rstudio")
|
||||
# or runGitHub("rstudio/shiny_example")
|
||||
|
||||
# Can run an app from a subdirectory in the repo
|
||||
runGitHub("shiny_example", "rstudio", subdir = "inst/shinyapp/")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
\name{tagList}
|
||||
\name{tag}
|
||||
\alias{tag}
|
||||
\alias{tagAppendAttributes}
|
||||
\alias{tagAppendChild}
|
||||
|
||||
@@ -3,12 +3,15 @@
|
||||
\alias{textOutput}
|
||||
\title{Create a text output element}
|
||||
\usage{
|
||||
textOutput(outputId, container = div)
|
||||
textOutput(outputId, container = if (inline) span else div, inline = FALSE)
|
||||
}
|
||||
\arguments{
|
||||
\item{outputId}{output variable to read the value from}
|
||||
|
||||
\item{container}{a function to generate an HTML element to contain the text}
|
||||
|
||||
\item{inline}{use an inline (\code{span()}) or block container (\code{div()})
|
||||
for the output}
|
||||
}
|
||||
\value{
|
||||
A text output element that can be included in a panel
|
||||
@@ -19,7 +22,7 @@ text will be included within an HTML \code{div} tag by default.
|
||||
}
|
||||
\details{
|
||||
Text is HTML-escaped prior to rendering. This element is often used
|
||||
to display \link{renderText} output variables.
|
||||
to display \link{renderText} output variables.
|
||||
}
|
||||
\examples{
|
||||
h3(textOutput("caption"))
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
\title{Change the value of a checkbox group input on the client}
|
||||
\usage{
|
||||
updateCheckboxGroupInput(session, inputId, label = NULL, choices = NULL,
|
||||
selected = NULL)
|
||||
selected = NULL, inline = FALSE)
|
||||
}
|
||||
\arguments{
|
||||
\item{session}{The \code{session} object passed to function given to
|
||||
@@ -14,10 +14,12 @@ updateCheckboxGroupInput(session, inputId, label = NULL, choices = NULL,
|
||||
|
||||
\item{label}{The label to set for the input object.}
|
||||
|
||||
\item{choices}{A named vector or named list of options. For each item, the
|
||||
name will be used as the label, and the value will be used as the value.}
|
||||
\item{choices}{List of values to show checkboxes for. If elements of the list
|
||||
are named then that name rather than the value is displayed to the user.}
|
||||
|
||||
\item{selected}{A vector or list of options (values) which will be selected.}
|
||||
\item{selected}{The values that should be initially selected, if any.}
|
||||
|
||||
\item{inline}{If \code{TRUE}, render the choices inline (i.e. horizontally)}
|
||||
}
|
||||
\description{
|
||||
Change the value of a checkbox group input on the client
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
\title{Change the value of a radio input on the client}
|
||||
\usage{
|
||||
updateRadioButtons(session, inputId, label = NULL, choices = NULL,
|
||||
selected = NULL)
|
||||
selected = NULL, inline = FALSE)
|
||||
}
|
||||
\arguments{
|
||||
\item{session}{The \code{session} object passed to function given to
|
||||
@@ -14,10 +14,13 @@ updateRadioButtons(session, inputId, label = NULL, choices = NULL,
|
||||
|
||||
\item{label}{The label to set for the input object.}
|
||||
|
||||
\item{choices}{A named vector or named list of options. For each item, the
|
||||
name will be used as the label, and the value will be used as the value.}
|
||||
\item{choices}{List of values to select from (if elements of the list are
|
||||
named then that name rather than the value is displayed to the user)}
|
||||
|
||||
\item{selected}{A vector or list of options (values) which will be selected.}
|
||||
\item{selected}{The initially selected value (if not specified then
|
||||
defaults to the first value)}
|
||||
|
||||
\item{inline}{If \code{TRUE}, render the choices inline (i.e. horizontally)}
|
||||
}
|
||||
\description{
|
||||
Change the value of a radio input on the client
|
||||
|
||||
@@ -18,17 +18,22 @@ updateSelectizeInput(session, inputId, label = NULL, choices = NULL,
|
||||
|
||||
\item{label}{The label to set for the input object.}
|
||||
|
||||
\item{choices}{A named vector or named list of options. For each item, the
|
||||
name will be used as the label, and the value will be used as the value.}
|
||||
|
||||
\item{selected}{A vector or list of options (values) which will be selected.}
|
||||
|
||||
\item{options}{a list of options (see \code{\link{selectizeInput}})}
|
||||
|
||||
\item{server}{whether to store \code{choices} on the server side, and load
|
||||
the select options dynamically on searching, instead of writing all
|
||||
\code{choices} into the page at once (i.e., only use the client-side
|
||||
version of \pkg{selectize.js})}
|
||||
|
||||
\item{choices}{List of values to select from. If elements of the list are
|
||||
named then that name rather than the value is displayed to the user.}
|
||||
|
||||
\item{selected}{The initially selected value (or multiple values if
|
||||
\code{multiple = TRUE}). If not specified then defaults to the first value
|
||||
for single-select lists and no values for multiple select lists.}
|
||||
|
||||
\item{options}{A list of options. See the documentation of \pkg{selectize.js}
|
||||
for possible options (character option values inside \code{\link{I}()} will
|
||||
be treated as literal JavaScript code; see \code{\link{renderDataTable}()}
|
||||
for details).}
|
||||
}
|
||||
\description{
|
||||
Change the value of a select input on the client
|
||||
|
||||
Reference in New Issue
Block a user