Compare commits

...

61 Commits

Author SHA1 Message Date
Joe Cheng
c2fe4e8b6d Fix staticdoc errors 2014-06-18 11:11:21 -07:00
Joe Cheng
2f94e1d2c9 Fix timing issue with random seed test on windows 2014-06-13 14:40:19 -07:00
Joe Cheng
2689dd32bb Bump version to 0.10.0 2014-06-13 09:41:45 -07:00
Winston Chang
ad5e703b8f Merge pull request #514 from yihui/doc/news-flowLayout
typo: flowPanel --> flowLayout
2014-06-13 11:12:07 -05:00
Yihui Xie
d3bc2e9279 typo: flowPanel --> flowLayout 2014-06-13 11:05:36 -05:00
Winston Chang
f02b405c12 Merge pull request #508 from yihui/bugfix/large-margin
set the margin to 0 before plot.new()
2014-06-10 11:57:07 -05:00
Yihui Xie
baa7036799 explain why par(mar = rep(0, 4)) is necessary before plot.new(), per @wch's suggestion 2014-06-10 11:50:49 -05:00
Yihui Xie
431aecaf00 set the margin to 0 before plot.new()
otherwise users will be unable to draw small plots because of the common error "figure margin too large", e.g. renderPlot(..., width=200, height=100)
2014-06-10 00:46:33 -05:00
Joe Cheng
9a250a4861 Merge pull request #506 from yihui/bugfix/stats
stats may not have been loaded in the event of .onLoad()
2014-06-09 09:09:11 -07:00
Yihui Xie
6450927192 stats may not have been loaded in the event of .onLoad() 2014-06-09 10:56:36 -05:00
Joe Cheng
7c9dbdc802 Merge pull request #504 from rstudio/news-update
Update NEWS
2014-06-07 12:29:04 -07:00
Joe Cheng
8d460afe2d Merge pull request #505 from yihui/doc/splitLayout
there should not be #' before @examples
2014-06-06 23:38:00 -07:00
Yihui Xie
6c44c2cf24 there should not be #' before @examples 2014-06-07 01:00:13 -05:00
Joe Cheng
cea550ebba Update NEWS 2014-06-06 22:41:04 -07:00
Joe Cheng
911a352ee6 Bump version 2014-06-06 22:20:17 -07:00
Joe Cheng
3fadfbe06e Merge pull request #503 from rstudio/bugfix/shinyapps-in-tags-2
Allow shinyApp objects to appear inside tags
2014-06-06 22:16:35 -07:00
Joe Cheng
5bf362927f Allow shinyApp objects to appear inside tags 2014-06-06 15:23:13 -07:00
Yihui Xie
4da5ca5ba9 bump version 2014-06-06 17:07:17 -05:00
Yihui Xie
d747005b30 copy the documentation of knit_print methods from htmltools, too 2014-06-06 17:07:10 -05:00
Yihui Xie
03a395107d export knit_print methods imported from htmltools 2014-06-06 16:59:12 -05:00
Yihui Xie
58ef4ccabf declare the method through @method per @hadley's suggestion at klutometis/roxygen#256 2014-06-04 16:30:12 -05:00
Yihui Xie
71ed082bb5 bump version 2014-06-04 15:41:33 -05:00
Yihui Xie
0819ac8124 no need to assign a copy of these functions in shiny, because we have imported htmltools, and we only need to export the imported functions 2014-06-04 15:38:41 -05:00
Yihui Xie
0cdd223172 cosmetic changes after #481, and roxygenize 2014-06-04 15:30:15 -05:00
Yihui Xie
571393f146 htmltools was in both Depends and Imports, against which R CMD check will warn
I guess it was in Depends because otherwise as.tags could not be treated as an S3 generic; sounds like a bug of roxygen2 or devtools
2014-06-04 15:30:15 -05:00
Yihui Xie
c85868c652 use @export instead of @S3method 2014-06-04 15:10:45 -05:00
Joe Cheng
a7a6f3b020 Merge pull request #499 from yihui/bugfix/456
Bugfix/456
2014-06-03 10:01:44 -07:00
Yihui Xie
3a0a11d55a introduce an equivalent function to achieve set.seed(NULL) in R 2.15.x 2014-06-02 16:14:22 -05:00
Yihui Xie
7eb8ddf372 fixes #456: use .Random.seed only if it exists in the global environment
e.g. the expr may not trigger the creation of .Random.seed, such as set.seed(NULL) under R 2.15.x, which will fail
2014-06-02 16:13:37 -05:00
Yihui Xie
87af63644a bump version 2014-06-02 15:38:40 -05:00
Yihui Xie
0a9dd18070 news for #433 2014-06-02 15:36:36 -05:00
Yihui Xie
f82b061ba7 news for #481 2014-06-02 15:18:54 -05:00
Yihui Xie
c17509e2a0 news for #495 2014-06-02 15:18:54 -05:00
Yihui Xie
cb383d4f62 serverInfo() returns list(shinyServer=FALSE) by default, per suggestion of @trestletech 2014-06-02 15:18:54 -05:00
Yihui Xie
451f950d0d tweak after #492: capture.output() does withVisible() and print() if necessary 2014-06-02 15:18:54 -05:00
Yihui Xie
bd0eae0961 Merge pull request #481 from saurfang/master
Add inline option for RadioButton and checkboxGroupInput
2014-06-02 15:03:40 -05:00
Joe Cheng
53a401f847 Merge pull request #495 from yihui/feature/serverInfo
add functions serverInfo() (exported) and setServerInfo() (not exported)
2014-06-02 09:16:51 -07:00
JJ Allaire
b288f5ca19 bump version 2014-06-02 08:11:02 -04:00
JJ Allaire
7a2fc19c4f bump version 2014-06-01 10:00:40 -04:00
JJ Allaire
046d712d6a Revert "Allow Shiny apps to appear inside other tags"
This reverts commit 9ab2f5338e.
2014-06-01 09:59:50 -04:00
Joe Cheng
e829aaecf1 Install htmltools in travis script 2014-05-31 10:58:54 -07:00
Joe Cheng
9ab2f5338e Allow Shiny apps to appear inside other tags 2014-05-31 09:06:54 -07:00
Joe Cheng
d7bda924be Depend on htmltools, not just Import
This seems to be necessary to get the knit_print.shiny.tags to work
with Rmarkdown without an explicit library(htmltools)
2014-05-31 08:26:09 -07:00
Joe Cheng
07eb2e51b7 Bump version to 0.9.1.9009 2014-05-31 08:08:08 -07:00
Joe Cheng
dfafa7ae40 Merge branch 'htmltools-refactor' 2014-05-31 08:06:56 -07:00
Joe Cheng
dde266768c Restore HTML generating functions
These functions were temporarily ripped out of Shiny and moved
to the htmltools package. We've discovered that it's safe to
keep including them in shiny; as long as the functions in shiny
and the functions in htmltools are identical, the user won't
receive a conflict warning.
2014-05-31 08:06:03 -07:00
Joe Cheng
01c81675f7 Make S3 method consistent with base 2014-05-31 08:06:03 -07:00
Joe Cheng
71972eb362 Update htmltools version 2014-05-31 08:06:03 -07:00
Joe Cheng
eb9f5f9025 Dependency fixes
1) Give bootstrap deps a path so they can be used in static docs
2) Resolve dependencies before rendering page (whoops)
2014-05-31 08:06:03 -07:00
Joe Cheng
eb4d4d7437 Adapt to htmltools 0.2.1 API 2014-05-31 08:06:03 -07:00
Joe Cheng
1cb5e09109 Remove obsolete entry from staticdocs index 2014-05-31 08:06:03 -07:00
Joe Cheng
cc82fff5d3 Add S3 method for turning render function into tags 2014-05-31 08:06:03 -07:00
Joe Cheng
3212e59dcc Fix broken client-side HTML dependency rendering 2014-05-31 08:06:03 -07:00
Joe Cheng
44a795bf18 Extract HTML functionality to htmltools library 2014-05-31 08:06:03 -07:00
Joe Cheng
376e6f35a2 Merge pull request #496 from eiriksm/travis-fix
Use svg version of build status. Only show master build status.
2014-05-31 08:03:16 -07:00
Eirik S. Morland
3b324e9532 Use svg version of build status. Only show master build status. 2014-05-31 12:04:00 +02:00
saurfang
063b58eebb Merge remote-tracking branch 'upstream/master' 2014-05-17 16:33:25 -04:00
Yihui Xie
01c24a578b add functions serverInfo() (exported) and setServerInfo() (not exported)
we can call shiny:::setServerInfo() in Shiny Server before launching an app, so that the app author can make use of the info to decide the behavior of the app
2014-05-16 13:22:22 -05:00
saurfang
6b82354129 Merge remote-tracking branch 'upstream/master' 2014-05-15 12:30:52 -04:00
saurfang
bab200ff03 Merge remote-tracking branch 'upstream/master' 2014-05-14 15:44:23 -04:00
saurfang
b0f95cd9e0 Add inline options
inline options for radiobuttons and checkboxgroupinput to allow choices
rendered horizontally
2014-05-13 17:18:20 -04:00
142 changed files with 371 additions and 1699 deletions

View File

@@ -10,3 +10,4 @@
^man-roxygen$
^\.travis\.yml$
^staticdocs$
^tools$

View File

@@ -13,8 +13,7 @@ install:
- sudo apt-get update
- sudo apt-get install r-base-dev r-cran-shiny r-cran-cairo r-cran-markdown
- "[ ! -d ~/R ] && mkdir ~/R"
- Rscript -e "install.packages(c('xtable'), repos = 'http://cran.rstudio.org')"
- Rscript -e "install.packages('knitr', repos = c('http://rforge.net', 'http://cran.rstudio.org'))"
- 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')"
# run tests

View File

@@ -1,8 +1,8 @@
Package: shiny
Type: Package
Title: Web Application Framework for R
Version: 0.9.1.9008
Date: 2014-03-19
Version: 0.10.0
Date: 2014-06-13
Author: RStudio, Inc.
Maintainer: Winston Chang <winston@rstudio.com>
Description: Shiny makes it incredibly easy to build interactive web
@@ -20,13 +20,14 @@ Imports:
caTools,
RJSONIO,
xtable,
digest
digest,
htmltools (>= 0.2.4)
Suggests:
datasets,
markdown,
Cairo (>= 1.5-5),
testthat,
knitr
knitr (>= 1.6),
markdown
URL: http://www.rstudio.com/shiny/
BugReports: https://github.com/rstudio/shiny/issues
Roxygen: list(wrap = FALSE)
@@ -36,13 +37,13 @@ Collate:
'map.R'
'globals.R'
'utils.R'
'htmltools.R'
'bootstrap.R'
'cache.R'
'fileupload.R'
'graph.R'
'hooks.R'
'html-deps.R'
'htmltools.R'
'imageutils.R'
'jqueryui.R'
'middleware-shiny.R'
@@ -58,7 +59,6 @@ Collate:
'shinywrappers.R'
'showcase.R'
'slider.R'
'tags.R'
'tar.R'
'timer.R'
'update-input.R'

View File

