Compare commits

...

99 Commits

Author SHA1 Message Date
Winston Chang
6c711b76b0 Bump version to 0.10.1 2014-07-25 14:20:43 -05:00
Winston Chang
9c914f10c4 Merge pull request #553 from wch/hidden-selectize
Add custom version of selectize.js to work around Firefox bug
2014-07-25 13:37:08 -05:00
Winston Chang
eda56d118a Merge pull request #549 from yihui/bugfix/utf8-bom
warn against the byte order mark if exists; fixes #545
2014-07-24 16:09:56 -05:00
Winston Chang
02c7351c6d Add custom version of selectize.js to work around Firefox bug
This is a workaround for issue #550. This version is based on selectize version 0.9.1.
2014-07-24 15:29:23 -05:00
Yihui Xie
ab618235f1 one more check before we use UTF-8: see if there are embedded nul's 2014-07-24 14:48:23 -05:00
Yihui Xie
ffead9ed70 add explanations of skipping *nix when checking encoding, and point to the shiny dev center article 2014-07-24 11:57:46 -05:00
Winston Chang
36aefadced Merge pull request #550 from rstudio/bugfix/offscreen-shinyapps
Deal gracefully with elements that have no computed style available
2014-07-23 11:55:24 -05:00
Jonathan McPherson
75ccfe38ce update comment with more specific browser notes 2014-07-23 09:43:42 -07:00
Jonathan McPherson
e3cb3fe2e4 deal gracefully with elements that have no computed style available 2014-07-22 14:41:34 -07:00
Yihui Xie
983e7e9b75 warn against the byte order mark if exists; fixes #545 2014-07-22 16:22:50 -05:00
Yihui Xie
3db47c076c a news item for the optgroup feature 2014-07-18 14:40:58 -05:00
Yihui Xie
eeff285b33 add links to examples in shiny dev center 2014-07-18 14:40:31 -05:00
Yihui Xie
029595f8ea an edge case selectInput(choices = NULL)
firstChoice() may fail with an error "subscript out of bounds"
2014-07-17 15:59:33 -05:00
Yihui Xie
ea2ec27724 bump version 2014-07-17 14:52:26 -05:00
Yihui Xie
f6bf4a416f Merge pull request #537 from yihui/bugfix/native-encoding
Use native encoding internally
2014-07-17 14:49:53 -05:00
Yihui Xie
af978a68e3 tweak the warning message
and simply stop() in case the user has set option(encoding = 'UTF-8')
2014-07-17 14:39:21 -05:00
Yihui Xie
89dc1323e1 add a note section about the clickId/hoverId arguments in plotOutput(), since they seem to have been confusing grid graphics users
and re-wrap the roxygen comments
2014-07-16 17:27:00 -05:00
Yihui Xie
a4b5f63deb a single quote ' was omitted here, making the Rd for plotOutput() incomplete since this line was ignored 2014-07-16 17:27:00 -05:00
Winston Chang
feaa6ccff4 Merge pull request #542 from rstudio/feature/select-optgroup
Feature/select optgroup (closes #520)
2014-07-16 17:22:29 -05:00
Winston Chang
7159293337 Use consistent indentation for function definitions 2014-07-16 17:04:22 -05:00
Winston Chang
4a5b31e3a7 Simplify needOptgroup function 2014-07-16 16:57:17 -05:00
Winston Chang
6f1dc89fb3 Enable union merge for NEWS 2014-07-16 16:48:56 -05:00
Yihui Xie
29dd405fe5 the options and ... arguments are no longer needed 2014-07-16 15:50:31 -05:00
Yihui Xie
0f0b0cd3d8 explicitly define updateSelectInput() instead of using the trick to change the options argument of updateInputOptions() 2014-07-16 15:50:08 -05:00
Winston Chang
262528e36a Add tests for deeper nesting with choicesWithNames 2014-07-16 12:07:13 -05:00
Winston Chang
597e86dd57 Make listify work on nested lists of depth > 1 2014-07-16 12:02:55 -05:00
Winston Chang
b604dba948 Add tests for default selected items 2014-07-16 00:52:29 -05:00
Winston Chang
1837a64bd2 Add tests for selectOptions 2014-07-16 00:51:57 -05:00
Winston Chang
9b413de4d8 selectOptions: handle mixed options and optgroups 2014-07-16 00:51:57 -05:00
Winston Chang
3d77cbd677 Slight clarification of comment 2014-07-16 00:51:57 -05:00
Winston Chang
62176c3218 Add tests for choicesWithNames 2014-07-16 00:51:57 -05:00
Winston Chang
d7a01c32cc Always convert choices to a (named) list
Converting it to a list, and ensuring that it's a named list reduces
many checks elsewhere.
2014-07-16 00:51:57 -05:00
Yihui Xie
cc493fd545 fall back to native encoding on Windows if UTF-8 does not work 2014-07-15 16:05:23 -05:00
Yihui Xie
6b8679454d factor out .Platform$OS.type == 'windows' as isWindows() 2014-07-15 16:04:02 -05:00
Yihui Xie
1b68d61e54 R CMD check will warn against the possibly missing variables inline and type 2014-07-11 17:36:37 -05:00
Yihui Xie
418de862e6 rename newOptions to config 2014-07-11 14:17:08 -05:00
Yihui Xie
413653858e inherit doc for updateFooInput() from fooInput() 2014-07-11 14:03:47 -05:00
Yihui Xie
f0886a7556 when we need <optgroup> for the child elements of choices, we just generate it no matter what the child element is
e.g. we use <optgroup> for A even if A only has one element: list(A = 'a', B = c('b1', 'b2'))
2014-07-11 14:03:47 -05:00
Yihui Xie
0e2666948f when choice is not a list, we need to return its first element 2014-07-11 14:03:47 -05:00
Yihui Xie
d2fc851816 make updateSelectInput(), updateCheckboxGroupInput(), and updateRadioButtons() work
now session$sendInputMessage() does not send options as the choices data, but as a pre-generated raw HTML string; in shiny.js, we just receive this string, and .append() it to the input after the input is emptied
2014-07-11 14:03:47 -05:00
Yihui Xie
e1fb29c8c5 factor out the code to generate options from checkboxGrouptInput() and radioButtons(), and use the new generator generateOptions() for them 2014-07-11 14:03:47 -05:00
Yihui Xie
fe3158fdd6 validateSelected() does not validate selected for the optgroup case; this function is only for shiny <= 0.9 2014-07-11 14:03:47 -05:00
Yihui Xie
721b26f80b choicesWithNames() should also consider the optgroup case now: all optgroup nodes must be named 2014-07-11 14:03:47 -05:00
Yihui Xie
d3ecfb22ee closes #326: generate <optgroup> when choices is a named list of choices
note the nested level of optgroup can be greater than one here, however, the HTML4 spec only allows one level, i.e. optgroup must have select as its direct parent http://stackoverflow.com/q/1037732/559676
2014-07-11 14:03:47 -05:00
Yihui Xie
27a98020c9 recursively select the first choice, to make sure selected is a scalar, even when choices is a list of lists (optgroup) 2014-07-11 14:03:47 -05:00
Yihui Xie
ab56b72f39 json2.js modified and uglified from https://github.com/yihui/JSON-js via http://lisperator.net/uglifyjs/
I'm using the date of json2 as its version number, since it does not really have a version number

This should close rstudio/shiny-server#79
2014-07-10 17:56:23 -05:00
Yihui Xie
8063f66958 let's read ui.R, server.R, README.md, and DESCRIPTION also with UTF-8
the reason for this is that htmltools::htmlEscape() uses gsub(..., x, fixed =
TRUE), which does not work on Windows if x is encoded in UTF-8; fixed = TRUE
only works with the native encoding
2014-07-10 15:59:42 -05:00
Yihui Xie
bf270b9adb convert the message to native encoding from UTF-8 before decoding it
on Windows, switch(input$foo, foo1 = val1) does not work even if input$foo ==
foo1 but Encoding(input$foo) is UTF-8 while foo1 is unknown (native encoding);
to prevent such problems, let's always use native encoding inside the shiny
process, and only do the UTF-8 conversion at I/O time

special thanks to @desar for the thorough tests
2014-07-10 15:59:42 -05:00
Joe Cheng
972db08740 Merge pull request #539 from yihui/doc/conditionalPanel
add a Note section to the documentation of conditionalPanel(), since it ...
2014-07-10 00:41:36 -07:00
Yihui Xie
6326c7cbaa add a Note section to the documentation of conditionalPanel(), since it always confuses R users
e.g. https://groups.google.com/d/msg/shiny-discuss/AFItYcRXzyw/ywRy3EEtjw4J
2014-07-10 00:11:11 -05:00
Yihui Xie
4152ace514 Merge pull request #538 from rstudio/bugfix/showcase-nullref
fix #500: check for null source ref highlight points
2014-07-09 11:55:02 -05:00
Jonathan McPherson
038221408c fix #500: check for null source ref highlight points 2014-07-09 09:26:39 -07:00
Joe Cheng
9f76def7ce Merge pull request #533 from rstudio/bugfix/slow-options
Calling getOption() with default is slow
2014-07-06 16:38:25 -07:00
Joe Cheng
1b83770c5c Merge pull request #528 from yihui/bugfix/showcase-encoding
use UTF-8 for showcase mode, and assume DESCRIPTION is also UTF-8
2014-07-06 12:13:05 -07:00
Joe Cheng
3458d924ca Calling getOption() with default is slow
This has a measurable effect in apps with lots of reactives.

Reported by Aran Lunzer
2014-07-06 12:10:51 -07:00
Yihui Xie
0749b9500c use UTF-8 for showcase mode, and assume DESCRIPTION is also UTF-8
this time we should fix #136 now; I did not find other files that have to be
read with UTF-8
2014-06-26 15:41:12 -05:00
Jonathan
b1dfc18a8c Merge pull request #527 from rstudio/render-rmd-warning
Emit R Markdown warnings for render* functions as well as shinyApps
2014-06-25 11:18:41 -07:00
Jonathan McPherson
7b25c282c0 append rather than replace knit_meta with Shiny warning 2014-06-25 10:20:07 -07:00
Yihui Xie
a128ceaf2d bump version 2014-06-25 10:41:34 -05:00
Jonathan McPherson
f266cab580 emit R Markdown warnings for render* functions as well as shinyApps 2014-06-24 16:43:58 -07:00
Yihui Xie
23bf9aaf17 Merge pull request #526 from rstudio/bugfix/plot-captures-output
Revert "tweak after #492: capture.output() does withVisible() and print(...
2014-06-24 13:40:45 -05:00
Joe Cheng
1983f60ec6 Revert "tweak after #492: capture.output() does withVisible() and print() if necessary"
This reverts commit 451f950d0d.

Too-aggressive capture.output was causing browser() not to work in
renderPlot().
2014-06-24 06:09:36 -07:00
Yihui Xie
27f8909406 bump version 2014-06-19 13:50:39 -05:00
Yihui Xie
9988206911 add news for #512 2014-06-19 13:50:06 -05:00
Joe Cheng
31fe1fdfa6 Merge pull request #523 from rstudio/feature/navbarPage-windowTitle
Add windowTitle parameter to navbarPage
2014-06-19 10:45:01 -07:00
Joe Cheng
77b125ce2d Add windowTitle parameter to navbarPage
Fixes #493
2014-06-19 09:36:50 -07:00
Joe Cheng
6e68e07aa2 Merge pull request #512 from yihui/feature/inline-output
Inline output in R Markdown documents
2014-06-19 09:20:13 -07:00
Yihui Xie
86bb010a93 roxygenize 2014-06-19 00:24:10 -05:00
Yihui Xie
4a623b596b ignore width/height in plotOutput() when inline=TRUE, and document required width/height values in renderPlot() 2014-06-19 00:24:10 -05:00
Yihui Xie
bcf098ea7d merge doc of width and height in renderPlot() and plotOutput() 2014-06-19 00:24:10 -05:00
Yihui Xie
4bfb226fb5 roxygenize 2014-06-19 00:24:10 -05:00
Yihui Xie
691615108b preserve the formal arguments of plotOutput() in outputFunc()
otherwise outputFunc() loses the `inline` argument, and knit_print() won't be able to produce inline plots
2014-06-19 00:24:10 -05:00
Yihui Xie
858ab00e36 closes #501: knit_print() for inline output uses the inline argument passed from knitr 2014-06-19 00:24:10 -05:00
Yihui Xie
7023f5b145 add an inline argument to textOutput(), imageOutput(), plotOutput(), and htmlOutput() 2014-06-19 00:24:10 -05:00
Yihui Xie
eb4fabeac6 fix two more staticdocs errors 2014-06-19 00:17:55 -05:00
Joe Cheng
a5e09f9ce4 Merge tag 'v/0/10/0-staticdocs' 2014-06-18 11:12:40 -07:00
Joe Cheng
c2fe4e8b6d Fix staticdoc errors 2014-06-18 11:11:21 -07:00
Winston Chang
5d22648d34 Merge pull request #513 from rstudio/feature/json-precision
Control precision of JSON numeric representation
2014-06-17 11:51:47 -05:00
Yihui Xie
066fd15184 quiet apt-get and install.packages() 2014-06-16 10:32:04 -05:00
Yihui Xie
fe90c230d5 r-base should just work, since the packages that need to be compiled are installed via apt-get 2014-06-16 10:07:54 -05:00
Yihui Xie
0b5ae92136 shiny 0.10.0 is on CRAN now, so the dependencies knitr and htmltools should be automatically detected 2014-06-16 10:05:33 -05:00
Yihui Xie
1c5565aaee a news item for #427 2014-06-16 09:59:32 -05:00
Yihui Xie
69c177a3ec a news item for #516 2014-06-16 09:50:59 -05:00
Joe Cheng
0645b3f65b Merge pull request #507 from yihui/doc/runUrl
Merge doc for runUrl(), runGist(), and runGitHub()
2014-06-16 01:19:52 -07:00
Joe Cheng
9e7471fcc0 Merge pull request #516 from yihui/bugfix/windows-encoding
Fixes #136: I18N support for Windows
2014-06-16 01:17:31 -07:00
Joe Cheng
c520f53799 Bump to development version number 2014-06-16 01:13:33 -07:00
Yihui Xie
0bf1386802 UTF8 encoding for runApp(list(ui, server)) as well 2014-06-13 18:53:36 -05:00
Yihui Xie
b2ab3797aa the cachedSource() function is not used anywhere, so perhaps we can remove it 2014-06-13 18:08:16 -05:00
Yihui Xie
ede0ca8bd1 make sure JSON messages are always encoded and decoded with UTF8
- per @jcheng5's suggestion, RJSONIO::fromJSON(encoding = 'UTF-8') actually works (no longer need my markUTF8 function)
- removed the global option 'shiny.transcode.json'
2014-06-13 18:07:01 -05:00
Yihui Xie
81e35f0cc3 make sure the HTML content is encoded in UTF8 2014-06-13 18:02:20 -05:00
Yihui Xie
237522a1f7 assuming all the input R scripts are UTF8 encoded
ui.R, server.R, and global.R
2014-06-13 18:00:46 -05:00
Joe Cheng
0cd1644cf1 Control precision of JSON numeric representation
Uses 16 digits by default, set shiny.json.digits option to customize
2014-06-10 15:02:45 -07:00
Yihui Xie
f31bb56ea6 subdir=NULL is the default of runUrl() 2014-06-09 22:24:51 -05:00
Yihui Xie
cf3b805c46 the message is not very useful, given that download() will emit a message 2014-06-09 22:24:51 -05:00
Yihui Xie
517283ca58 closes #427: runGitHub() can accept "username/repo" in its first argument 2014-06-09 22:24:51 -05:00
Yihui Xie
f416b7ba47 the name variable is not used anywhere 2014-06-09 22:21:29 -05:00
Yihui Xie
973190b7a1 let download() fail in this case (ref=NULL); since ref='master' by default, if the user provides another value, he/she is expected to have read the documentation 2014-06-09 22:21:29 -05:00
Yihui Xie
f536a9d3d3 move runGist() and runGithub() after runUrl(), and merge their descriptions into the description of runUrl() 2014-06-09 22:21:29 -05:00
Yihui Xie
1348ec3bcf closes #213: merge the documentation of runUrl(), runGithub(), and runGist()
removed the port and launch.browser arguments, and used ... instead
2014-06-09 21:45:52 -05:00
45 changed files with 754 additions and 527 deletions

1
.gitattributes vendored Normal file
View File

@@ -0,0 +1 @@
/NEWS merge=union

View File

@@ -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:

View File

@@ -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>

View File

@@ -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
View File

@@ -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
View File

@@ -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
}

