Compare commits

..

41 Commits

Author SHA1 Message Date
Joe Cheng
e9fc873c8d 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-29 14:00:48 -07:00
Joe Cheng
0153349979 Make S3 method consistent with base 2014-05-28 13:28:02 -07:00
Joe Cheng
d227842414 Update htmltools version 2014-05-28 13:20:54 -07:00
Joe Cheng
b6a2122a41 Merge remote-tracking branch 'origin/master' into htmltools-refactor
Conflicts:
	R/shiny.R
	man/session.Rd
2014-05-28 13:18:49 -07:00
Joe Cheng
a0df8f3490 Merge pull request #491 from rstudio/bugfix/validation-silent
Suppress validation errors from printing at console
2014-05-28 13:14:02 -07:00
Winston Chang
6c14789362 Merge pull request #492 from rstudio/bugfix/0.10misc
Miscellaneous bug fixes
2014-05-23 14:13:29 -05:00
Winston Chang
880a12b914 Merge pull request #489 from yihui/bugfix/428
Fixes #428
2014-05-23 14:09:43 -05:00
Joe Cheng
93d69400e6 Merge pull request #486 from yihui/feature/widget-width
Width of selectize and sliders
2014-05-22 15:43:34 -07:00
Joe Cheng
d4829e49ea Doc tweak to validation 2014-05-21 19:57:18 -07:00
Joe Cheng
1c56be3a6b Suppress validation errors from printing at console 2014-05-21 19:51:24 -07:00
Joe Cheng
07a0dfddc7 Validation error causes real errors to look like validation errors
The CSS class for validation errors was not being properly removed between different kinds of errors
2014-05-21 19:32:44 -07:00
Joe Cheng
b86f9086ef Avoid black background when renderPlot doesn't actually plot 2014-05-21 19:28:51 -07:00
Joe Cheng
343ca12c6f Don't print NULL to the console during renderPrint 2014-05-21 19:28:28 -07:00
Joe Cheng
af3c4f84b6 Merge pull request #488 from yihui/bugfix/220
fix #220: the first entry in zip is not necessarily a directory
2014-05-20 00:32:11 -07:00
Yihui Xie
3679e8795f fix #220: the first entry is not necessarily a directory
in that case, we use dirname() on the first entry
2014-05-20 01:43:48 -05:00
Yihui Xie
39b4805a76 make sure the selected argument never contains names; fixes #428 2014-05-20 01:31:14 -05:00
Yihui Xie
3bdcdf96d4 upgrade selectize.js to v0.9.1 to fix the third issue in #428 2014-05-20 01:30:37 -05:00
Yihui Xie
b54e5d33bc roxygenize 2014-05-19 11:25:40 -05:00
Yihui Xie
85e020a513 examples of the 'width' argument 2014-05-19 11:24:56 -05:00
Yihui Xie
5b6268f5bc add width to selectInput() as well 2014-05-19 11:23:52 -05:00
Yihui Xie
f8b38e4683 validateCssUnit(width) for selectize and slider 2014-05-17 01:32:01 -05:00
Yihui Xie
18e85c32b4 roxygenize 2014-05-17 01:28:27 -05:00
Yihui Xie
831fba9a53 add a 'width' option to selectizeInput() and sliderInput() to specify the width of these widgets 2014-05-17 01:28:27 -05:00
Joe Cheng
b1f233cd8c Merge remote-tracking branch 'origin/pr/485'
Conflicts:
	NEWS
2014-05-16 23:22:01 -07:00
Yihui Xie
3d0caba695 \emph cannot be used in \code{}: only \var and \link are allowed 2014-05-17 00:53:57 -05:00
Yihui Xie
79c92f1f8e fixes #429, which is yet yet another WAT of RJSONIO
perhaps we really should consider switching to jsonlite...
2014-05-17 00:43:13 -05:00
Joe Cheng
78f87d9003 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-16 15:39:08 -07:00
Yihui Xie
87f26e47bb a news item for the 'width' argument of renderPrint() 2014-05-16 14:19:55 -05:00
Yihui Xie
9d8d04ae28 add a 'width' argument so we can control the width of the text output 2014-05-16 14:17:50 -05:00
Yihui Xie
a42f046ff8 capture.output() has already considered withVisible(), and we do not need to redo it 2014-05-16 14:12:50 -05:00
Joe Cheng
0824726dbb Adapt to htmltools 0.2.1 API 2014-05-15 15:17:42 -07:00
Joe Cheng
f55155404a Remove obsolete entry from staticdocs index 2014-05-14 17:13:38 -07:00
Joe Cheng
b711bb553f Add S3 method for turning render function into tags 2014-05-14 17:12:15 -07:00
Joe Cheng
2a36179bdc Fix broken client-side HTML dependency rendering 2014-05-14 17:12:15 -07:00
Joe Cheng
e57221861f Extract HTML functionality to htmltools library 2014-05-14 17:12:15 -07:00
Joe Cheng
b00fbda1ae Make sure random bytes are formatted with 2 chars 2014-05-14 17:11:18 -07:00
Joe Cheng
357e81aeca Bump version 2014-05-14 09:14:19 -07:00
Joe Cheng
3189c748b5 Merge pull request #479 from rstudio/not-just-last-expressions
Allow shinyUI and shinyServer calls to not be the last expression in ui....
2014-05-14 09:06:28 -07:00
Joe Cheng
2700643cbf Merge pull request #480 from jcheng5/bugfix/renderplot-height-overlap
Fix #477: renderPlot in shinydoc with height > 400 overlaps subsequent c...
2014-05-14 09:06:15 -07:00
Joe Cheng
f5fa7d6d4b Fix #477: renderPlot in shinydoc with height > 400 overlaps subsequent content 2014-05-09 18:14:28 -07:00
Joe Cheng
77bff6e6c2 Allow shinyUI and shinyServer calls to not be the last expression in ui.R and server.R 2014-05-08 16:14:53 -07:00
140 changed files with 579 additions and 1956 deletions