@@ -1,4 +1,4 @@
# Generated by roxygen2 (4.0.0): do not edit by hand
# Generated by roxygen2 (4.0.1): do not edit by hand
S3method("$",reactivevalues)
S3method("$",shinyoutput)
@@ -13,21 +13,15 @@ S3method("[[",shinyoutput)
S3method("[[<-",reactivevalues)
S3method("[[<-",shinyoutput)
S3method("names<-",reactivevalues)
S3method(as.character,shiny.tag)
S3method(as.character,shiny.tag.list)
S3method(as.list,reactivevalues)
S3method(as.shiny.appobj,character)
S3method(as.shiny.appobj,list)
S3method(as.shiny.appobj,shiny.appobj)
S3method(format,html)
S3method(format,shiny.tag)
S3method(format,shiny.tag.list)
S3method(as.tags,shiny.appobj)
S3method(as.tags,shiny.render.function)
S3method(names,reactivevalues)
S3method(print,html)
S3method(print,reactive)
S3method(print,shiny.appobj)
S3method(print,shiny.tag)
S3method(print,shiny.tag.list)
S3method(str,reactivevalues)
export(HTML)
export(a)
@@ -62,7 +56,6 @@ export(flowLayout)
export(fluidPage)
export(fluidRow)
export(getDefaultReactiveDomain)
export(getProvidedHtmlDependencies)
export(h1)
export(h2)
export(h3)
@@ -86,7 +79,9 @@ export(installExprFunction)
export(invalidateLater)
export(is.reactive)
export(is.reactivevalues)
export(is.singleton)
export(isolate)
export(knit_print.html)
export(knit_print.shiny.appobj)
export(knit_print.shiny.render.function)
export(knit_print.shiny.tag)
@@ -138,6 +133,7 @@ export(runGitHub)
export(runUrl)
export(selectInput)
export(selectizeInput)
export(serverInfo)
export(shinyApp)
export(shinyAppDir)
export(shinyServer)
@@ -188,6 +184,7 @@ export(withTags)
import(RJSONIO)
import(caTools)
import(digest)
import(htmltools)
import(httpuv)
import(methods)
import(xtable)

34
NEWS
View File