View File

@@ -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
#'

View File

@@ -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)) {

View File

@@ -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 {

View File

@@ -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)
}

View File

@@ -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,

View File

@@ -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() {

View File

@@ -75,6 +75,7 @@ createMockDomain <- function() {
#
## ------------------------------------------------------------------------
#' @name domains
#' @rdname domains
#' @export
getDefaultReactiveDomain <- function() {

View File

@@ -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, ...)
}

View File

@@ -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") {

View File

@@ -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)
},

View File

@@ -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)))
}
}

View File

@@ -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()))

View File

@@ -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",

View File

@@ -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))

View File

@@ -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))

View File

@@ -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))
}

View 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",

View File

@@ -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>&lt;A&gt;</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)
))
})

View File

@@ -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
View 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

View File

@@ -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

View File

@@ -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'))

View File

@@ -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(

View File

@@ -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}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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{

View File

@@ -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(

View File

@@ -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

View File

@@ -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")
}
}

View File

@@ -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/")
}
}

View File

@@ -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/")
}
}

View File

@@ -1,4 +1,4 @@
\name{tagList}
\name{tag}
\alias{tag}
\alias{tagAppendAttributes}
\alias{tagAppendChild}

View File

@@ -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"))

View File

@@ -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

View File

@@ -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

View File

@@ -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