View File

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

View File

@@ -1,7 +1,7 @@
Package: shiny
Type: Package
Title: Web Application Framework for R
Version: 0.9.1.9007
Version: 0.9.1.9008
Date: 2014-03-19
Author: RStudio, Inc.
Maintainer: Winston Chang <winston@rstudio.com>
@@ -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,14 @@ 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.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 +55,6 @@ export(flowLayout)
export(fluidPage)
export(fluidRow)
export(getDefaultReactiveDomain)
export(getProvidedHtmlDependencies)
export(h1)
export(h2)
export(h3)
@@ -86,11 +78,10 @@ export(installExprFunction)
export(invalidateLater)
export(is.reactive)
export(is.reactivevalues)
export(is.singleton)
export(isolate)
export(knit_print.shiny.appobj)
export(knit_print.shiny.render.function)
export(knit_print.shiny.tag)
export(knit_print.shiny.tag.list)
export(mainPanel)
export(makeReactiveBinding)
export(markRenderFunction)
@@ -124,7 +115,6 @@ export(reactiveValuesToList)
export(registerInputHandler)
export(removeInputHandler)
export(renderDataTable)
export(renderHTML)
export(renderImage)
export(renderPlot)
export(renderPrint)
@@ -189,6 +179,7 @@ export(withTags)
import(RJSONIO)
import(caTools)
import(digest)
import(htmltools)
import(httpuv)
import(methods)
import(xtable)

9
NEWS
View File

@@ -27,6 +27,15 @@ shiny 0.9.1.9XXX
* `sliderInput` and `selectizeInput`/`selectInput` now use a standard horizontal
size instead of filling up all available horizontal space.
* Fixed a bug of renderDataTable() when the data object only has 1 row and 1
column. (Thanks, ZJ Dai, #429)
* `renderPrint` gained a new argument 'width' to control the width of the text
output, e.g. renderPrint({mtcars}, width = 40).
* 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)
shiny 0.9.1
--------------------------------------------------------------------------------

72
R/app.R
View File