@@ -1,9 +1,18 @@
shiny 0.9.1.9XXX
shiny 0.10.0
--------------------------------------------------------------------------------
* BREAKING CHANGE: By default, observers now terminate themselves if they were
created during a session and that session ends. See ?domains for more details.
* Shiny can now be used in R Markdown v2 documents, to create "Shiny Docs":
reports and presentations that combine narrative, statically computed output,
and fully dynamic inputs and outputs. For more info, including examples, see
http://rmarkdown.rstudio.com/authoring_shiny.html.
* The `session` object that can be passed into a server function (e.g.
shinyServer(function(input, output, session) {...})) is now documented: see
`?session`.
* Most inputs can now accept `NULL` label values to omit the label altogether.
* New `actionLink` input control; like `actionButton`, but with the appearance
@@ -12,20 +21,39 @@ shiny 0.9.1.9XXX
* `renderPlot` now calls `print` on its result if it's visible (i.e. no more
explicit `print()` required for ggplot2).
* Introduced Shiny app objects (see `?shinyApp`). These essentially replace the
little-advertised ability for `runApp` to take a `list(ui=..., server=...)`
as the first argument instead of a directory (though that ability remains for
backward compatibility). Unlike those lists, Shiny app objects are tagged with
class `shiny.appobj` so they can be run simply by printing them.
* Added `maskReactiveContext` function. It blocks the current reactive context,
to evaluate expressions that shouldn't use reactive sources directly. (This
should not be commonly needed.)
* Added `flowLayout`, `splitLayout`, and `inputPanel` functions for putting UI
elements side by side. `flowPanel` lays out its children in a left-to-right,
elements side by side. `flowLayout` lays out its children in a left-to-right,
top-to-bottom arrangement. `splitLayout` evenly divides its horizontal space
among its children (or unevenly divides if `cellWidths` argument is provided).
`inputPanel` is like `flowPanel`, but with a light grey background, and is
intended to be used to encapsulate small input controls wherever vertical
space is at a premium.
* Added `serverInfo` to obtain info about the Shiny Server if the app is served
through it.
* Added an `inline` argument (TRUE/FALSE) in `checkboxGroupInput()` and
`radioButtons()` to allow the horizontal layout (inline = TRUE) of checkboxes
or radio buttons. (Thanks, @saurfang, #481)
* `sliderInput` and `selectizeInput`/`selectInput` now use a standard horizontal
size instead of filling up all available horizontal space.
size instead of filling up all available horizontal space. Pass `width="100%"`
explicitly for the old behavior.
* Added the `updateSelectizeInput()` function to make it possible to process
searching on the server side (i.e. using R), which can be much faster than the
client side processing (i.e. using HTML and JavaScript). See the article at
http://shiny.rstudio.com/articles/selectize.html for a detailed introduction.
* Fixed a bug of renderDataTable() when the data object only has 1 row and 1
column. (Thanks, ZJ Dai, #429)

52
R/app.R
View File

@@ -224,6 +224,21 @@ print.shiny.appobj <- function(x, ...) {
do.call(runApp, args)
}
#' @rdname shinyApp
#' @method as.tags shiny.appobj
#' @export
as.tags.shiny.appobj <- function(x, ...) {
# jcheng 06/06/2014: Unfortunate copy/paste between this function and
# knit_print.shiny.appobj, but I am trying to make the most conservative
# change possible due to upcoming release.
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
path <- addSubApp(x)
tags$iframe(src=path, width=width, height=height, class="shiny-frame")
}
#' Knitr S3 methods
#'
#' These S3 methods are necessary to help Shiny applications and UI chunks embed
@@ -273,37 +288,10 @@ knit_print.shiny.appobj <- function(x, ...) {
# need to grab those and put them in meta, like in knit_print.shiny.tag. But
# for now it's not an issue, so just return the HTML and warning.
knitr::asis_output(html_preserve(format(output, indent=FALSE)),
knitr::asis_output(htmlPreserve(format(output, indent=FALSE)),
meta = shiny_warning, cacheable = FALSE)
}
#' @rdname knitr_methods
#' @export
knit_print.shiny.tag <- function(x, ...) {
output <- surroundSingletons(x)
deps <- getNewestDeps(findDependencies(x))
content <- takeHeads(output)
head_content <- doRenderTags(tagList(content$head))
meta <- if (length(head_content) > 1 || head_content != "") {
list(structure(head_content, class = "shiny_head"))
}
meta <- c(meta, deps)
knitr::asis_output(html_preserve(format(content$ui, indent=FALSE)), meta = meta)
}
knit_print.html <- function(x, ...) {
deps <- getNewestDeps(findDependencies(x))
knitr::asis_output(html_preserve(as.character(x)),
meta = if (length(deps)) list(deps))
}
#' @rdname knitr_methods
#' @export
knit_print.shiny.tag.list <- knit_print.shiny.tag
# Lets us use a nicer syntax in knitr chunks than literally
# calling output$value <- renderFoo(...) and fooOutput().
#' @rdname knitr_methods
@@ -313,11 +301,3 @@ knit_print.shiny.render.function <- function(x, ...) {
attr(output, "knit_cacheable") <- FALSE
output
}
html_preserve <- function(x) {
x <- paste(x, collapse = "\r\n")
if (nzchar(x))
sprintf("<!--html_preserve-->%s<!--/html_preserve-->", x)
else
x
}

View File

@@ -320,7 +320,7 @@ verticalLayout <- function(..., fluid = TRUE) {
#'
#' @seealso \code{\link{verticalLayout}}
#'
#' #' @examples
#' @examples
#' flowLayout(
#' numericInput("rows", "How many rows?", 5),
#' selectInput("letter", "Which letter?", LETTERS),
@@ -370,7 +370,7 @@ inputPanel <- function(...) {
#' @param cellArgs Any additional attributes that should be used for each cell
#' of the layout.
#'
#' #' @examples
#' @examples
#' # Equal sizing
#' splitLayout(
#' plotOutput("plot1"),

View File

@@ -1,5 +1,4 @@
#' @include utils.R
#' @include htmltools.R
NULL
#' Create a Bootstrap page
@@ -38,16 +37,19 @@ bootstrapPage <- function(..., title = NULL, responsive = TRUE, theme = NULL) {
}
cssExt <- ext(".css")
jsExt = ext(".js")
bs <- "shared/bootstrap"
bs <- c(
href = "shared/bootstrap",
file = system.file("www/shared/bootstrap", package = "shiny")
)
list(
html_dependency("bootstrap", "2.3.2", path = bs,
htmlDependency("bootstrap", "2.3.2", bs,
script = sprintf("js/bootstrap%s", jsExt),
stylesheet = if (is.null(theme))
sprintf("css/bootstrap%s", cssExt)
),
if (responsive) {
html_dependency("bootstrap-responsive", "2.3.2", path = bs,
htmlDependency("bootstrap-responsive", "2.3.2", bs,
stylesheet = sprintf("css/bootstrap-responsive%s", cssExt),
meta = list(viewport = "width=device-width, initial-scale=1.0")
)
@@ -55,7 +57,7 @@ bootstrapPage <- function(..., title = NULL, responsive = TRUE, theme = NULL) {
)
}
attach_dependency(
attachDependencies(
tagList(
if (!is.null(title)) tags$head(tags$title(title)),
if (!is.null(theme)) {
@@ -555,6 +557,7 @@ checkboxInput <- function(inputId, label, value = FALSE) {
#' @param 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.
#' @param selected The values that should be initially selected, if any.
#' @param inline If \code{TRUE}, render the choices inline (i.e. horizontally)
#' @return A list of HTML elements that can be added to a UI definition.
#'
#' @family input elements
@@ -567,7 +570,7 @@ checkboxInput <- function(inputId, label, value = FALSE) {
#' "Gears" = "gear"))
#'
#' @export
checkboxGroupInput <- function(inputId, label, choices, selected = NULL) {
checkboxGroupInput <- function(inputId, label, choices, selected = NULL, inline = FALSE) {
# resolve names
choices <- choicesWithNames(choices)
if (!is.null(selected))
@@ -587,7 +590,7 @@ checkboxGroupInput <- function(inputId, label, choices, selected = NULL) {
if (value %in% selected)
inputTag$attribs$checked <- "checked"
tags$label(class = "checkbox",
tags$label(class = if (inline) "checkbox inline" else "checkbox",
inputTag,
tags$span(name))
}
@@ -753,7 +756,8 @@ selectizeInput <- function(inputId, ..., options = NULL, width = NULL) {
selectizeIt <- function(inputId, select, options, width = NULL, nonempty = FALSE) {
res <- checkAsIs(options)
selectizeDep <- html_dependency("selectize", "0.8.5", "shared/selectize",
selectizeDep <- htmlDependency(
"selectize", "0.8.5", c(href = "shared/selectize"),
stylesheet = "css/selectize.bootstrap2.css",
head = format(tagList(
HTML('<!--[if lt IE 9]>'),
@@ -762,7 +766,7 @@ selectizeIt <- function(inputId, select, options, width = NULL, nonempty = FALSE
tags$script(src = 'shared/selectize/js/selectize.min.js')
))
)
attach_dependency(
attachDependencies(
tagList(
select,
tags$script(
@@ -787,6 +791,7 @@ selectizeIt <- function(inputId, select, options, width = NULL, nonempty = FALSE
#' named then that name rather than the value is displayed to the user)
#' @param selected The initially selected value (if not specified then
#' defaults to the first value)
#' @param inline If \code{TRUE}, render the choices inline (i.e. horizontally)
#' @return A set of radio buttons that can be added to a UI definition.
#'
#' @family input elements
@@ -799,7 +804,7 @@ selectizeIt <- function(inputId, select, options, width = NULL, nonempty = FALSE
#' "Log-normal" = "lnorm",
#' "Exponential" = "exp"))
#' @export
radioButtons <- function(inputId, label, choices, selected = NULL) {
radioButtons <- function(inputId, label, choices, selected = NULL, inline = FALSE) {
# resolve names
choices <- choicesWithNames(choices)
@@ -823,7 +828,7 @@ radioButtons <- function(inputId, label, choices, selected = NULL) {
inputTag$attribs$checked = "checked"
# Put the label text in a span
tags$label(class = "radio",
tags$label(class = if (inline) "radio inline" else "radio",
inputTag,
tags$span(name)
)
@@ -979,8 +984,9 @@ sliderInput <- function(inputId, label, min, max, value, step = NULL,
}
}
datePickerDependency <- html_dependency("bootstrap-datepicker", "1.0.2",
"shared/datepicker", script = "js/bootstrap-datepicker.min.js",
datePickerDependency <- htmlDependency(
"bootstrap-datepicker", "1.0.2", c(href = "shared/datepicker"),
script = "js/bootstrap-datepicker.min.js",
stylesheet = "css/datepicker.css")
#' Create date input
@@ -1059,7 +1065,7 @@ dateInput <- function(inputId, label, value = NULL, min = NULL, max = NULL,
if (inherits(min, "Date")) min <- format(min, "%Y-%m-%d")
if (inherits(max, "Date")) max <- format(max, "%Y-%m-%d")
attach_dependency(
attachDependencies(
tags$div(id = inputId,
class = "shiny-date-input",
@@ -1158,7 +1164,7 @@ dateRangeInput <- function(inputId, label, start = NULL, end = NULL,
if (inherits(min, "Date")) min <- format(min, "%Y-%m-%d")
if (inherits(max, "Date")) max <- format(max, "%Y-%m-%d")
attach_dependency(
attachDependencies(
tags$div(id = inputId,
# input-daterange class is needed for dropdown behavior
class = "shiny-date-range-input input-daterange",
@@ -1604,12 +1610,12 @@ tableOutput <- function(outputId) {
}
dataTableDependency <- list(
html_dependency(
"datatables", "1.9.4", "shared/datatables",
htmlDependency(
"datatables", "1.9.4", c(href = "shared/datatables"),
script = "js/jquery.dataTables.min.js"
),
html_dependency(
"datatables-bootstrap", "1.9.4", "shared/datatables",
htmlDependency(
"datatables-bootstrap", "1.9.4", c(href = "shared/datatables"),
stylesheet = "css/DT_bootstrap.css",
script = "js/DT_bootstrap.js"
)
@@ -1618,7 +1624,7 @@ dataTableDependency <- list(
#' @rdname tableOutput
#' @export
dataTableOutput <- function(outputId) {
attach_dependency(
attachDependencies(
div(id = outputId, class="shiny-datatable-output"),
dataTableDependency
)
@@ -1762,49 +1768,3 @@ icon <- function(name, class = NULL, lib = "font-awesome") {
iconClass <- function(icon) {
if (!is.null(icon)) icon[[2]]$attribs$class
}
#' Validate proper CSS formatting of a unit
#'
#' Checks that the argument is valid for use as a CSS unit of length.
#'
#' \code{NULL} and \code{NA} are returned unchanged.
#'
#' Single element numeric vectors are returned as a character vector with the
#' number plus a suffix of \code{"px"}.
#'
#' Single element character vectors must be \code{"auto"} or \code{"inherit"},
#' or a number. If the number has a suffix, it must be valid: \code{px},
#' \code{\%}, \code{em}, \code{pt}, \code{in}, \code{cm}, \code{mm}, \code{ex},
#' or \code{pc}. If the number has no suffix, the suffix \code{"px"} is
#' appended.
#'
#' Any other value will cause an error to be thrown.
#'
#' @param x The unit to validate. Will be treated as a number of pixels if a
#' unit is not specified.
#' @return A properly formatted CSS unit of length, if possible. Otherwise, will
#' throw an error.
#' @examples
#' validateCssUnit("10%")
#' validateCssUnit(400) #treated as '400px'
#' @export
validateCssUnit <- function(x) {
if (is.null(x) || is.na(x))
return(x)
if (length(x) > 1 || (!is.character(x) && !is.numeric(x)))
stop('CSS units must be a numeric or character vector with a single element')
# if the input is a character vector consisting only of digits (e.g. "960"), coerce it to a
# numeric value
if (is.character(x) && nchar(x) > 0 && gsub("\\d*", "", x) == "")
x <- as.numeric(x)
if (is.character(x) &&
!grepl("^(auto|inherit|((\\.\\d+)|(\\d+(\\.\\d+)?))(%|in|cm|mm|em|ex|pt|pc|px))$", x)) {
stop('"', x, '" is not a valid CSS unit (e.g., "100%", "400px", "auto")')
} else if (is.numeric(x)) {
x <- paste(x, "px", sep = "")
}
x
}

View File

@@ -5,5 +5,5 @@
# R's lazy-loading package scheme causes the private seed to be cached in the
# package itself, making our PRNG completely deterministic. This line resets
# the private seed during load.
withPrivateSeed(set.seed(NULL))
withPrivateSeed(reinitializeSeed())
}

View File

@@ -1,5 +1,3 @@
pathPattern <- "^(~|/|[a-zA-Z]:[/\\\\]|\\\\\\\\)"
createWebDependency <- function(dependency) {
if (is.null(dependency))
return(NULL)
@@ -7,53 +5,11 @@ createWebDependency <- function(dependency) {
if (!inherits(dependency, "html_dependency"))
stop("Unexpected non-html_dependency type")
# Does it look like a path on disk? Register it as a resource and replace the
# disk-based path with a relative URL
if (grepl(pathPattern, dependency$path, perl = TRUE)) {
if (is.null(dependency$src$href)) {
prefix <- paste(dependency$name, "-", dependency$version, sep = "")
addResourcePath(prefix, dependency$path)
dependency$path <- prefix
addResourcePath(prefix, dependency$src$file)
dependency$src$href <- prefix
}
return(dependency)
}
# Given a list of dependencies, choose the latest versions and return them as a
# named list in the correct order.
getNewestDeps <- function(dependencies) {
result <- list()
for (dep in dependencies) {
if (!is.null(dep)) {
other <- result[[dep$name]]
if (is.null(other) || compareVersion(dep$version, other$version) > 0) {
# Note that if the dep was already in the result list, then this
# assignment preserves its position in the list
result[[dep$name]] <- dep
}
}
}
return(result)
}
# Remove `remove` from `dependencies` if the name matches.
# dependencies is a named list of dependencies.
# remove is a named list of dependencies that take priority.
# If warnOnConflict, then warn when a dependency is being removed because of an
# older version already being loaded.
removeDeps <- function(dependencies, remove, warnOnConflict = TRUE) {
matches <- names(dependencies) %in% names(remove)
if (warnOnConflict) {
for (depname in names(dependencies)[matches]) {
loser <- dependencies[[depname]]
winner <- remove[[depname]]
if (compareVersion(loser$version, winner$version) > 0) {
warning(sprintf(paste("The dependency %s %s conflicts with",
"version %s"), loser$name, loser$version, winner$version
))
}
}
}
# Return only deps that weren't in remove
return(dependencies[!matches])
}

View File

@@ -1,97 +1,7 @@
# Define an HTML dependency
#
# Define an HTML dependency (e.g. CSS or Javascript and related library). HTML
# dependency definitions are required for \code{\link{html_output}} that
# require CSS or JavaScript within the document head to render correctly.
#
# @param name Library name
# @param version Library version
# @param path Full path to library
# @param meta Named list of meta tags to insert into document head
# @param script Script(s) to include within the document head (should be
# specified relative to the \code{path} parameter).
# @param stylesheet Stylesheet(s) to include within the document (should be
# specified relative to the \code{path} parameter).
# @param head Arbitrary lines of HTML to insert into the document head
#
# @return An object that can be included in the list of dependencies passed to
# \code{\link{html_print}} or \code{\link{html_knit_print}}.
#
# @details See the documentation on
# \href{http://rmarkdown.rstudio.com/developer_html_widgets.html}{R
# Markdown HTML Widgets} for examples and additional details.
#
html_dependency <- function(name,
version,
path,
meta = NULL,
script = NULL,
stylesheet = NULL,
head = NULL) {
structure(class = "html_dependency", list(
name = name,
version = version,
path = path,
meta = meta,
script = script,
stylesheet = stylesheet,
head = head
))
}
# Given a list of HTML dependencies produce a character representation
# suitable for inclusion within the head of an HTML document
html_dependencies_as_character <- function(dependencies, lib_dir = NULL) {
html <- c()
for (dep in dependencies) {
# copy library files if necessary
if (!is.null(lib_dir)) {
if (!file.exists(lib_dir))
dir.create(lib_dir)
target_dir <- file.path(lib_dir, basename(dep$path))
if (!file.exists(target_dir))
file.copy(from = dep$path, to = lib_dir, recursive = TRUE)
dep$path <- file.path(basename(lib_dir), basename(target_dir))
}
# add meta content
for (name in names(dep$meta)) {
html <- c(html, paste("<meta name=\"", name,
"\" content=\"", dep$meta[[name]], "\" />",
sep = ""))
}
# add stylesheets
for (stylesheet in dep$stylesheet) {
stylesheet <- file.path(dep$path, stylesheet)
html <- c(html, paste("<link href=\"", stylesheet, "\" ",
"rel=\"stylesheet\" />",
sep = ""))
}
# add scripts
for (script in dep$script) {
script <- file.path(dep$path, script)
html <- c(html,
paste("<script src=\"", script, "\"></script>", sep = ""))
}
# add raw head content
html <- c(html, dep$head)
}
html
}
attach_dependency <- function(x, dependency) {
structure(x, html_dependency = dependency)
}
#' @export a br code div em h1 h2 h3 h4 h5 h6 hr HTML img p pre span strong
#' @export includeCSS includeHTML includeMarkdown includeScript includeText
#' @export is.singleton singleton
#' @export tag tagAppendAttributes tagAppendChild tagAppendChildren tagList tags tagSetChildren withTags
#' @export validateCssUnit
#' @export knit_print.html knit_print.shiny.tag knit_print.shiny.tag.list
NULL

View File

@@ -42,9 +42,15 @@ plotPNG <- function(func, filename=tempfile(fileext='.png'),
}
pngfun(filename=filename, width=width, height=height, res=res, ...)
# Call plot.new() so that even if no plotting operations are performed
# at least we have a blank background
plot.new()
# Call plot.new() so that even if no plotting operations are performed at
# least we have a blank background. N.B. we need to set the margin to 0
# temporarily before plot.new() because when the plot size is small (e.g.
# 200x50), we will get an error "figure margin too large", which is triggered
# by plot.new() with the default (large) margin. However, this does not
# guarantee user's code in func() will not trigger the error -- they may have
# to set par(mar = smaller_value) before they draw base graphics.
op <- par(mar = rep(0, 4))
tryCatch(plot.new(), finally = par(op))
dv <- dev.cur()
tryCatch(shinyCallingHandlers(func()), finally = dev.off(dv))

View File

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

View File

@@ -463,7 +463,7 @@ identicalFunctionBodies <- function(a, b) {
handlerManager <- HandlerManager$new()
addSubApp <- function(appObj, autoRemove = TRUE) {
path <- sprintf("/%s", createUniqueId(16))
path <- createUniqueId(16, "/app")
appHandlers <- createAppHandlers(appObj$httpHandler, appObj$serverFuncSource)
# remove the leading / from the path so a relative path is returned

View File

@@ -15,14 +15,19 @@ NULL
#' @name shiny-package
#' @aliases shiny
#' @docType package
#' @import httpuv caTools RJSONIO xtable digest methods
#' @import htmltools httpuv caTools RJSONIO xtable digest methods
NULL
createUniqueId <- function(bytes) {
createUniqueId <- function(bytes, prefix = "", suffix = "") {
withPrivateSeed({
paste(
format(as.hexmode(sample(256, bytes, replace = TRUE)-1), width=2),
collapse = "")
prefix,
paste(
format(as.hexmode(sample(256, bytes, replace = TRUE)-1), width=2),
collapse = ""),
suffix,
sep = ""
)
})
}

View File

@@ -1,143 +1,5 @@
#' @include globals.R
#' @rdname builder
#' @export
p <- function(...) tags$p(...)
#' @rdname builder
#' @export
h1 <- function(...) tags$h1(...)
#' @rdname builder
#' @export
h2 <- function(...) tags$h2(...)
#' @rdname builder
#' @export
h3 <- function(...) tags$h3(...)
#' @rdname builder
#' @export
h4 <- function(...) tags$h4(...)
#' @rdname builder
#' @export
h5 <- function(...) tags$h5(...)
#' @rdname builder
#' @export
h6 <- function(...) tags$h6(...)
#' @rdname builder
#' @export
a <- function(...) tags$a(...)
#' @rdname builder
#' @export
br <- function(...) tags$br(...)
#' @rdname builder
#' @export
div <- function(...) tags$div(...)
#' @rdname builder
#' @export
span <- function(...) tags$span(...)
#' @rdname builder
#' @export
pre <- function(...) tags$pre(...)
#' @rdname builder
#' @export
code <- function(...) tags$code(...)
#' @rdname builder
#' @export
img <- function(...) tags$img(...)
#' @rdname builder
#' @export
strong <- function(...) tags$strong(...)
#' @rdname builder
#' @export
em <- function(...) tags$em(...)
#' @rdname builder
#' @export
hr <- function(...) tags$hr(...)
#' Include Content From a File
#'
#' Include HTML, text, or rendered Markdown into a \link[=shinyUI]{Shiny UI}.
#'
#' These functions provide a convenient way to include an extensive amount of
#' HTML, textual, Markdown, CSS, or JavaScript content, rather than using a
#' large literal R string.
#'
#' @note \code{includeText} escapes its contents, but does no other processing.
#' This means that hard breaks and multiple spaces will be rendered as they
#' usually are in HTML: as a single space character. If you are looking for
#' preformatted text, wrap the call with \code{\link{pre}}, or consider using
#' \code{includeMarkdown} instead.
#'
#' @note The \code{includeMarkdown} function requires the \code{markdown}
#' package.
#'
#' @param path The path of the file to be included. It is highly recommended to
#' use a relative path (the base path being the Shiny application directory),
#' not an absolute path.
#'
#' @rdname include
#' @name include
#' @aliases includeHTML
#' @export
includeHTML <- function(path) {
dependsOnFile(path)
lines <- readLines(path, warn=FALSE, encoding='UTF-8')
return(HTML(paste(lines, collapse='\r\n')))
}
#' @rdname include
#' @export
includeText <- function(path) {
dependsOnFile(path)
lines <- readLines(path, warn=FALSE, encoding='UTF-8')
return(paste(lines, collapse='\r\n'))
}
#' @rdname include
#' @export
includeMarkdown <- function(path) {
library(markdown)
dependsOnFile(path)
html <- markdown::markdownToHTML(path, fragment.only=TRUE)
Encoding(html) <- 'UTF-8'
return(HTML(html))
}
#' @param ... Any additional attributes to be applied to the generated tag.
#' @rdname include
#' @export
includeCSS <- function(path, ...) {
dependsOnFile(path)
lines <- readLines(path, warn=FALSE, encoding='UTF-8')
args <- list(...)
if (is.null(args$type))
args$type <- 'text/css'
return(do.call(tags$style,
c(list(HTML(paste(lines, collapse='\r\n'))), args)))
}
#' @rdname include
#' @export
includeScript <- function(path, ...) {
dependsOnFile(path)
lines <- readLines(path, warn=FALSE, encoding='UTF-8')
return(tags$script(HTML(paste(lines, collapse='\r\n')), ...))
}
NULL
#' Load the MathJax library and typeset math expressions
#'
@@ -162,22 +24,6 @@ withMathJax <- function(...) {
)
}
#' Include Content Only Once
#'
#' Use \code{singleton} to wrap contents (tag, text, HTML, or lists) that should
#' be included in the generated document only once, yet may appear in the
#' document-generating code more than once. Only the first appearance of the
#' content (in document order) will be used. Useful for custom components that
#' have JavaScript files or stylesheets.
#'
#' @param x A \code{\link{tag}}, text, \code{\link{HTML}}, or list.
#'
#' @export
singleton <- function(x) {
class(x) <- c(class(x), 'shiny.singleton')
return(x)
}
renderPage <- function(ui, connection, showcase=0) {
if (showcase > 0)
@@ -187,17 +33,18 @@ renderPage <- function(ui, connection, showcase=0) {
deps <- c(
list(
html_dependency("jquery", "1.11.0", "shared", script = "jquery.js"),
html_dependency("shiny", packageVersion("shiny"), "shared",
htmlDependency("jquery", "1.11.0", c(href="shared"), script = "jquery.js"),
htmlDependency("shiny", packageVersion("shiny"), c(href="shared"),
script = "shiny.js", stylesheet = "shiny.css")
),
result$dependencies
)
deps <- resolveDependencies(deps)
deps <- lapply(deps, createWebDependency)
depStr <- paste(sapply(deps, function(dep) {
sprintf("%s[%s]", dep$name, dep$version)
}), collapse = ";")
depHtml <- html_dependencies_as_character(deps)
depHtml <- renderDependencies(deps, "href")
# write preamble
writeLines(c('<!DOCTYPE html>',
@@ -284,20 +131,3 @@ uiHttpHandler <- function(ui, path = "/") {
return(httpResponse(200, content=html))
}
}
#' Return HTML dependencies provided by Shiny
#'
#' By default, Shiny supplies some framework scripts when it renders a page.
#' \code{getProvidedHtmlDependencies} returns a list of those provided objects.
#'
#' @return A list of objects of type \code{html_dependency}, one per dependency
#'
#' @export
getProvidedHtmlDependencies <- function() {
list(structure(
list(name = "jquery",
version = "1.11.0",
path = system.file("www/shared/jquery.js", package="shiny"),
script = "jquery.js"),
class = "html_dependency"))
}

View File

@@ -23,13 +23,19 @@ markRenderFunction <- function(uiFunc, renderFunc) {
useRenderFunction <- function(renderFunc) {
outputFunction <- attr(renderFunc, "outputFunc")
id <- createUniqueId(8)
id <- createUniqueId(8, "out")
o <- getDefaultReactiveDomain()$output
if (!is.null(o))
o[[id]] <- renderFunc
return(outputFunction(id))
}
#' @export
#' @method as.tags shiny.render.function
as.tags.shiny.render.function <- function(x, ...) {
useRenderFunction(x)
}
#' Plot Output
#'
#' Renders a reactive plot that is suitable for assigning to an \code{output}
@@ -118,13 +124,9 @@ renderPlot <- function(expr, width='auto', height='auto', res=72, ...,
coordmap <- NULL
plotFunc <- function() {
# 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))
}
# Actually perform the plotting: use capture.output() to suppress output
# to console, and print func() if it returns a visible value
capture.output(func())
# Now capture some graphics device info before we close it
usrCoords <- par('usr')
@@ -459,7 +461,8 @@ renderUI <- function(expr, env=parent.frame(), quoted=FALSE, func=NULL) {
result <- takeSingletons(result, shinysession$singletons, desingleton=FALSE)$ui
result <- surroundSingletons(result)
dependencies <- lapply(getNewestDeps(findDependencies(result)), createWebDependency)
dependencies <- lapply(resolveDependencies(findDependencies(result)),
createWebDependency)
names(dependencies) <- NULL
# renderTags returns a list with head, singletons, and html

View File

@@ -31,13 +31,13 @@ licenseLink <- function(licenseName) {
showcaseHead <- function() {
deps <- list(
html_dependency("jqueryui", "1.10.4", "shared/jqueryui/1.10.4",
htmlDependency("jqueryui", "1.10.4", c(href="shared/jqueryui/1.10.4"),
script = "jquery-ui.min.js"),
html_dependency("showdown", "0.3.1", "shared/showdown/compressed",
htmlDependency("showdown", "0.3.1", c(href="shared/showdown/compressed"),
script = "showdown.js"),
html_dependency("font-awesome", "4.0.3", "shared/font-awesome",
htmlDependency("font-awesome", "4.0.3", c(href="shared/font-awesome"),
stylesheet = "css/font-awesome.min.css"),
html_dependency("highlight.js", "6.2", "shared/highlight",
htmlDependency("highlight.js", "6.2", c(href="shared/highlight"),
script = "highlight.pack.js")
)
@@ -54,7 +54,7 @@ showcaseHead <- function() {
else ""
))
return(attach_dependency(html, deps))
return(attachDependencies(html, deps))
}
# Returns tags containing the application metadata (title and author) in

View File

@@ -99,13 +99,12 @@ slider <- function(inputId, min, max, value, step = NULL, ...,
}
# build slider
dep <- html_dependency(name = "jslider", version = "1",
path = "shared/slider",
dep <- htmlDependency("jslider", "1", c(href="shared/slider"),
script = "js/jquery.slider.min.js",
stylesheet = "css/jquery.slider.min.css"
)
sliderFragment <- list(
attach_dependency(
attachDependencies(
tags$input(
id=inputId, type="slider",
name=inputId, value=paste(value, collapse=';'), class="jslider",

637
R/tags.R
View File

@@ -1,637 +0,0 @@
htmlEscape <- local({
.htmlSpecials <- list(
`&` = '&amp;',
`<` = '&lt;',
`>` = '&gt;'
)
.htmlSpecialsPattern <- paste(names(.htmlSpecials), collapse='|')
.htmlSpecialsAttrib <- c(
.htmlSpecials,
`'` = '&#39;',
`"` = '&quot;',
`\r` = '&#13;',
`\n` = '&#10;'
)
.htmlSpecialsPatternAttrib <- paste(names(.htmlSpecialsAttrib), collapse='|')
function(text, attribute=TRUE) {
pattern <- if(attribute)
.htmlSpecialsPatternAttrib
else
.htmlSpecialsPattern
# Short circuit in the common case that there's nothing to escape
if (!any(grepl(pattern, text)))
return(text)
specials <- if(attribute)
.htmlSpecialsAttrib
else
.htmlSpecials
for (chr in names(specials)) {
text <- gsub(chr, specials[[chr]], text, fixed=TRUE)
}
return(text)
}
})
isTag <- function(x) {
inherits(x, "shiny.tag")
}
#' @export
print.shiny.tag <- function(x, ...) {
print(as.character(x), ...)
invisible(x)
}
# indent can be numeric to indicate an initial indent level,
# or FALSE to suppress
#' @export
format.shiny.tag <- function(x, ..., singletons = character(0), indent = 0) {
as.character(renderTags(x, singletons = singletons, indent = indent)$html)
}
#' @export
as.character.shiny.tag <- function(x, ...) {
renderTags(x)$html
}
#' @export
print.shiny.tag.list <- print.shiny.tag
#' @export
format.shiny.tag.list <- format.shiny.tag
#' @export
as.character.shiny.tag.list <- as.character.shiny.tag
#' @export
print.html <- function(x, ...) {
cat(x, "\n")
invisible(x)
}
#' @export
format.html <- function(x, ...) {
as.character(x)
}
normalizeText <- function(text) {
if (!is.null(attr(text, "html")))
text
else
htmlEscape(text, attribute=FALSE)
}
#' @rdname tag
#' @export
tagList <- function(...) {
lst <- list(...)
class(lst) <- c("shiny.tag.list", "list")
return(lst)
}
#' @rdname tag
#' @export
tagAppendAttributes <- function(tag, ...) {
tag$attribs <- c(tag$attribs, list(...))
tag
}
#' @rdname tag
#' @export
tagAppendChild <- function(tag, child) {
tag$children[[length(tag$children)+1]] <- child
tag
}
#' @rdname tag
#' @export
tagAppendChildren <- function(tag, ..., list = NULL) {
tag$children <- c(tag$children, c(list(...), list))
tag
}
#' @rdname tag
#' @export
tagSetChildren <- function(tag, ..., list = NULL) {
tag$children <- c(list(...), list)
tag
}
#' HTML Tag Object
#'
#' \code{tag()} creates an HTML tag definition. Note that all of the valid HTML5
#' tags are already defined in the \code{\link{tags}} environment so these
#' functions should only be used to generate additional tags.
#' \code{tagAppendChild()} and \code{tagList()} are for supporting package
#' authors who wish to create their own sets of tags; see the contents of
#' bootstrap.R for examples.
#' @param _tag_name HTML tag name
#' @param varArgs List of attributes and children of the element. Named list
#' items become attributes, and unnamed list items become children. Valid
#' children are tags, single-character character vectors (which become text
#' nodes), and raw HTML (see \code{\link{HTML}}). You can also pass lists that
#' contain tags, text nodes, and HTML.
#' @param tag A tag to append child elements to.
#' @param child A child element to append to a parent tag.
#' @param ... Unnamed items that comprise this list of tags.
#' @param list An optional list of elements. Can be used with or instead of the
#' \code{...} items.
#' @return An HTML tag object that can be rendered as HTML using
#' \code{\link{as.character}()}.
#' @export
#' @examples
#' tagList(tags$h1("Title"),
#' tags$h2("Header text"),
#' tags$p("Text here"))
#'
#' # Can also convert a regular list to a tagList (internal data structure isn't
#' # exactly the same, but when rendered to HTML, the output is the same).
#' x <- list(tags$h1("Title"),
#' tags$h2("Header text"),
#' tags$p("Text here"))
#' tagList(x)
tag <- function(`_tag_name`, varArgs) {
# Get arg names; if not a named list, use vector of empty strings
varArgsNames <- names(varArgs)
if (is.null(varArgsNames))
varArgsNames <- character(length=length(varArgs))
# Named arguments become attribs, dropping NULL values
named_idx <- nzchar(varArgsNames)
attribs <- dropNulls(varArgs[named_idx])
# Unnamed arguments are flattened and added as children.
# Use unname() to remove the names attribute from the list, which would
# consist of empty strings anyway.
children <- unname(varArgs[!named_idx])
# Return tag data structure
structure(
list(name = `_tag_name`,
attribs = attribs,
children = children),
class = "shiny.tag"
)
}
tagWrite <- function(tag, textWriter, indent=0, eol = "\n") {
if (length(tag) == 0)
return (NULL)
# optionally process a list of tags
if (!isTag(tag) && is.list(tag)) {
tag <- dropNullsOrEmpty(flattenTags(tag))
lapply(tag, tagWrite, textWriter, indent)
return (NULL)
}
nextIndent <- if (is.numeric(indent)) indent + 1 else indent
indent <- if (is.numeric(indent)) indent else 0
# compute indent text
indentText <- paste(rep(" ", indent*2), collapse="")
# Check if it's just text (may either be plain-text or HTML)
if (is.character(tag)) {
textWriter(paste(indentText, normalizeText(tag), eol, sep=""))
return (NULL)
}
# write tag name
textWriter(paste(indentText, "<", tag$name, sep=""))
# Convert all attribs to chars explicitly; prevents us from messing up factors
attribs <- lapply(tag$attribs, as.character)
# concatenate attributes
# split() is very slow, so avoid it if possible
if (anyDuplicated(names(attribs)))
attribs <- lapply(split(attribs, names(attribs)), paste, collapse = " ")
# write attributes
for (attrib in names(attribs)) {
attribValue <- attribs[[attrib]]
if (!is.na(attribValue)) {
if (is.logical(attribValue))
attribValue <- tolower(attribValue)
text <- htmlEscape(attribValue, attribute=TRUE)
textWriter(paste(" ", attrib,"=\"", text, "\"", sep=""))
}
else {
textWriter(paste(" ", attrib, sep=""))
}
}
# write any children
children <- dropNullsOrEmpty(flattenTags(tag$children))
if (length(children) > 0) {
textWriter(">")
# special case for a single child text node (skip newlines and indentation)
if ((length(children) == 1) && is.character(children[[1]]) ) {
textWriter(paste(normalizeText(children[[1]]), "</", tag$name, ">", eol,
sep=""))
}
else {
textWriter("\n")
for (child in children)
tagWrite(child, textWriter, nextIndent)
textWriter(paste(indentText, "</", tag$name, ">", eol, sep=""))
}
}
else {
# only self-close void elements
# (see: http://dev.w3.org/html5/spec/single-page.html#void-elements)
if (tag$name %in% c("area", "base", "br", "col", "command", "embed", "hr",
"img", "input", "keygen", "link", "meta", "param",
"source", "track", "wbr")) {
textWriter(paste("/>", eol, sep=""))
}
else {
textWriter(paste("></", tag$name, ">", eol, sep=""))
}
}
}
doRenderTags <- function(ui, indent = 0) {
# Render the body--the bodyHtml variable will be created
conn <- file(open="w+")
connWriter <- function(text) writeChar(text, conn, eos = NULL)
htmlResult <- tryCatch({
tagWrite(ui, connWriter, indent)
flush(conn)
readLines(conn)
},
finally = close(conn)
)
return(HTML(paste(htmlResult, collapse = "\n")))
}
renderTags <- function(ui, singletons = character(0), indent = 0) {
# Do singleton and head processing before rendering
singletonInfo <- takeSingletons(ui, singletons)
headInfo <- takeHeads(singletonInfo$ui)
deps <- getNewestDeps(findDependencies(singletonInfo$ui))
headIndent <- if (is.numeric(indent)) indent + 1 else indent
headHtml <- doRenderTags(headInfo$head, indent = headIndent)
bodyHtml <- doRenderTags(headInfo$ui, indent = indent)
return(list(head = headHtml,
singletons = singletonInfo$singletons,
dependencies = deps,
html = bodyHtml))
}
# Walk a tree of tag objects, rewriting objects according to func.
# preorder=TRUE means preorder tree traversal, that is, an object
# should be rewritten before its children.
rewriteTags <- function(ui, func, preorder) {
if (preorder)
ui <- func(ui)
if (isTag(ui)) {
ui$children[] <- lapply(ui$children, rewriteTags, func, preorder)
} else if (is.list(ui)) {
ui[] <- lapply(ui, rewriteTags, func, preorder)
}
if (!preorder)
ui <- func(ui)
return(ui)
}
# Preprocess a tag object by changing any singleton X into
# <!--SHINY.SINGLETON[sig]-->X'<!--/SHINY.SINGLETON[sig]-->
# where sig is the sha1 of X, and X' is X minus the singleton
# attribute.
#
# In the case of nested singletons, outer singletons are processed
# before inner singletons (otherwise the processing of inner
# singletons would cause the sha1 of the outer singletons to be
# different).
surroundSingletons <- local({
surroundSingleton <- function(uiObj) {
if (inherits(uiObj, "shiny.singleton")) {
sig <- digest(uiObj, "sha1")
class(uiObj) <- class(uiObj)[class(uiObj) != "shiny.singleton"]
return(tagList(
HTML(sprintf("<!--SHINY.SINGLETON[%s]-->", sig)),
uiObj,
HTML(sprintf("<!--/SHINY.SINGLETON[%s]-->", sig))
))
} else {
uiObj
}
}
function(ui) {
rewriteTags(ui, surroundSingleton, TRUE)
}
})
# Given a tag object, apply singleton logic (allow singleton objects
# to appear no more than once per signature) and return the processed
# HTML objects and also the list of known singletons.
takeSingletons <- function(ui, singletons=character(0), desingleton=TRUE) {
result <- rewriteTags(ui, function(uiObj) {
if (inherits(uiObj, "shiny.singleton")) {
sig <- digest(uiObj, "sha1")
if (sig %in% singletons)
return(NULL)
singletons <<- append(singletons, sig)
if (desingleton)
class(uiObj) <- class(uiObj)[class(uiObj) != "shiny.singleton"]
return(uiObj)
} else {
return(uiObj)
}
}, TRUE)
return(list(ui=result, singletons=singletons))
}
# Given a tag object, extract out any children of tags$head
# and return them separate from the body.
takeHeads <- function(ui) {
headItems <- list()
result <- rewriteTags(ui, function(uiObj) {
if (isTag(uiObj) && tolower(uiObj$name) == "head") {
headItems <<- append(headItems, uiObj$children)
return(NULL)
}
return(uiObj)
}, FALSE)
return(list(ui=result, head=headItems))
}
findDependencies <- function(ui) {
dep <- attr(ui, "html_dependency")
if (!is.null(dep) && inherits(dep, "html_dependency"))
dep <- list(dep)
children <- if (is.list(ui)) {
if (isTag(ui)) {
ui$children
} else {
ui
}
}
childDeps <- unlist(lapply(children, findDependencies), recursive = FALSE)
c(childDeps, if (!is.null(dep)) dep)
}
#' HTML Builder Functions
#'
#' Simple functions for constructing HTML documents.
#'
#' The \code{tags} environment contains convenience functions for all valid
#' HTML5 tags. To generate tags that are not part of the HTML5 specification,
#' you can use the \code{\link{tag}()} function.
#'
#' Dedicated functions are available for the most common HTML tags that do not
#' conflict with common R functions.
#'
#' The result from these functions is a tag object, which can be converted using
#' \code{\link{as.character}()}.
#'
#' @name builder
#' @param ... Attributes and children of the element. Named arguments become
#' attributes, and positional arguments become children. Valid children are
#' tags, single-character character vectors (which become text nodes), and raw
#' HTML (see \code{\link{HTML}}). You can also pass lists that contain tags,
#' text nodes, and HTML.
#' @export tags
#' @examples
#' doc <- tags$html(
#' tags$head(
#' tags$title('My first page')
#' ),
#' tags$body(
#' h1('My first heading'),
#' p('My first paragraph, with some ',
#' strong('bold'),
#' ' text.'),
#' div(id='myDiv', class='simpleDiv',
#' 'Here is a div with some attributes.')
#' )
#' )
#' cat(as.character(doc))
NULL
#' @rdname builder
#' @format NULL
#' @docType NULL
#' @keywords NULL
tags <- list(
a = function(...) tag("a", list(...)),
abbr = function(...) tag("abbr", list(...)),
address = function(...) tag("address", list(...)),
area = function(...) tag("area", list(...)),
article = function(...) tag("article", list(...)),
aside = function(...) tag("aside", list(...)),
audio = function(...) tag("audio", list(...)),
b = function(...) tag("b", list(...)),
base = function(...) tag("base", list(...)),
bdi = function(...) tag("bdi", list(...)),
bdo = function(...) tag("bdo", list(...)),
blockquote = function(...) tag("blockquote", list(...)),
body = function(...) tag("body", list(...)),
br = function(...) tag("br", list(...)),
button = function(...) tag("button", list(...)),
canvas = function(...) tag("canvas", list(...)),
caption = function(...) tag("caption", list(...)),
cite = function(...) tag("cite", list(...)),
code = function(...) tag("code", list(...)),
col = function(...) tag("col", list(...)),
colgroup = function(...) tag("colgroup", list(...)),
command = function(...) tag("command", list(...)),
data = function(...) tag("data", list(...)),
datalist = function(...) tag("datalist", list(...)),
dd = function(...) tag("dd", list(...)),
del = function(...) tag("del", list(...)),
details = function(...) tag("details", list(...)),
dfn = function(...) tag("dfn", list(...)),
div = function(...) tag("div", list(...)),
dl = function(...) tag("dl", list(...)),
dt = function(...) tag("dt", list(...)),
em = function(...) tag("em", list(...)),
embed = function(...) tag("embed", list(...)),
eventsource = function(...) tag("eventsource", list(...)),
fieldset = function(...) tag("fieldset", list(...)),
figcaption = function(...) tag("figcaption", list(...)),
figure = function(...) tag("figure", list(...)),
footer = function(...) tag("footer", list(...)),
form = function(...) tag("form", list(...)),
h1 = function(...) tag("h1", list(...)),
h2 = function(...) tag("h2", list(...)),
h3 = function(...) tag("h3", list(...)),
h4 = function(...) tag("h4", list(...)),
h5 = function(...) tag("h5", list(...)),
h6 = function(...) tag("h6", list(...)),
head = function(...) tag("head", list(...)),
header = function(...) tag("header", list(...)),
hgroup = function(...) tag("hgroup", list(...)),
hr = function(...) tag("hr", list(...)),
html = function(...) tag("html", list(...)),
i = function(...) tag("i", list(...)),
iframe = function(...) tag("iframe", list(...)),
img = function(...) tag("img", list(...)),
input = function(...) tag("input", list(...)),
ins = function(...) tag("ins", list(...)),
kbd = function(...) tag("kbd", list(...)),
keygen = function(...) tag("keygen", list(...)),
label = function(...) tag("label", list(...)),
legend = function(...) tag("legend", list(...)),
li = function(...) tag("li", list(...)),
link = function(...) tag("link", list(...)),
mark = function(...) tag("mark", list(...)),
map = function(...) tag("map", list(...)),
menu = function(...) tag("menu", list(...)),
meta = function(...) tag("meta", list(...)),
meter = function(...) tag("meter", list(...)),
nav = function(...) tag("nav", list(...)),
noscript = function(...) tag("noscript", list(...)),
object = function(...) tag("object", list(...)),
ol = function(...) tag("ol", list(...)),
optgroup = function(...) tag("optgroup", list(...)),
option = function(...) tag("option", list(...)),
output = function(...) tag("output", list(...)),
p = function(...) tag("p", list(...)),
param = function(...) tag("param", list(...)),
pre = function(...) tag("pre", list(...)),
progress = function(...) tag("progress", list(...)),
q = function(...) tag("q", list(...)),
ruby = function(...) tag("ruby", list(...)),
rp = function(...) tag("rp", list(...)),
rt = function(...) tag("rt", list(...)),
s = function(...) tag("s", list(...)),
samp = function(...) tag("samp", list(...)),
script = function(...) tag("script", list(...)),
section = function(...) tag("section", list(...)),
select = function(...) tag("select", list(...)),
small = function(...) tag("small", list(...)),
source = function(...) tag("source", list(...)),
span = function(...) tag("span", list(...)),
strong = function(...) tag("strong", list(...)),
style = function(...) tag("style", list(...)),
sub = function(...) tag("sub", list(...)),
summary = function(...) tag("summary", list(...)),
sup = function(...) tag("sup", list(...)),
table = function(...) tag("table", list(...)),
tbody = function(...) tag("tbody", list(...)),
td = function(...) tag("td", list(...)),
textarea = function(...) tag("textarea", list(...)),
tfoot = function(...) tag("tfoot", list(...)),
th = function(...) tag("th", list(...)),
thead = function(...) tag("thead", list(...)),
time = function(...) tag("time", list(...)),
title = function(...) tag("title", list(...)),
tr = function(...) tag("tr", list(...)),
track = function(...) tag("track", list(...)),
u = function(...) tag("u", list(...)),
ul = function(...) tag("ul", list(...)),
var = function(...) tag("var", list(...)),
video = function(...) tag("video", list(...)),
wbr = function(...) tag("wbr", list(...))
)
#' Mark Characters as HTML
#'
#' Marks the given text as HTML, which means the \link{tag} functions will know
#' not to perform HTML escaping on it.
#'
#' @param text The text value to mark with HTML
#' @param ... Any additional values to be converted to character and
#' concatenated together
#' @return The same value, but marked as HTML.
#'
#' @examples
#' el <- div(HTML("I like <u>turtles</u>"))
#' cat(as.character(el))
#'
#' @export
HTML <- function(text, ...) {
htmlText <- c(text, as.character(list(...)))
htmlText <- paste(htmlText, collapse=" ")
attr(htmlText, "html") <- TRUE
class(htmlText) <- c("html", "character")
htmlText
}
#' Evaluate an expression using the \code{tags}
#'
#' This function makes it simpler to write HTML-generating code. Instead of
#' needing to specify \code{tags} each time a tag function is used, as in
#' \code{tags$div()} and \code{tags$p()}, code inside \code{withTags} is
#' evaluated with \code{tags} searched first, so you can simply use
#' \code{div()} and \code{p()}.
#'
#' If your code uses an object which happens to have the same name as an
#' HTML tag function, such as \code{source()} or \code{summary()}, it will call
#' the tag function. To call the intended (non-tags function), specify the
#' namespace, as in \code{base::source()} or \code{base::summary()}.
#'
#' @param code A set of tags.
#'
#' @examples
#' # Using tags$ each time
#' tags$div(class = "myclass",
#' tags$h3("header"),
#' tags$p("text")
#' )
#'
#' # Equivalent to above, but using withTags
#' withTags(
#' div(class = "myclass",
#' h3("header"),
#' p("text")
#' )
#' )
#'
#'
#' @export
withTags <- function(code) {
eval(substitute(code), envir = as.list(tags), enclos = parent.frame())
}
# Given a list of tags, lists, and other items, return a flat list, where the
# items from the inner, nested lists are pulled to the top level, recursively.
flattenTags <- function(x) {
if (isTag(x)) {
# For tags, wrap them into a list (which will be unwrapped by caller)
list(x)
} else if (is.list(x)) {
if (length(x) == 0) {
# Empty lists are simply returned
x
} else {
# For items that are lists (but not tags), recurse
unlist(lapply(x, flattenTags), recursive = FALSE)
}
} else if (is.character(x)){
# This will preserve attributes if x is a character with attribute,
# like what HTML() produces
list(x)
} else if (is.function(x) && inherits(x, "shiny.render.function")) {
list(useRenderFunction(x))
} else {
# For other items, coerce to character and wrap them into a list (which
# will be unwrapped by caller). Note that this will strip attributes.
list(as.character(x))
}
}

View File

@@ -77,11 +77,22 @@ withPrivateSeed <- function(expr) {
.globals$ownSeed, unset=is.null(.globals$ownSeed), {
tryCatch({
expr
}, finally = {.globals$ownSeed <- .Random.seed})
}, finally = {
.globals$ownSeed <- getExists('.Random.seed', 'numeric', globalenv())
})
}
)
}
# a homemade version of set.seed(NULL) for backward compatibility with R 2.15.x
reinitializeSeed <- if (getRversion() >= '3.0.0') {
function() set.seed(NULL)
} else function() {
if (exists('.Random.seed', globalenv()))
rm(list = '.Random.seed', pos = globalenv())
stats::runif(1) # generate any random numbers so R can reinitialize the seed
}
# Version of runif that runs with private seed
p_runif <- function(...) {
withPrivateSeed(runif(...))
@@ -897,3 +908,23 @@ stopWithCondition <- function(class, message) {
)
stop(cond)
}
#' Collect information about the Shiny Server environment
#'
#' This function returns the information about the current Shiny Server, such as
#' its version, and whether it is the open source edition or professional
#' edition. If the app is not served through the Shiny Server, this function
#' just returns \code{list(shinyServer = FALSE)}.
#' @export
#' @return A list of the Shiny Server information.
serverInfo <- function() {
.globals$serverInfo
}
.globals$serverInfo <- list(shinyServer = FALSE)
setServerInfo <- function(...) {
infoOld <- serverInfo()
infoNew <- list(...)
infoOld[names(infoNew)] <- infoNew
.globals$serverInfo <- infoOld
}

View File

@@ -1,6 +1,6 @@
# Shiny
[![Build Status](https://travis-ci.org/rstudio/shiny.png)](https://travis-ci.org/rstudio/shiny)
[![Build Status](https://travis-ci.org/rstudio/shiny.svg?branch=master)](https://travis-ci.org/rstudio/shiny)
Shiny is a new package from RStudio that makes it incredibly easy to build interactive web applications with R.

View File

@@ -159,8 +159,6 @@ sd_section("Embedding",
"Functions that are intended for third-party packages that embed Shiny applications.",
c(
"shinyApp",
"maskReactiveContext",
"knitr_methods",
"getProvidedHtmlDependencies"
"maskReactiveContext"
)
)

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")
known_unindexed <- c("shiny-package", "knitr_methods")
indexed_topics <- local({
result <- character(0)

View File

@@ -1,432 +0,0 @@
context("tags")
test_that("Basic tag writing works", {
expect_equal(as.character(tagList("hi")), HTML("hi"))
expect_equal(
as.character(tagList("one", "two", tagList("three"))),
HTML("one\ntwo\nthree"))
expect_equal(
as.character(tags$b("one")),
HTML("<b>one</b>"))
expect_equal(
as.character(tags$b("one", "two")),
HTML("<b>\n one\n two\n</b>"))
expect_equal(
as.character(tagList(list("one"))),
HTML("one"))
expect_equal(
as.character(tagList(list(tagList("one")))),
HTML("one"))
expect_equal(
as.character(tagList(tags$br(), "one")),
HTML("<br/>\none"))
})
test_that("withTags works", {
output_tags <- tags$div(class = "myclass",
tags$h3("header"),
tags$p("text here")
)
output_withhtml <- withTags(
div(class = "myclass",
h3("header"),
p("text here")
)
)
expect_identical(output_tags, output_withhtml)
# Check that current environment is searched
x <- 100
expect_identical(tags$p(x), withTags(p(x)))
# Just to make sure, run it in a function, which has its own environment
foo <- function() {
y <- 100
withTags(p(y))
}
expect_identical(tags$p(100), foo())
})
test_that("HTML escaping in tags", {
# Regular text is escaped
expect_equivalent(format(div("<a&b>")), "<div>&lt;a&amp;b&gt;</div>")
# Text in HTML() isn't escaped
expect_equivalent(format(div(HTML("<a&b>"))), "<div><a&b></div>")
# Text in a property is escaped
expect_equivalent(format(div(class = "<a&b>", "text")),
'<div class="&lt;a&amp;b&gt;">text</div>')
# HTML() has no effect in a property like 'class'
expect_equivalent(format(div(class = HTML("<a&b>"), "text")),
'<div class="&lt;a&amp;b&gt;">text</div>')
})
test_that("Adding child tags", {
tag_list <- list(tags$p("tag1"), tags$b("tag2"), tags$i("tag3"))
# Creating nested tags by calling the tag$div function and passing a list
t1 <- tags$div(class="foo", tag_list)
expect_equal(length(t1$children), 1)
expect_equal(length(t1$children[[1]]), 3)
expect_equal(t1$children[[1]][[1]]$name, "p")
expect_equal(t1$children[[1]][[1]]$children[[1]], "tag1")
expect_equal(t1$children[[1]][[2]]$name, "b")
expect_equal(t1$children[[1]][[2]]$children[[1]], "tag2")
expect_equal(t1$children[[1]][[3]]$name, "i")
expect_equal(t1$children[[1]][[3]]$children[[1]], "tag3")
# div tag used as starting point for tests below
div_tag <- tags$div(class="foo")
# Appending each child
t2 <- tagAppendChild(div_tag, tag_list[[1]])
t2 <- tagAppendChild(t2, tag_list[[2]])
t2 <- tagAppendChild(t2, tag_list[[3]])
t2a <- do.call(tags$div, c(tag_list, class="foo"))
expect_identical(t2a, t2)
# tagSetChildren, using list argument
t2 <- tagSetChildren(div_tag, list = tag_list)
expect_identical(t2a, t2)
# tagSetChildren, using ... arguments
t2 <- tagSetChildren(div_tag, tag_list[[1]], tag_list[[2]], tag_list[[3]])
expect_identical(t2a, t2)
# tagSetChildren, using ... and list arguments
t2 <- tagSetChildren(div_tag, tag_list[[1]], list = tag_list[2:3])
expect_identical(t2a, t2)
# tagSetChildren overwrites existing children
t2 <- tagAppendChild(div_tag, p("should replace this tag"))
t2 <- tagSetChildren(div_tag, list = tag_list)
expect_identical(t2a, t2)
# tagAppendChildren, using list argument
t2 <- tagAppendChild(div_tag, tag_list[[1]])
t2 <- tagAppendChildren(t2, list = tag_list[2:3])
expect_identical(t2a, t2)
# tagAppendChildren, using ... arguments
t2 <- tagAppendChild(div_tag, tag_list[[1]])
t2 <- tagAppendChildren(t2, tag_list[[2]], tag_list[[3]])
expect_identical(t2a, t2)
# tagAppendChildren, using ... and list arguments
t2 <- tagAppendChild(div_tag, tag_list[[1]])
t2 <- tagAppendChildren(t2, tag_list[[2]], list = list(tag_list[[3]]))
expect_identical(t2a, t2)
# tagAppendChildren can start with no children
t2 <- tagAppendChildren(div_tag, list = tag_list)
expect_identical(t2a, t2)
# tagSetChildren preserves attributes
x <- tagSetChildren(div(), HTML("text"))
expect_identical(attr(x$children[[1]], "html"), TRUE)
# tagAppendChildren preserves attributes
x <- tagAppendChildren(div(), HTML("text"))
expect_identical(attr(x$children[[1]], "html"), TRUE)
})
test_that("Creating simple tags", {
# Empty tag
expect_identical(
div(),
structure(
list(name = "div", attribs = list(), children = list()),
.Names = c("name", "attribs", "children"),
class = "shiny.tag"
)
)
# Tag with text
expect_identical(
div("text"),
structure(
list(name = "div", attribs = list(), children = list("text")),
.Names = c("name", "attribs", "children"),
class = "shiny.tag"
)
)
# NULL attributes are dropped
expect_identical(
div(a = NULL, b = "value"),
div(b = "value")
)
# NULL children are dropped
expect_identical(
renderTags(div("foo", NULL, list(NULL, list(NULL, "bar"))))$html,
renderTags(div("foo", "bar"))$html
)
# Numbers are coerced to strings
expect_identical(
renderTags(div(1234))$html,
renderTags(div("1234"))$html
)
})
test_that("Creating nested tags", {
# Simple version
# Note that the $children list should not have a names attribute
expect_identical(
div(class="foo", list("a", "b")),
structure(
list(name = "div",
attribs = structure(list(class = "foo"), .Names = "class"),
children = list(list("a", "b"))),
.Names = c("name", "attribs", "children"),
class = "shiny.tag"
)
)
# More complex version
t1 <- withTags(
div(class = "foo",
p("child tag"),
list(
p("in-list child tag 1"),
"in-list character string",
p(),
p("in-list child tag 2")
),
"character string",
1234
)
)
# t1 should be identical to this data structure.
# The nested list should be flattened, and non-tag, non-strings should be
# converted to strings
t1_full <- structure(
list(
name = "div",
attribs = list(class = "foo"),
children = list(
structure(list(name = "p",
attribs = list(),
children = list("child tag")),
class = "shiny.tag"
),
structure(list(name = "p",
attribs = list(),
children = list("in-list child tag 1")),
class = "shiny.tag"
),
"in-list character string",
structure(list(name = "p",
attribs = list(),
children = list()),
class = "shiny.tag"
),
structure(list(name = "p",
attribs = list(),
children = list("in-list child tag 2")),
class = "shiny.tag"
),
"character string",
"1234"
)
),
class = "shiny.tag"
)
expect_identical(renderTags(t1)$html, renderTags(t1_full)$html)
})
test_that("Attributes are preserved", {
# HTML() adds an attribute to the data structure (note that this is
# different from the 'attribs' field in the list)
x <- HTML("<tag>&&</tag>")
expect_identical(attr(x, "html"), TRUE)
expect_equivalent(format(x), "<tag>&&</tag>")
# Make sure attributes are preserved when wrapped in other tags
x <- div(HTML("<tag>&&</tag>"))
expect_equivalent(x$children[[1]], HTML("<tag>&&</tag>"))
expect_identical(attr(x$children[[1]], "html"), TRUE)
expect_equivalent(format(x), "<div><tag>&&</tag></div>")
# Deeper nesting
x <- div(p(HTML("<tag>&&</tag>")))
expect_equivalent(x$children[[1]]$children[[1]], HTML("<tag>&&</tag>"))
expect_identical(attr(x$children[[1]]$children[[1]], "html"), TRUE)
expect_equivalent(format(x), "<div>\n <p><tag>&&</tag></p>\n</div>")
})
test_that("Flattening a list of tags", {
# Flatten a nested list
nested <- list(
"a1",
list(
"b1",
list("c1", "c2"),
list(),
"b2",
list("d1", "d2")
),
"a2"
)
flat <- list("a1", "b1", "c1", "c2", "b2", "d1", "d2", "a2")
expect_identical(flattenTags(nested), flat)
# no-op for flat lists
expect_identical(flattenTags(list(a="1", "b")), list(a="1", "b"))
# numbers are coerced to character
expect_identical(flattenTags(list(a=1, "b")), list(a="1", "b"))
# empty list results in empty list
expect_identical(flattenTags(list()), list())
# preserve attributes
nested <- list("txt1", list(structure("txt2", prop="prop2")))
flat <- list("txt1",
structure("txt2", prop="prop2"))
expect_identical(flattenTags(nested), flat)
})
test_that("Head and singleton behavior", {
result <- renderTags(tagList(
tags$head(singleton("hello"))
))
expect_identical(result$html, HTML(""))
expect_identical(result$head, HTML(" hello"))
expect_identical(result$singletons, "60eed8231e688bcba7c275c58dd2e3b4dacb61f0")
# Ensure that "hello" actually behaves like a singleton
result2 <- renderTags(tagList(
tags$head(singleton("hello"))
), singletons = result$singletons)
expect_identical(result$singletons, result2$singletons)
expect_identical(result2$head, HTML(""))
expect_identical(result2$html, HTML(""))
result3 <- renderTags(tagList(
tags$head(singleton("hello"), singleton("hello"))
))
expect_identical(result$singletons, result3$singletons)
expect_identical(result3$head, HTML(" hello"))
# Ensure that singleton can be applied to lists, not just tags
result4 <- renderTags(list(singleton(list("hello")), singleton(list("hello"))))
expect_identical(result4$singletons, "d7319e3f14167c4c056dd7aa0b274c83fe2291f6")
expect_identical(result4$html, renderTags(HTML("hello"))$html)
})
test_that("Factors are treated as characters, not numbers", {
myfactors <- factor(LETTERS[1:3])
expect_identical(
as.character(tags$option(value=myfactors[[1]], myfactors[[1]])),
HTML('<option value="A">A</option>')
)
expect_identical(
as.character(tags$option(value=myfactors[[1]], value='B', value=3, myfactors[[1]])),
HTML('<option value="A B 3">A</option>')
)
})
test_that("Unusual list contents are rendered correctly", {
expect_identical(renderTags(list(NULL)), renderTags(HTML("")))
expect_identical(renderTags(list(100)), renderTags(HTML("100")))
expect_identical(renderTags(list(list(100))), renderTags(HTML("100")))
expect_identical(renderTags(list(list())), renderTags(HTML("")))
expect_identical(renderTags(NULL), renderTags(HTML("")))
})
test_that("Low-level singleton manipulation methods", {
# Default arguments drop singleton duplicates and strips the
# singletons it keeps of the singleton bit
result1 <- takeSingletons(tags$div(
singleton(tags$head(tags$script("foo"))),
singleton(tags$head(tags$script("foo")))
))
expect_identical(result1$ui$children[[2]], NULL)
expect_false(is(result1$ui$children[[1]], "shiny.singleton"))
# desingleton=FALSE means drop duplicates but don't strip the
# singleton bit
result2 <- takeSingletons(tags$div(
singleton(tags$head(tags$script("foo"))),
singleton(tags$head(tags$script("foo")))
), desingleton=FALSE)
expect_identical(result2$ui$children[[2]], NULL)
expect_is(result2$ui$children[[1]], "shiny.singleton")
result3 <- surroundSingletons(tags$div(
singleton(tags$script("foo")),
singleton(tags$script("foo"))
))
expect_identical(
renderTags(result3)$html,
HTML("<div>
<!--SHINY.SINGLETON[58b302d493b50acb75e4a5606687cadccdf902d8]-->
<script>foo</script>
<!--/SHINY.SINGLETON[58b302d493b50acb75e4a5606687cadccdf902d8]-->
<!--SHINY.SINGLETON[58b302d493b50acb75e4a5606687cadccdf902d8]-->
<script>foo</script>
<!--/SHINY.SINGLETON[58b302d493b50acb75e4a5606687cadccdf902d8]-->
</div>")
)
})
test_that("Indenting can be controlled/suppressed", {
expect_identical(
renderTags(tags$div("a", "b"))$html,
HTML("<div>\n a\n b\n</div>")
)
expect_identical(
format(tags$div("a", "b")),
"<div>\n a\n b\n</div>"
)
expect_identical(
renderTags(tags$div("a", "b"), indent = 2)$html,
HTML(" <div>\n a\n b\n </div>")
)
expect_identical(
format(tags$div("a", "b"), indent = 2),
" <div>\n a\n b\n </div>"
)
expect_identical(
renderTags(tags$div("a", "b"), indent = FALSE)$html,
HTML("<div>\na\nb\n</div>")
)
expect_identical(
format(tags$div("a", "b"), indent = FALSE),
"<div>\na\nb\n</div>"
)
expect_identical(
renderTags(tagList(tags$div("a", "b")), indent = FALSE)$html,
HTML("<div>\na\nb\n</div>")
)
expect_identical(
format(tagList(tags$div("a", "b")), indent = FALSE),
"<div>\na\nb\n</div>"
)
})

View File

@@ -21,6 +21,10 @@ test_that("Setting process-wide seed doesn't affect private randomness", {
test_that("Resetting private seed doesn't result in dupes", {
.globals$ownSeed <- NULL
id3 <- createUniqueId(4)
# Make sure we let enough time pass that reinitializing the seed is
# going to result in a different value. This is especially required
# on Windows.
Sys.sleep(1)
set.seed(0)
.globals$ownSeed <- NULL
id4 <- createUniqueId(4)

View File

@@ -1285,7 +1285,7 @@
registerDependency(dep.name, dep.version);
var path = dep.path;
var href = dep.src.href;
var $head = $("head").first();
@@ -1299,14 +1299,14 @@
if (dep.stylesheet) {
var stylesheets = $.map(asArray(dep.stylesheet), function(stylesheet) {
return $("<link rel='stylesheet' type='text/css'>")
.attr("href", path + "/" + stylesheet);
.attr("href", href + "/" + stylesheet);
});
$head.append(stylesheets);
}
if (dep.script) {
var scripts = $.map(asArray(dep.script), function(scriptName) {
return $("<script>").attr("src", path + "/" + scriptName);
return $("<script>").attr("src", href + "/" + scriptName);
});
$head.append(scripts);
}

View File

@@ -1,4 +1,3 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
\name{HTML}
\alias{HTML}
\title{Mark Characters as HTML}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{absolutePanel}
\alias{absolutePanel}
\alias{fixedPanel}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{actionButton}
\alias{actionButton}
\alias{actionLink}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{addResourcePath}
\alias{addResourcePath}
\title{Resource Publishing}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{bootstrapPage}
\alias{basicPage}
\alias{bootstrapPage}

View File

@@ -1,5 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
\name{p}
\name{builder}
\alias{a}
\alias{br}
\alias{builder}
@@ -21,6 +20,8 @@
\alias{tags}
\title{HTML Builder Functions}
\usage{
tags
p(...)
h1(...)
@@ -54,8 +55,6 @@ strong(...)
em(...)
hr(...)
tags
}
\arguments{
\item{...}{Attributes and children of the element. Named arguments become

View File

@@ -1,9 +1,9 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{checkboxGroupInput}
\alias{checkboxGroupInput}
\title{Checkbox Group Input Control}
\usage{
checkboxGroupInput(inputId, label, choices, selected = NULL)
checkboxGroupInput(inputId, label, choices, selected = NULL, inline = FALSE)
}
\arguments{
\item{inputId}{Input variable to assign the control's value to.}
@@ -14,6 +14,8 @@ checkboxGroupInput(inputId, label, choices, selected = NULL)
are named then that name rather than the value is displayed to the user.}
\item{selected}{The values that should be initially selected, if any.}
\item{inline}{If \code{TRUE}, render the choices inline (i.e. horizontally)}
}
\value{
A list of HTML elements that can be added to a UI definition.

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{checkboxInput}
\alias{checkboxInput}
\title{Checkbox Input Control}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{column}
\alias{column}
\title{Create a column within a UI definition}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{conditionalPanel}
\alias{conditionalPanel}
\title{Conditional Panel}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{dateInput}
\alias{dateInput}
\title{Create date input}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{dateRangeInput}
\alias{dateRangeInput}
\title{Create date range input}

View File

@@ -1,5 +1,5 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
\name{getDefaultReactiveDomain}
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{domains}
\alias{domains}
\alias{getDefaultReactiveDomain}
\alias{onReactiveDomainEnded}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{downloadButton}
\alias{downloadButton}
\alias{downloadLink}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{downloadHandler}
\alias{downloadHandler}
\title{File Downloads}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{exprToFunction}
\alias{exprToFunction}
\title{Convert an expression to a function}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{fileInput}
\alias{fileInput}
\title{File Upload Control}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{fixedPage}
\alias{fixedPage}
\alias{fixedRow}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{flowLayout}
\alias{flowLayout}
\title{Flow layout}
@@ -27,7 +27,5 @@ flowLayout(
}
\seealso{
\code{\link{verticalLayout}}
#'
}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{fluidPage}
\alias{fluidPage}
\alias{fluidRow}

View File

@@ -1,15 +0,0 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
\name{getProvidedHtmlDependencies}
\alias{getProvidedHtmlDependencies}
\title{Return HTML dependencies provided by Shiny}
\usage{
getProvidedHtmlDependencies()
}
\value{
A list of objects of type \code{html_dependency}, one per dependency
}
\description{
By default, Shiny supplies some framework scripts when it renders a page.
\code{getProvidedHtmlDependencies} returns a list of those provided objects.
}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{headerPanel}
\alias{headerPanel}
\title{Create a header panel}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{helpText}
\alias{helpText}
\title{Create a help text element}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{htmlOutput}
\alias{htmlOutput}
\alias{uiOutput}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{icon}
\alias{icon}
\title{Create an icon}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{imageOutput}
\alias{imageOutput}
\title{Create a image output element}

View File

@@ -1,4 +1,3 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
\name{include}
\alias{include}
\alias{includeCSS}
@@ -26,7 +25,7 @@ includeScript(path, ...)
\item{...}{Any additional attributes to be applied to the generated tag.}
}
\description{
Include HTML, text, or rendered Markdown into a \link[=shinyUI]{Shiny UI}.
Load HTML, text, or rendered Markdown from a file and turn into HTML.
}
\details{
These functions provide a convenient way to include an extensive amount of

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{inputPanel}
\alias{inputPanel}
\title{Input panel}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{installExprFunction}
\alias{installExprFunction}
\title{Install an expression as a function}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{invalidateLater}
\alias{invalidateLater}
\title{Scheduled Invalidation}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{is.reactivevalues}
\alias{is.reactivevalues}
\title{Checks whether an object is a reactivevalues object}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{isolate}
\alias{isolate}
\title{Create a non-reactive scope for an expression}

View File

@@ -1,18 +1,12 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{knitr_methods}
\alias{knit_print.shiny.appobj}
\alias{knit_print.shiny.render.function}
\alias{knit_print.shiny.tag}
\alias{knit_print.shiny.tag.list}
\alias{knitr_methods}
\title{Knitr S3 methods}
\usage{
knit_print.shiny.appobj(x, ...)
knit_print.shiny.tag(x, ...)
knit_print.shiny.tag.list(x, ...)
knit_print.shiny.render.function(x, ...)
}
\arguments{

View File

@@ -0,0 +1,22 @@
\name{knit_print.html}
\alias{knit_print.html}
\alias{knit_print.shiny.tag}
\alias{knit_print.shiny.tag.list}
\title{Knitr S3 methods}
\usage{
knit_print.shiny.tag(x, ...)
knit_print.html(x, ...)
knit_print.shiny.tag.list(x, ...)
}
\arguments{
\item{x}{Object to knit_print}
\item{...}{Additional knit_print arguments}
}
\description{
These S3 methods are necessary to allow HTML tags to print themselves in
knitr/rmarkdown documents.
}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{mainPanel}
\alias{mainPanel}
\title{Create a main panel}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{makeReactiveBinding}
\alias{makeReactiveBinding}
\title{Make a reactive variable}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{markRenderFunction}
\alias{markRenderFunction}
\title{Mark a function as a render function}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{maskReactiveContext}
\alias{maskReactiveContext}
\title{Evaluate an expression without a reactive context}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{navbarPage}
\alias{navbarMenu}
\alias{navbarPage}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{navlistPanel}
\alias{navlistPanel}
\title{Create a navigation list panel}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{numericInput}
\alias{numericInput}
\title{Create a numeric input control}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{observe}
\alias{observe}
\title{Create a reactive observer}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{outputOptions}
\alias{outputOptions}
\title{Set options for an output object.}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{pageWithSidebar}
\alias{pageWithSidebar}
\title{Create a page with a sidebar}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{parseQueryString}
\alias{parseQueryString}
\title{Parse a GET query string from a URL}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{plotOutput}
\alias{plotOutput}
\title{Create an plot output element}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{plotPNG}
\alias{plotPNG}
\title{Run a plotting function and save the output as a PNG}

View File

@@ -1,9 +1,9 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{radioButtons}
\alias{radioButtons}
\title{Create radio buttons}
\usage{
radioButtons(inputId, label, choices, selected = NULL)
radioButtons(inputId, label, choices, selected = NULL, inline = FALSE)
}
\arguments{
\item{inputId}{Input variable to assign the control's value to}
@@ -15,6 +15,8 @@ named then that name rather than the value is displayed to the user)}
\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)}
}
\value{
A set of radio buttons that can be added to a UI definition.

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{reactive}
\alias{is.reactive}
\alias{reactive}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{reactiveFileReader}
\alias{reactiveFileReader}
\title{Reactive file reader}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{reactivePlot}
\alias{reactivePlot}
\title{Plot output (deprecated)}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{reactivePoll}
\alias{reactivePoll}
\title{Reactive polling}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{reactivePrint}
\alias{reactivePrint}
\title{Print output (deprecated)}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{reactiveTable}
\alias{reactiveTable}
\title{Table output (deprecated)}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{reactiveText}
\alias{reactiveText}
\title{Text output (deprecated)}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{reactiveTimer}
\alias{reactiveTimer}
\title{Timer}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{reactiveUI}
\alias{reactiveUI}
\title{UI output (deprecated)}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{reactiveValues}
\alias{reactiveValues}
\title{Create an object for storing reactive values}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{reactiveValuesToList}
\alias{reactiveValuesToList}
\title{Convert a reactivevalues object to a list}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{registerInputHandler}
\alias{registerInputHandler}
\title{Register an Input Handler}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{removeInputHandler}
\alias{removeInputHandler}
\title{Deregister an Input Handler}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{renderDataTable}
\alias{renderDataTable}
\title{Table output with the JavaScript library DataTables}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{renderImage}
\alias{renderImage}
\title{Image file output}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{renderPlot}
\alias{renderPlot}
\title{Plot Output}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{renderPrint}
\alias{renderPrint}
\title{Printable Output}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{renderTable}
\alias{renderTable}
\title{Table Output}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{renderText}
\alias{renderText}
\title{Text Output}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{renderUI}
\alias{renderUI}
\title{UI Output}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{repeatable}
\alias{repeatable}
\title{Make a random number generator repeatable}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{runApp}
\alias{runApp}
\title{Run Shiny Application}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{runExample}
\alias{runExample}
\title{Run Shiny Example Applications}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% 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}

View File

@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{runGitHub}
\alias{runGitHub}
\title{Run a Shiny application from a GitHub repository}

Some files were not shown because too many files have changed in this diff Show More