@@ -106,14 +106,18 @@ shinyAppDir <- function(appDir, options=list()) {
# ui.R as a webpage. The "cachedFuncWithFile" call makes sure that the closure
# we're creating here only gets executed when ui.R's contents change.
uiHandlerSource <- cachedFuncWithFile(appDir, "ui.R", case.sensitive = FALSE,
function() {
# Have to use file.path.ci every time in case the case of ui.R has
# changed. (Hmmm, overengineering a bit?)
uiR <- file.path.ci(appDir, "ui.R")
function(uiR) {
if (file.exists(uiR)) {
# If ui.R contains a call to shinyUI (which sets .globals$ui), use that.
# 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
if (!is.null(.globals$ui)) {
ui <- .globals$ui[[1]]
}
return(uiHttpHandler(ui))
} else {
return(function(req) NULL)
@@ -126,14 +130,29 @@ shinyAppDir <- function(appDir, options=list()) {
wwwDir <- file.path.ci(appDir, "www")
fallbackWWWDir <- system.file("www-dir", package = "shiny")
serverSource <- cachedSource(appDir, "server.R", case.sensitive = FALSE)
serverSource <- cachedFuncWithFile(appDir, "server.R", case.sensitive = FALSE,
function(serverR) {
# If server.R contains a call to shinyServer (which sets .globals$server),
# use that. If not, then take the last expression that's returned from
# server.R.
.globals$server <- NULL
on.exit(.globals$server <- NULL, add = TRUE)
result <- source(
serverR,
local = new.env(parent = globalenv()),
keep.source = TRUE
)$value
if (!is.null(.globals$server)) {
result <- .globals$server[[1]]
}
return(result)
}
)
# This function stands in for the server function, and reloads the
# real server function as necessary whenever server.R changes
serverFuncSource <- function() {
serverFunction <- serverSource(
local = new.env(parent = globalenv()),
keep.source = TRUE)$value
serverFunction <- serverSource()
if (is.null(serverFunction)) {
return(function(input, output) NULL)
} else if (is.function(serverFunction)) {
@@ -254,37 +273,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
@@ -294,11 +286,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

@@ -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)) {
@@ -603,6 +605,8 @@ checkboxGroupInput <- function(inputId, label, choices, selected = NULL) {
# Before shiny 0.9, `selected` refers to names/labels of `choices`; now it
# refers to values. Below is a function for backward compatibility.
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)
@@ -615,7 +619,7 @@ validateSelected <- function(selected, choices, inputId) {
i <- (selected %in% nms) & !(selected %in% choices)
if (any(i)) {
warnFun <- if (all(i)) {
# replace names with values; drop names, otherwise toJSON() keeps them too
# replace names with values
selected <- unname(choices[selected])
warning
} else stop # stop when it is ambiguous (some labels == values)
@@ -696,7 +700,7 @@ choicesWithNames <- function(choices) {
#' "Gears" = "gear"))
#' @export
selectInput <- function(inputId, label, choices, selected = NULL,
multiple = FALSE, selectize = TRUE) {
multiple = FALSE, selectize = TRUE, width = NULL) {
# resolve names
choices <- choicesWithNames(choices)
@@ -723,7 +727,7 @@ selectInput <- function(inputId, label, choices, selected = NULL,
# return label and select tag
res <- tagList(controlLabel(inputId, label), selectTag)
if (!selectize) return(res)
selectizeIt(inputId, res, NULL, nonempty = !multiple && !("" %in% choices))
selectizeIt(inputId, res, NULL, width, nonempty = !multiple && !("" %in% choices))
}
#' @rdname selectInput
@@ -732,6 +736,8 @@ selectInput <- function(inputId, label, choices, selected = NULL,
#' for possible options (character option values inside \code{\link{I}()} will
#' be treated as literal JavaScript code; see \code{\link{renderDataTable}()}
#' for details).
#' @param width The width of the input, e.g. \code{'400px'}, or \code{'100\%'};
#' see \code{\link{validateCssUnit}}.
#' @note The selectize input created from \code{selectizeInput()} allows
#' deletion of the selected option even in a single select input, which will
#' return an empty string as its value. This is the default behavior of
@@ -741,15 +747,16 @@ selectInput <- function(inputId, label, choices, selected = NULL,
#' \code{choices} argument. This is to keep compatibility with
#' \code{selectInput(..., selectize = FALSE)}.
#' @export
selectizeInput <- function(inputId, ..., options = NULL) {
selectizeIt(inputId, selectInput(inputId, ..., selectize = FALSE), options)
selectizeInput <- function(inputId, ..., options = NULL, width = NULL) {
selectizeIt(inputId, selectInput(inputId, ..., selectize = FALSE), options, width)
}
# given a select input and its id, selectize it
selectizeIt <- function(inputId, select, options, nonempty = FALSE) {
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]>'),
@@ -758,13 +765,14 @@ selectizeIt <- function(inputId, select, options, nonempty = FALSE) {
tags$script(src = 'shared/selectize/js/selectize.min.js')
))
)
attach_dependency(
attachDependencies(
tagList(
select,
tags$script(
type = 'application/json',
`data-for` = inputId, `data-nonempty` = if (nonempty) '',
`data-eval` = if (length(res$eval)) HTML(toJSON(res$eval)),
`data-width` = validateCssUnit(width),
if (length(res$options)) HTML(toJSON(res$options)) else '{}'
)
),
@@ -928,7 +936,7 @@ actionLink <- function(inputId, label, icon = NULL, ...) {
#' @param animate \code{TRUE} to show simple animation controls with default
#' settings; \code{FALSE} not to; or a custom settings list, such as those
#' created using \code{animationOptions}.
#'
#' @inheritParams selectizeInput
#' @family input elements
#' @seealso \code{\link{updateSliderInput}}
#'
@@ -947,7 +955,7 @@ actionLink <- function(inputId, label, icon = NULL, ...) {
#' @export
sliderInput <- function(inputId, label, min, max, value, step = NULL,
round=FALSE, format='#,##0.#####', locale='us',
ticks=TRUE, animate=FALSE) {
ticks=TRUE, animate=FALSE, width=NULL) {
if (identical(animate, TRUE))
animate <- animationOptions()
@@ -961,7 +969,8 @@ sliderInput <- function(inputId, label, min, max, value, step = NULL,
# build slider
sliderTag <- slider(inputId, min=min, max=max, value=value, step=step,
round=round, locale=locale, format=format, ticks=ticks, animate=animate)
round=round, locale=locale, format=format, ticks=ticks, animate=animate,
width=width)
if (is.null(label)) {
sliderTag
@@ -973,8 +982,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
@@ -1053,7 +1063,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",
@@ -1152,7 +1162,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",
@@ -1598,12 +1608,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"
)
@@ -1612,7 +1622,7 @@ dataTableDependency <- list(
#' @rdname tableOutput
#' @export
dataTableOutput <- function(outputId) {
attach_dependency(
attachDependencies(
div(id = outputId, class="shiny-datatable-output"),
dataTableDependency
)
@@ -1756,49 +1766,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

@@ -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,101 @@
#' @export
a <- htmltools::a
#' @export
br <- htmltools::br
# 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
))
}
#' @export
code <- htmltools::code
#' @export
div <- htmltools::div
# 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) {
#' @export
em <- htmltools::em
html <- c()
#' @export
h1 <- htmltools::h1
for (dep in dependencies) {
#' @export
h2 <- htmltools::h2
# copy library files if necessary
if (!is.null(lib_dir)) {
#' @export
h3 <- htmltools::h3
if (!file.exists(lib_dir))
dir.create(lib_dir)
#' @export
h4 <- htmltools::h4
target_dir <- file.path(lib_dir, basename(dep$path))
if (!file.exists(target_dir))
file.copy(from = dep$path, to = lib_dir, recursive = TRUE)
#' @export
h5 <- htmltools::h5
dep$path <- file.path(basename(lib_dir), basename(target_dir))
}
#' @export
h6 <- htmltools::h6
# add meta content
for (name in names(dep$meta)) {
html <- c(html, paste("<meta name=\"", name,
"\" content=\"", dep$meta[[name]], "\" />",
sep = ""))
}
#' @export
hr <- htmltools::hr
# add stylesheets
for (stylesheet in dep$stylesheet) {
stylesheet <- file.path(dep$path, stylesheet)
html <- c(html, paste("<link href=\"", stylesheet, "\" ",
"rel=\"stylesheet\" />",
sep = ""))
}
#' @export
HTML <- htmltools::HTML
# add scripts
for (script in dep$script) {
script <- file.path(dep$path, script)
html <- c(html,
paste("<script src=\"", script, "\"></script>", sep = ""))
}
#' @export
img <- htmltools::img
# add raw head content
html <- c(html, dep$head)
}
#' @export
includeCSS <- htmltools::includeCSS
html
}
#' @export
includeHTML <- htmltools::includeHTML
attach_dependency <- function(x, dependency) {
structure(x, html_dependency = dependency)
}
#' @export
includeMarkdown <- htmltools::includeMarkdown
#' @export
includeScript <- htmltools::includeScript
#' @export
includeText <- htmltools::includeText
#' @export
is.singleton <- htmltools::is.singleton
#' @export
p <- htmltools::p
#' @export
pre <- htmltools::pre
#' @export
singleton <- htmltools::singleton
#' @export
span <- htmltools::span
#' @export
strong <- htmltools::strong
#' @export
tag <- htmltools::tag
#' @export
tagAppendAttributes <- htmltools::tagAppendAttributes
#' @export
tagAppendChild <- htmltools::tagAppendChild
#' @export
tagAppendChildren <- htmltools::tagAppendChildren
#' @export
tagList <- htmltools::tagList
#' @export
tags <- htmltools::tags
#' @export
tagSetChildren <- htmltools::tagSetChildren
#' @export
validateCssUnit <- htmltools::validateCssUnit
#' @export
withTags <- htmltools::withTags

View File

@@ -42,6 +42,9 @@ 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()
dv <- dev.cur()
tryCatch(shinyCallingHandlers(func()), finally = dev.off(dv))

View File

@@ -373,7 +373,7 @@ Observable <- setRefClass(
on.exit(.running <<- wasRunning)
ctx$run(function() {
result <- withVisible(try(shinyCallingHandlers(.func()), silent=FALSE))
result <- withVisible(try(shinyCallingHandlers(.func()), silent=TRUE))
.visible <<- result$visible
.value <<- result$value
})

View File

@@ -137,6 +137,8 @@ runUrl <- function(url, filetype = NULL, subdir = NULL, port = NULL,
message("Downloading ", url)
filePath <- tempfile('shinyapp', fileext=fileext)
fileDir <- tempfile('shinyapp')
dir.create(fileDir, showWarnings = FALSE)
if (download(url, filePath, mode = "wb", quiet = TRUE) != 0)
stop("Failed to download URL ", url)
on.exit(unlink(filePath))
@@ -148,17 +150,18 @@ runUrl <- function(url, filetype = NULL, subdir = NULL, port = NULL,
# 2) If the internal untar implementation is used, it chokes on the 'g'
# type flag that github uses (to stash their commit hash info).
# By using our own forked/modified untar2 we sidestep both issues.
dirname <- untar2(filePath, list=TRUE)[1]
untar2(filePath, exdir = dirname(filePath))
first <- untar2(filePath, list=TRUE)[1]
untar2(filePath, exdir = fileDir)
} else if (fileext == ".zip") {
dirname <- as.character(unzip(filePath, list=TRUE)$Name[1])
unzip(filePath, exdir = dirname(filePath))
first <- as.character(unzip(filePath, list=TRUE)$Name)[1]
unzip(filePath, exdir = fileDir)
}
on.exit(unlink(fileDir, recursive = TRUE), add = TRUE)
appdir <- file.path(dirname(filePath), dirname)
on.exit(unlink(appdir, recursive = TRUE), add = TRUE)
appdir <- file.path(fileDir, first)
if (!file_test('-d', appdir)) appdir <- dirname(appdir)
appsubdir <- ifelse(is.null(subdir), appdir, file.path(appdir, subdir))
runApp(appsubdir, port=port, launch.browser=launch.browser)
if (!is.null(subdir)) appdir <- file.path(appdir, subdir)
runApp(appdir, port=port, launch.browser=launch.browser)
}

View File

@@ -240,6 +240,7 @@ resourcePathHandler <- function(req) {
#'
#' @export
shinyServer <- function(func) {
.globals$server <- list(func)
invisible(func)
}
@@ -462,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,12 +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(as.hexmode(sample(256, bytes, replace = TRUE)-1), collapse = "")
paste(
prefix,
paste(
format(as.hexmode(sample(256, bytes, replace = TRUE)-1), width=2),
collapse = ""),
suffix,
sep = ""
)
})
}
@@ -80,10 +87,10 @@ workerId <- local({
#' }
#' }
#' \code{clientData} also contains information about each output.
#' \code{output_\emph{outputId}_width} and \code{output_\emph{outputId}_height}
#' \code{output_\var{outputId}_width} and \code{output_\var{outputId}_height}
#' give the dimensions (using \code{offsetWidth} and \code{offsetHeight}) of
#' the DOM element that is bound to \code{\emph{outputId}}, and
#' \code{output_\emph{outputId}_hidden} is a logical that indicates whether
#' the DOM element that is bound to \code{\var{outputId}}, and
#' \code{output_\var{outputId}_hidden} is a logical that indicates whether
#' the element is hidden. These values may be \code{NULL} if the output is
#' not bound.
#' }
@@ -314,7 +321,25 @@ ShinySession <- setRefClass(
obs <- observe({
value <- try(shinyCallingHandlers(func()), silent=FALSE)
value <- try(
{
tryCatch(
shinyCallingHandlers(func()),
shiny.silent.error = function(cond) {
# Don't let shiny.silent.error go through the normal stop
# path of try, because we don't want it to print. But we
# do want to try to return the same looking result so that
# the code below can send the error to the browser.
structure(
NULL,
class = "try-error",
condition = cond
)
}
)
},
silent=FALSE
)
.invalidatedOutputErrors$remove(name)
.invalidatedOutputValues$remove(name)

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>',
@@ -246,7 +93,10 @@ renderPage <- function(ui, connection, showcase=0) {
#' @return The user interface definition, without modifications or side effects.
#'
#' @export
shinyUI <- function(ui) ui
shinyUI <- function(ui) {
.globals$ui <- list(ui)
ui
}
uiHttpHandler <- function(ui, path = "/") {
@@ -281,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,18 @@ 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))
}
#' @S3method 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}
@@ -84,7 +89,16 @@ renderPlot <- function(expr, width='auto', height='auto', res=72, ...,
else
heightWrapper <- NULL
return(markRenderFunction(plotOutput, function(shinysession, name, ...) {
# If renderPlot isn't going to adapt to the height of the div, then the
# 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)
return(markRenderFunction(outputFunc, function(shinysession, name, ...) {
if (!is.null(widthWrapper))
width <- widthWrapper()
if (!is.null(heightWrapper))
@@ -111,8 +125,11 @@ renderPlot <- function(expr, width='auto', height='auto', res=72, ...,
plotFunc <- function() {
# Actually perform the plotting
result <- withVisible(func())
if (result$visible)
print(result$value)
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')
@@ -344,14 +361,15 @@ renderTable <- function(expr, ..., env=parent.frame(), quoted=FALSE, func=NULL)
#' @param quoted Is \code{expr} a quoted expression (with \code{quote()})? This
#' @param func A function that may print output and/or return a printable R
#' object (deprecated; use \code{expr} instead).
#'
#' @param width The value for \code{\link{options}('width')}.
#' @seealso \code{\link{renderText}} for displaying the value returned from a
#' function, instead of the printed output.
#'
#' @example res/text-example.R
#'
#' @export
renderPrint <- function(expr, env=parent.frame(), quoted=FALSE, func=NULL) {
renderPrint <- function(expr, env = parent.frame(), quoted = FALSE, func = NULL,
width = getOption('width')) {
if (!is.null(func)) {
shinyDeprecated(msg="renderPrint: argument 'func' is deprecated. Please use 'expr' instead.")
} else {
@@ -359,11 +377,9 @@ renderPrint <- function(expr, env=parent.frame(), quoted=FALSE, func=NULL) {
}
markRenderFunction(verbatimTextOutput, function() {
return(paste(capture.output({
result <- withVisible(func())
if (result$visible)
print(result$value)
}), collapse="\n"))
op <- options(width = width)
on.exit(options(op), add = TRUE)
paste(capture.output(func()), collapse = "\n")
})
}
@@ -407,27 +423,6 @@ renderText <- function(expr, env=parent.frame(), quoted=FALSE, func=NULL) {
})
}
#' @export
renderHTML <- function(expr, env=parent.frame(), quoted=FALSE) {
installExprFunction(expr, "func", env, quoted)
markRenderFunction(htmlOutput, function() {
result <- func()
if (is.null(result) || length(result) == 0)
return(NULL)
output <- list(
html = result,
deps = attr(result, "dependencies")
)
return(output)
})
}
#' UI Output
#'
#' \bold{Experimental feature.} Makes a reactive version of a function that
@@ -469,7 +464,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

@@ -33,7 +33,7 @@ animationOptions <- function(interval=1000,
# (www/shared/slider contains js, css, and img dependencies)
slider <- function(inputId, min, max, value, step = NULL, ...,
round=FALSE, format='#,##0.#####', locale='us',
ticks=TRUE, animate=FALSE) {
ticks=TRUE, animate=FALSE, width=NULL) {
# validate inputId
inputId <- as.character(inputId)
if (!is.character(inputId))
@@ -99,20 +99,20 @@ 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",
'data-from'=min, 'data-to'=max, 'data-step'=step,
'data-skin'='plastic', 'data-round'=round, 'data-locale'=locale,
'data-format'=format, 'data-scale'=ticks,
'data-smooth'=FALSE
'data-smooth'=FALSE,
'data-width'=validateCssUnit(width)
),
dep
)

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

@@ -606,7 +606,11 @@ dataTablesJSON <- function(data, req) {
fdata <- data[i, , drop = FALSE] # filtered data
} else fdata <- data
fdata <- unname(as.matrix(fdata))
# WAT: toJSON(list(x = matrix(nrow = 0, ncol = 1))) => {"x": } (#299)
if (nrow(fdata) == 0) fdata <- list()
# WAT: toJSON(list(x = matrix(1:2))) => {x: [ [1], [2] ]}, however,
# toJSON(list(x = matrix(1))) => {x: [ 1 ]} (loss of dimension, #429)
if (all(dim(fdata) == 1)) fdata <- list(list(fdata[1, 1]))
res <- toJSON(list(
sEcho = as.integer(sEcho),
@@ -714,7 +718,7 @@ cachedFuncWithFile <- function(dir, file, func, case.sensitive = FALSE) {
now <- file.info(fname)$mtime
if (!identical(mtime, now)) {
value <<- func(...)
value <<- func(fname, ...)
mtime <<- now
}
value
@@ -725,11 +729,7 @@ cachedFuncWithFile <- function(dir, file, func, case.sensitive = FALSE) {
# 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 (case.sensitive)
file.path(dir, file)
else
file.path.ci(dir, file)
cachedFuncWithFile(dir, file, function(fname, ...) {
if (file.exists(fname))
return(source(fname, ...))
else
@@ -800,7 +800,8 @@ columnToRowData <- function(data) {
#' @param ... A list of tests. Each test should equal \code{NULL} for success,
#' \code{FALSE} for silent failure, or a string for failure with an error
#' message.
#' @param errorClass A CSS class to apply.
#' @param errorClass A CSS class to apply. The actual CSS string will have
#' \code{shiny-output-error-} prepended to this value.
#' @export
#' @examples
#' # in ui.R
@@ -892,7 +893,7 @@ isTruthy <- function(x) {
stopWithCondition <- function(class, message) {
cond <- structure(
list(message = message),
class = c(class, 'error', 'condition')
class = c(class, 'shiny.silent.error', 'error', 'condition')
)
stop(cond)
}

View File

@@ -1,10 +0,0 @@
library(shiny)
library(rmdexamples)
shinyServer(function(input, output) {
output$gage <- renderHTML({
justgage("Foo", 5, 1, 10)
})
})

View File

@@ -1,9 +0,0 @@
library(shiny)
shinyUI(fluidPage(
titlePanel("Hello Shiny!"),
htmlOutput("gage")
))

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

@@ -1,5 +1,5 @@
/**
* selectize.bootstrap2.css (v0.8.0) - Bootstrap 2 Theme
* selectize.bootstrap2.css (v0.9.1) - Bootstrap 2 Theme
* Copyright (c) 2013 Brian Reavis & contributors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
@@ -13,387 +13,337 @@
*
* @author Brian Reavis <brian@thirdroute.com>
*/
.selectize-control.plugin-drag_drop.multi > .selectize-input > div.ui-sortable-placeholder {
visibility: visible !important;
background: #f2f2f2 !important;
background: rgba(0, 0, 0, 0.06) !important;
border: 0 none !important;
visibility: visible !important;
-webkit-box-shadow: inset 0 0 12px 4px #ffffff;
box-shadow: inset 0 0 12px 4px #ffffff;
box-shadow: inset 0 0 12px 4px #ffffff;
}
.selectize-control.plugin-drag_drop .ui-sortable-placeholder::after {
content: '!';
visibility: hidden;
}
.selectize-control.plugin-drag_drop .ui-sortable-helper {
-webkit-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
}
.selectize-dropdown-header {
position: relative;
padding: 3px 10px;
background: #f8f8f8;
border-bottom: 1px solid #d0d0d0;
background: #f8f8f8;
-webkit-border-radius: 4px 4px 0 0;
-moz-border-radius: 4px 4px 0 0;
border-radius: 4px 4px 0 0;
-moz-border-radius: 4px 4px 0 0;
border-radius: 4px 4px 0 0;
}
.selectize-dropdown-header-close {
position: absolute;
top: 50%;
right: 10px;
margin-top: -12px;
font-size: 20px !important;
line-height: 20px;
top: 50%;
color: #333333;
opacity: 0.4;
margin-top: -12px;
line-height: 20px;
font-size: 20px !important;
}
.selectize-dropdown-header-close:hover {
color: #000000;
}
.selectize-dropdown.plugin-optgroup_columns .optgroup {
float: left;
border-top: 0 none;
border-right: 1px solid #f2f2f2;
border-top: 0 none;
float: left;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.selectize-dropdown.plugin-optgroup_columns .optgroup:last-child {
border-right: 0 none;
}
.selectize-dropdown.plugin-optgroup_columns .optgroup:before {
display: none;
}
.selectize-dropdown.plugin-optgroup_columns .optgroup-header {
border-top: 0 none;
}
.selectize-control.plugin-remove_button [data-value] {
position: relative;
padding-right: 24px !important;
}
.selectize-control.plugin-remove_button [data-value] .remove {
z-index: 1;
/* fixes ie bug (see #392) */
position: absolute;
top: 0;
right: 0;
bottom: 0;
display: inline-block;
width: 17px;
padding: 1px 0 0 0;
font-size: 12px;
font-weight: bold;
color: inherit;
text-align: center;
font-weight: bold;
font-size: 12px;
color: inherit;
text-decoration: none;
vertical-align: middle;
display: inline-block;
padding: 1px 0 0 0;
border-left: 1px solid #cccccc;
-webkit-border-radius: 0 2px 2px 0;
-moz-border-radius: 0 2px 2px 0;
border-radius: 0 2px 2px 0;
-moz-border-radius: 0 2px 2px 0;
border-radius: 0 2px 2px 0;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.selectize-control.plugin-remove_button [data-value] .remove:hover {
background: rgba(0, 0, 0, 0.05);
}
.selectize-control.plugin-remove_button [data-value].active .remove {
border-left-color: #0077b3;
}
.selectize-control.plugin-remove_button .disabled [data-value] .remove:hover {
background: none;
}
.selectize-control.plugin-remove_button .disabled [data-value] .remove {
border-left-color: #e0e0e0;
}
.selectize-control {
position: relative;
}
.selectize-dropdown,
.selectize-input,
.selectize-input input {
color: #333333;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 14px;
-webkit-font-smoothing: inherit;
line-height: 20px;
color: #333333;
-webkit-font-smoothing: inherit;
}
.selectize-input,
.selectize-control.single .selectize-input.input-active {
display: inline-block;
cursor: text;
background: #ffffff;
cursor: text;
display: inline-block;
}
.selectize-input {
position: relative;
z-index: 1;
border: 1px solid #d0d0d0;
padding: 7px 10px;
display: inline-block;
width: 100%;
padding: 7px 10px;
overflow: hidden;
border: 1px solid #d0d0d0;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
-webkit-box-shadow: none;
box-shadow: none;
position: relative;
z-index: 1;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
-webkit-box-shadow: none;
box-shadow: none;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
}
.selectize-control.multi .selectize-input.has-items {
padding: 5px 10px 2px;
}
.selectize-input.full {
background-color: #ffffff;
}
.selectize-input.disabled,
.selectize-input.disabled * {
cursor: default !important;
}
.selectize-input.focus {
-webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.15);
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.15);
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.15);
}
.selectize-input.dropdown-active {
-webkit-border-radius: 4px 4px 0 0;
-moz-border-radius: 4px 4px 0 0;
border-radius: 4px 4px 0 0;
-moz-border-radius: 4px 4px 0 0;
border-radius: 4px 4px 0 0;
}
.selectize-input > * {
vertical-align: baseline;
display: -moz-inline-stack;
display: inline-block;
*display: inline;
vertical-align: baseline;
zoom: 1;
*display: inline;
}
.selectize-control.multi .selectize-input > div {
padding: 1px 3px;
margin: 0 3px 3px 0;
color: #333333;
cursor: pointer;
margin: 0 3px 3px 0;
padding: 1px 3px;
background: #e6e6e6;
color: #333333;
border: 1px solid #cccccc;
}
.selectize-control.multi .selectize-input > div.active {
color: #ffffff;
background: #0088cc;
color: #ffffff;
border: 1px solid #0077b3;
}
.selectize-control.multi .selectize-input.disabled > div,
.selectize-control.multi .selectize-input.disabled > div.active {
color: #474747;
background: #fafafa;
border: 1px solid #e0e0e0;
}
.selectize-input > input {
max-width: 100% !important;
max-height: none !important;
min-height: 0 !important;
padding: 0 !important;
min-height: 0 !important;
max-height: none !important;
max-width: 100% !important;
margin: 0 !important;
line-height: inherit !important;
text-indent: 0 !important;
background: none !important;
border: 0 none !important;
-webkit-box-shadow: none !important;
box-shadow: none !important;
background: none !important;
line-height: inherit !important;
-webkit-user-select: auto !important;
-webkit-box-shadow: none !important;
box-shadow: none !important;
}
.selectize-input > input::-ms-clear {
display: none;
}
.selectize-input > input:focus {
outline: none !important;
}
.selectize-input::after {
content: ' ';
display: block;
clear: left;
content: ' ';
}
.selectize-input.dropdown-active::before {
content: ' ';
display: block;
position: absolute;
right: 0;
background: #e5e5e5;
height: 1px;
bottom: 0;
left: 0;
display: block;
height: 1px;
background: #e5e5e5;
content: ' ';
right: 0;
}
.selectize-dropdown {
position: absolute;
z-index: 10;
margin: -1px 0 0 0;
background: #ffffff;
border: 1px solid #d0d0d0;
background: #ffffff;
margin: -1px 0 0 0;
border-top: 0 none;
-webkit-border-radius: 0 0 4px 4px;
-moz-border-radius: 0 0 4px 4px;
border-radius: 0 0 4px 4px;
-webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
-webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
-webkit-border-radius: 0 0 4px 4px;
-moz-border-radius: 0 0 4px 4px;
border-radius: 0 0 4px 4px;
}
.selectize-dropdown [data-selectable] {
overflow: hidden;
cursor: pointer;
overflow: hidden;
}
.selectize-dropdown [data-selectable] .highlight {
background: rgba(255, 237, 40, 0.4);
-webkit-border-radius: 1px;
-moz-border-radius: 1px;
border-radius: 1px;
-moz-border-radius: 1px;
border-radius: 1px;
}
.selectize-dropdown [data-selectable],
.selectize-dropdown .optgroup-header {
padding: 3px 10px;
}
.selectize-dropdown .optgroup:first-child .optgroup-header {
border-top: 0 none;
}
.selectize-dropdown .optgroup-header {
color: #999999;
cursor: default;
background: #ffffff;
cursor: default;
}
.selectize-dropdown .active {
color: #ffffff;
background-color: #0088cc;
color: #ffffff;
}
.selectize-dropdown .active.create {
color: #ffffff;
}
.selectize-dropdown .create {
color: rgba(51, 51, 51, 0.5);
}
.selectize-dropdown-content {
max-height: 200px;
overflow-x: hidden;
overflow-y: auto;
overflow-x: hidden;
max-height: 200px;
}
.selectize-control.single .selectize-input,
.selectize-control.single .selectize-input input {
cursor: pointer;
}
.selectize-control.single .selectize-input.input-active,
.selectize-control.single .selectize-input.input-active input {
cursor: text;
}
.selectize-control.single .selectize-input:after {
content: ' ';
display: block;
position: absolute;
top: 50%;
right: 15px;
display: block;
margin-top: -3px;
width: 0;
height: 0;
margin-top: -3px;
border-color: #000000 transparent transparent transparent;
border-style: solid;
border-width: 5px 5px 0 5px;
content: ' ';
border-color: #000000 transparent transparent transparent;
}
.selectize-control.single .selectize-input.dropdown-active:after {
margin-top: -4px;
border-color: transparent transparent #000000 transparent;
border-width: 0 5px 5px 5px;
border-color: transparent transparent #000000 transparent;
}
.selectize-control.rtl.single .selectize-input:after {
right: auto;
left: 15px;
right: auto;
}
.selectize-control.rtl .selectize-input > input {
margin: 0 4px 0 -2px !important;
}
.selectize-control .selectize-input.disabled {
background-color: #ffffff;
opacity: 0.5;
background-color: #ffffff;
}
.selectize-dropdown {
z-index: 1000;
margin: 2px 0 0 0;
z-index: 1000;
border: 1px solid rgba(0, 0, 0, 0.2);
border-radius: 4px;
-webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
-moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
-moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
}
.selectize-dropdown .optgroup-header {
font-size: 11px;
font-weight: bold;
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
text-transform: uppercase;
}
.selectize-dropdown .optgroup:first-child:before {
display: none;
}
.selectize-dropdown .optgroup:before {
content: ' ';
display: block;
*width: 100%;
height: 1px;
margin: 9px 1px;
*margin: -5px 0 5px;
margin-right: -10px;
margin-left: -10px;
overflow: hidden;
background-color: #e5e5e5;
border-bottom: 1px solid #ffffff;
content: ' ';
margin-left: -10px;
margin-right: -10px;
}
.selectize-dropdown [data-selectable].active {
background-color: #0081c2;
background-image: -moz-linear-gradient(top, #0088cc, #0077b3);
@@ -404,32 +354,26 @@
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);
}
.selectize-dropdown-content {
padding: 5px 0;
}
.selectize-dropdown-header {
padding: 6px 10px;
}
.selectize-input {
-webkit-transition: border linear 0.2s, box-shadow linear 0.2s;
-moz-transition: border linear 0.2s, box-shadow linear 0.2s;
-o-transition: border linear 0.2s, box-shadow linear 0.2s;
transition: border linear 0.2s, box-shadow linear 0.2s;
-webkit-transition: border linear .2s, box-shadow linear .2s;
-moz-transition: border linear .2s, box-shadow linear .2s;
-o-transition: border linear .2s, box-shadow linear .2s;
transition: border linear .2s, box-shadow linear .2s;
}
.selectize-input.dropdown-active {
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
}
.selectize-input.dropdown-active::before {
display: none;
}
.selectize-input.input-active,
.selectize-input.input-active:hover,
.selectize-control.multi .selectize-input.focus {
@@ -437,31 +381,30 @@
border-color: rgba(82, 168, 236, 0.8) !important;
outline: 0 !important;
outline: thin dotted \9 !important;
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6) !important;
-moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6) !important;
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6) !important;
-webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(82,168,236,.6) !important;
-moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(82,168,236,.6) !important;
box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(82,168,236,.6) !important;
}
.selectize-control.single .selectize-input {
color: #333333;
text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);
background-color: #f5f5f5;
*background-color: #e6e6e6;
background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));
background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);
background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);
background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);
border-color: #e6e6e6 #e6e6e6 #bfbfbf;
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
-moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
*background-color: #e6e6e6;
/* Darken IE7 buttons by default so they stand out more given they won't have borders */
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
-webkit-box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);
-moz-box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);
box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);
}
.selectize-control.single .selectize-input:hover,
.selectize-control.single .selectize-input:focus,
.selectize-control.single .selectize-input:active,
@@ -472,79 +415,72 @@
background-color: #e6e6e6;
*background-color: #d9d9d9;
}
.selectize-control.single .selectize-input:active,
.selectize-control.single .selectize-input.active {
background-color: #cccccc \9;
}
.selectize-control.single .selectize-input:hover {
color: #333333;
text-decoration: none;
background-position: 0 -15px;
-webkit-transition: background-position 0.1s linear;
-moz-transition: background-position 0.1s linear;
-o-transition: background-position 0.1s linear;
transition: background-position 0.1s linear;
-moz-transition: background-position 0.1s linear;
-o-transition: background-position 0.1s linear;
transition: background-position 0.1s linear;
}
.selectize-control.single .selectize-input.disabled {
background: #e6e6e6 !important;
-webkit-box-shadow: none;
-moz-box-shadow: none;
box-shadow: none;
-moz-box-shadow: none;
box-shadow: none;
}
.selectize-control.multi .selectize-input {
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
-moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
-moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
}
.selectize-control.multi .selectize-input.has-items {
padding-right: 7px;
padding-left: 7px;
padding-right: 7px;
}
.selectize-control.multi .selectize-input > div {
color: #333333;
text-shadow: none;
background-color: #f5f5f5;
*background-color: #e6e6e6;
background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));
background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);
background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);
background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);
background-repeat: repeat-x;
border: 1px solid #cccccc;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);
border-color: #e6e6e6 #e6e6e6 #bfbfbf;
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
*background-color: #e6e6e6;
border: 1px solid #cccccc;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
-moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
-moz-border-radius: 4px;
border-radius: 4px;
-webkit-box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);
-moz-box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);
box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);
}
.selectize-control.multi .selectize-input > div.active {
-webkit-box-shadow: 0 1px 2px rgba(0,0,0,.05);
-moz-box-shadow: 0 1px 2px rgba(0,0,0,.05);
box-shadow: 0 1px 2px rgba(0,0,0,.05);
color: #ffffff;
text-shadow: none;
background-color: #0081c2;
*background-color: #0088cc;
background-image: -moz-linear-gradient(top, #0088cc, #0077b3);
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));
background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);
background-image: -o-linear-gradient(top, #0088cc, #0077b3);
background-image: linear-gradient(to bottom, #0088cc, #0077b3);
background-repeat: repeat-x;
border: 1px solid #0088cc;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);
border-color: #0077b3 #0077b3 #004466;
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
-moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
}
*background-color: #0088cc;
border: 1px solid #0088cc;
}

File diff suppressed because one or more lines are too long

View File

@@ -1072,10 +1072,11 @@
this.renderError(el, err);
};
this.renderError = function(el, err) {
this.clearError(el);
if (err.message === '') {
// not really error, but we just need to wait (e.g. action buttons)
$(el).empty();
return this.clearError(el);
return;
}
var errClass = 'shiny-output-error';
if (err.type !== null) {
@@ -1284,7 +1285,7 @@
registerDependency(dep.name, dep.version);
var path = dep.path;
var href = dep.src.href;
var $head = $("head").first();
@@ -1298,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);
}
@@ -1721,7 +1722,9 @@
};
},
initialize: function(el) {
$(el).slider();
var $el = $(el);
$el.slider();
$el.next('span.jslider').css('width', $el.data('width'));
}
});
inputBindings.register(sliderInputBinding, 'shiny.sliderInput');
@@ -2207,6 +2210,7 @@
control.destroy();
control = $el.selectize(settings)[0].selectize;
}
$el.next('div.selectize-control').css('width', config.data('width'));
return control;
}
});

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,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{checkboxGroupInput}
\alias{checkboxGroupInput}
\title{Checkbox Group 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{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,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{getDefaultReactiveDomain}
\alias{domains}
\alias{getDefaultReactiveDomain}

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}

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

@@ -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,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{radioButtons}
\alias{radioButtons}
\title{Create radio buttons}

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,9 +1,10 @@
% 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}
\usage{
renderPrint(expr, env = parent.frame(), quoted = FALSE, func = NULL)
renderPrint(expr, env = parent.frame(), quoted = FALSE, func = NULL,
width = getOption("width"))
}
\arguments{
\item{expr}{An expression that may print output and/or return a printable R
@@ -14,7 +15,9 @@ object.}
\item{quoted}{Is \code{expr} a quoted expression (with \code{quote()})? This}
\item{func}{A function that may print output and/or return a printable R
object (deprecated; use \code{expr} instead).}
object (deprecated; use \code{expr} instead).}
\item{width}{The value for \code{\link{options}('width')}.}
}
\description{
Makes a reactive version of the given function that captures any printed

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}

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{runUrl}
\alias{runUrl}
\title{Run a Shiny application from a URL}

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