Compare commits

...

5484 Commits
v0.6.0 ... main

Author SHA1 Message Date
Karan
07af5f91c8 chore(license): Change license from GPL-3 to MIT (#4339)
* Change license from GPL-3 to MIT

Updated the project license from GPL-3 to MIT in DESCRIPTION, LICENSE, LICENSE.md, README.md, and package.json. Added LICENSE.md with the MIT license text and updated .Rbuildignore to exclude LICENSE.md from builds.

* `npm run build` (GitHub Actions)

* Update LICENSE and add LICENSE.note

Replaced the LICENSE file content with a summary including year and copyright holder. Moved detailed third-party license information to a new LICENSE.note file.

* Remove R check log file

Deleted the ..Rcheck/00check.log file, likely to clean up generated or temporary files from the repository.
2025-12-16 17:51:22 -06:00
Barret Schloerke
fda6a9fede chore(assets): Update asset versions (#4337) 2025-12-11 11:56:42 -05:00
Barret Schloerke
d2245a2e34 Increment version number to 1.12.1.9000 2025-12-09 16:29:27 -05:00
Barret Schloerke
a12a8130b8 v1.12.1 (#4329) 2025-12-09 16:26:52 -05:00
Barret Schloerke
b436d2a96d Clarify OTel collection level usage in docs (#4335)
Co-authored-by: Carson Sievert <cpsievert1@gmail.com>
2025-12-08 15:31:57 -05:00
Barret Schloerke
05b0f270c4 fix(otel): ExtendedTask's otel enabled status set during init (#4334) 2025-12-08 14:55:59 -05:00
Barret Schloerke
f24f71e4e0 feat(otel): Add withOtelCollect() and localOtelCollect() (#4333) 2025-12-08 14:30:40 -05:00
Barret Schloerke
63a00f775f fix(otel): Duplicate otel code attribute keys using both deprecated and preferred names (#4325) 2025-12-03 16:37:20 -05:00
Barret Schloerke
5a946caf35 Skip timer tests on CRAN and fix empty vector comparison (#4327) 2025-12-03 16:29:17 -05:00
Barret Schloerke
16c016a171 Increment version number to 1.12.0.9000 2025-12-03 15:50:36 -05:00
Barret Schloerke
284af65534 Update .Rbuildignore 2025-12-03 15:50:27 -05:00
Barret Schloerke
b5da7868fa v1.12.0 (#4312) 2025-12-03 15:48:49 -05:00
ismirsehregal
c8a41aa834 Update dateYMD (#4318)
Co-authored-by: Garrick Aden-Buie <garrick@adenbuie.com>
2025-12-01 10:25:28 -05:00
Copilot
390f6d3b95 chore(otel): Rename shiny.otel.bind to shiny.otel.collect (#4321)
Co-authored-by: Barret Schloerke <barret@posit.co>
2025-11-25 16:36:56 -05:00
Barret Schloerke
9a2140cd19 chore(test): Fix stacks test with R 4.5.2 (#4322) 2025-11-25 16:31:53 -05:00
Barret Schloerke
e3cf4fb089 refactor(otel): Cache tracer and logger on init and on demand (#4315)
Co-authored-by: Charlie Gao <53399081+shikokuchuo@users.noreply.github.com>
2025-11-11 08:44:57 -05:00
Barret Schloerke
472a1cdba1 refactor(otel): Refactor internal method names (#4313) 2025-11-06 11:20:37 -05:00
Barret Schloerke
b56c275364 feat(otel): Enhanced OpenTelemetry support (#4300) 2025-10-28 14:01:50 -04:00
Garrick Aden-Buie
592e825a0f feat: Replace client-side markdown rendering with server-side in showcase mode (#4306)
* feat: Replace client-side markdown rendering with server-side in showcase mode

* `devtools::document()` (GitHub Actions)

* chore: callout rendering differences may happen
2025-10-22 09:34:20 -04:00
Barret Schloerke
50a140c580 ci(test): Disable installation of Cairo for unit tests (#4301) 2025-10-15 16:24:22 -04:00
Barret Schloerke
48d255a235 feat: Add {otel} support (#4269) 2025-10-14 15:40:36 -04:00
Barret Schloerke
a01fcc5194 chore(check): Fix minor check warnings (#4299) 2025-10-10 16:30:47 -04:00
Winston Chang
b6e9e9d216 Update package.json for publishing (#4284)
* Update package.json for publishing

* Use custom readme file for npm

* Update repository URLs

* Script cleanup

* Use name @posit/shiny
2025-09-09 16:37:06 -05:00
Barret Schloerke
5ddb99a5b4 update docs (#4285) 2025-09-05 13:52:30 -04:00
Carson Sievert
f981ed6363 feat: add shinyRemoveButton selectize.js option (for py-shiny) (#4276)
* fix: supply and retain default selectize.js plugins (for py-shiny)

* `npm run build` (GitHub Actions)

* Move more in a 'remove_button' attribute direction

* `npm run build` (GitHub Actions)

* Move to a JSON-only approach

* `npm run build` (GitHub Actions)

* Drop sticky update logic by always sending 'missing' value and resolving client-side

* Cleanup

* Don't mutate options; better typing pattern

* `npm run build` (GitHub Actions)

---------

Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
2025-08-28 15:49:25 -05:00
Carson Sievert
6d6b0ea6f9 fix: add CSS workaround to hide all but the first selectize remove button (#4275)
* fix: add CSS workaround to hide all but the first selectize remove button

* Update news

* Apply suggestions from code review
2025-08-21 16:48:34 -05:00
Barret Schloerke
0e355ed25c preemptively run revdepcheck. 5 failures. 2025-08-18 09:10:19 -04:00
Barret Schloerke
80a9ff470c fix(scss): Remove updated scss files and restore R sass compilation (#4272)
* Revert changes in 8861645d99 from #4252

We compile from R sass. So we should be partial to R's compiler, no the latest in npm

* Restore original compile script (with message) that built using R-sass, not npm

* Add step in build command to update the sass output

* run new command
2025-08-14 16:03:48 -04:00
Barret Schloerke
ead0abcd62 bug(check): Update .Rbuildignore with new and removed files (#4270) 2025-08-04 23:17:45 -04:00
Barret Schloerke
7dcb54bc7e build(js): Migrate from yarn to npm (#4252) 2025-08-04 16:07:39 -04:00
Colin Gillespie
ae82850e1f docs: Update R supported versions (#4256) 2025-08-04 10:37:48 -04:00
Daniel Chen
0610d756a8 docs: update srcts/readme.md to shiny 1.11.1 (#4259) 2025-08-04 09:50:06 -04:00
Carson Sievert
6325067130 Update DESCRIPTION (#4255)
* Change maintainer to Carson

* Add Garrick

* Add Posit ROR link

* `usethis::use_tidy_description()` (GitHub Actions)

* `devtools::document()` (GitHub Actions)

---------

Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
2025-07-22 13:19:24 -05:00
Carson Sievert
1a4e52dc73 Run routine (#4257)
* Touch news

* `usethis::use_tidy_description()` (GitHub Actions)

* Revert "Touch news"

This reverts commit 854e7e10ae.

* `usethis::use_tidy_description()` (GitHub Actions)

---------

Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
2025-07-22 12:38:23 -05:00
Winston Chang
08383ad8b9 Update srcts/README with info about window.Shiny (#4198) 2025-07-18 17:22:52 -05:00
Carson Sievert
ecf6bfe9a7 Put actionButton()s icon and label into containers (#4249)
* Put action icon and label into containers

* Update snaps

* More robust test

* Don't include container if icon/label isn't specified

* `yarn build` (GitHub Actions)

* Send HTML string/deps on update; update news

---------

Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
2025-07-14 16:22:03 -05:00
Carson Sievert
f7528568e5 Increment version number to 1.11.1.9000 (#4253)
* Increment version number to 1.11.1.9000

* `yarn build` (GitHub Actions)

* Sync package version (GitHub Actions)

---------

Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
2025-07-07 22:02:14 -07:00
Carson Sievert
51f653b66f v1.11.1 release candidate (#4245)
* v1.11.1 release candidate

* `yarn build` (GitHub Actions)

* Revert actionButton()/actionLink() implementation to v1.11.0's behavior (re-introducing #4239)

* Minimal fix to address the regression in #4239

Ideally we'd fix this issue, and also get updateActionButton() working with HTML labels, but thanks to today's release of kinesis (which snapshots all of actionButton()s markup), and CRAN dragging their feet to accept our original submission (which was fine, by the way), we can't have nice things

* `yarn build` (GitHub Actions)

---------

Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
2025-07-07 21:53:08 -07:00
Carson Sievert
460a93a5fd Revert the addition of spacing between icon and label in actionButton() (#4248)
* Revert the addition of spacing between icon and label in actionButton()

* `yarn build` (GitHub Actions)

---------

Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
2025-06-27 10:58:17 -05:00
Carson Sievert
3ea4c8eb1d Restrict icon/label separator spacing to actionButton() (#4247)
* Follow up to #4242: Restrict icon/label separator spacing to actionButton()

* `yarn build` (GitHub Actions)

* Add spacing only when both icon and label are truthy

* Update snapshot

* `yarn build` (GitHub Actions)

* Slightly more readable JS

* `yarn build` (GitHub Actions)

---------

Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
2025-06-26 19:12:13 -05:00
Carson Sievert
f237de559d Fix front-end action button label updating logic (#4242)
* Close #4239: fix front-end action button label updating logic (follow up to #3996)

* Update news

* Use a separator instead of putting markup in attributes

* `yarn build` (GitHub Actions)

* Address feedback

* Cleanup

* Refactor into a single method to split icon/label

* `yarn build` (GitHub Actions)

* Better naming

* Add some padding to the separator

* Add some unit tests for R logic

* Update NEWS.md

* Update NEWS.md

* Update NEWS.md

* Update NEWS.md

* Increase backcompat (keep same R structure when no icon is provided)

* Refine comment

---------

Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
2025-06-26 16:32:17 -05:00
Carson
8c7abbac44 Update news 2025-06-26 13:56:35 -05:00
Carson Sievert
1710316142 Properly handle undefined value for input subscribe callback (#4243)
* Close #4240: properly handle undefined value for input subscribe callback

* Refactor normalization into a function
2025-06-26 09:36:09 -05:00
Carson Sievert
2d856f4f09 Start new version (#4241)
* Start new version

* `yarn build` (GitHub Actions)

* Sync package version (GitHub Actions)

---------

Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
2025-06-25 17:05:03 -05:00
Carson Sievert
ab219e3408 v1.11.0 release candidate (#4232) 2025-06-25 16:28:51 -05:00
Carson Sievert
673be3dd77 Follow up to #3996: fix front-end checkbox label updating logic (#4238)
* Follow up to #3996: fix front-end checkbox label updating logic

* More descriptive name
2025-06-20 15:15:30 -05:00
Carson Sievert
b25e6feabb feat(InputBinding): subscribe callback now supports event priority (#4211)
* feat(InputBinding): subscribe callback now supports event priority

* Update NEWS.md

* Update srcts/src/shiny/bind.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* `yarn build` (GitHub Actions)

* Simpler and more consistent typing

* Support a suitable object as input

* Provide a type for the callback itself, not just the valueit's given

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
2025-06-19 10:27:45 -05:00
Carson Sievert
e6b22d86b6 Follow up to #3996 when label is unspecified (i.e., NULL), don't include it in the message (#4237) 2025-06-19 09:48:44 -05:00
Carson Sievert
9c5196ee63 Run routine (#4234)
* Run routine

* `devtools::document()` (GitHub Actions)

* `yarn build` (GitHub Actions)

* Update NEWS.md

---------

Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
2025-06-16 12:52:48 -05:00
Hedley
9b53251b09 chore: #4175 update jquery-ui to 1.14.1 (#4205)
* chore: #4175 update jquery-ui to 1.14.1

* Update to latest types

---------

Co-authored-by: Carson <cpsievert1@gmail.com>
2025-06-16 12:42:07 -05:00
David Macro
942bdd8c40 Update jQuery to 3.7.1 (#3969)
* Update jquery

* Upgrade to latest types

* Update news

---------

Co-authored-by: Carson Sievert <cpsievert1@gmail.com>
2025-06-16 11:46:17 -05:00
edemain03
d762865753 Fix 404 in example 08_html (shiny.min.css) (#4221)
* fix(examples-shiny): use shiny.min.css in 08_html to avoid 404 (#4220)

* Update NEWS.md

* Minimize all the files

---------

Co-authored-by: Carson Sievert <cpsievert1@gmail.com>
2025-06-16 11:20:00 -05:00
Carson Sievert
992b967095 Follow up to #3870: fix location of news item (#4233) 2025-06-16 11:12:58 -05:00
Stuart Russell
9a39cea0cc Bugfix for error found in tests (#3870)
* Bugfix for error found when calling shiny::shinyAppTemplate without library(shiny)

* Update news

* Update NEWS.md

---------

Co-authored-by: Carson <cpsievert1@gmail.com>
2025-06-16 11:05:43 -05:00
John Coene
db9f210257 Allow update input labels with HTML (#3996)
* fix: allow update input labels with HTML fixes #3995

* refactor: use processDeps and renderContent

* fix: formatting on lists

* fix: put spaces between infix

* chore: generated files

* fix: update input tests

* revert: generated javascript and sourcemaps

* fix: empty label check

* Remove package-lock

* Undo unintended change when merging

* Update news

* Simplify

---------

Co-authored-by: Carson <cpsievert1@gmail.com>
2025-06-16 11:01:44 -05:00
Charlie Gao
e8b7c08a19 Adds mirai to documentation (#4230)
* Update docs to mention mirai

* Update example to use mirai

* Fix other roxygen2 render
2025-06-16 09:42:21 -05:00
Michael Chirico
b596245571 family->given for R Core authorship (#4222) 2025-06-12 16:23:57 -05:00
Carson Sievert
57bb3a12d3 fix(renderPlot): get interactive plotting working with ggplot2 v4.0 (#4228)
* fix(renderPlot): get interactive plotting working with ggplot2 v4.0

* Update NEWS.md
2025-06-12 16:23:38 -05:00
Winston Chang
219fbc6819 Update NEWS 2025-06-09 17:22:20 -05:00
Teun van den Brand
a660093fa5 Compatibility with ggplot2 4.0.0 (#4226)
* add S7 class method

* Update tests/testthat/test-plot-coordmap.R

---------

Co-authored-by: Winston Chang <winston@stdout.org>
2025-06-09 17:20:43 -05:00
Garrick Aden-Buie
eac0eea886 fix: Wrap extended task invocation in promise_resolve() (#4225)
* fix: Wrap extended task invocation in `promise_resolve()`

* refactor: cleanup error handling and promise chain

* chore: add news entry
2025-05-30 08:44:31 -04:00
Charlie Gao
6df0bb9423 Fix performance regression related to limiting deep call stack growth (#4214)
* Use less expensive version of getCallNames() just for hashing

* Update R/conditions.R

Co-authored-by: Carson Sievert <cpsievert1@gmail.com>

---------

Co-authored-by: Carson Sievert <cpsievert1@gmail.com>
Co-authored-by: Barret Schloerke <barret@rstudio.com>
2025-05-23 18:56:00 +01:00
Barret Schloerke
159e771ac7 Relax test as we've already confirmed throttle is updating. Only required final value expectation (#4218) 2025-05-23 13:43:03 -04:00
Carson Sievert
ca41c0831b feat!(submitButton): don't treat any HTML type='submit' button/input like a submitButton() (#4209)
* feat!(submitButton): don't treat any HTML type='submit' button/input like a submitButton()

* `yarn build` (GitHub Actions)

* Sync package version (GitHub Actions)

* Update NEWS.md

* `yarn build` (GitHub Actions)

---------

Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
Co-authored-by: Barret Schloerke <barret@rstudio.com>
Co-authored-by: schloerke <schloerke@users.noreply.github.com>
2025-05-01 12:37:21 -05:00
Carson Sievert
316c3c8409 feat(textAreaInput): Add an autoresize option (#4210)
* feat(textAreaInput): Add an autoresize option

* `devtools::document()` (GitHub Actions)

* `yarn build` (GitHub Actions)

* Update NEWS.md

* Fix broken CSS selector.

Rules aren't being applied correctly in PyShiny either...

* Put shiny input class on container (to mirror what PyShiny does)

* Refactor autoresize logic

* Reduce diff size

---------

Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
2025-04-30 18:34:04 -05:00
Garrick Aden-Buie
f79a22b987 feat: Fully reload ui/server when autoreload occurs (#4184)
* feat: Fully reload ui/server when autoreload occurs

* chore: remove stray empty line

* chore: clean up function names and add comments

* docs: Add news item

* feat: Use {watcher} for autoreload file watching (#4185)

* feat: Use {watcher}

* chore: shikokuchuo/watcher@dev

* chore: watcher is on CRAN now

* chore: Undo air format changes

* feat: Use `shiny.autoreload.interval` for watcher latency

* chore: Simply track last time auto-reload changed

* docs: rewrite options docs for clarity

* chore: code style

* docs: global.R changes are not applied

* feat(ui/server): Autoreload also reloads global and R support files

* chore: remove outdated comment

* chore: safer comparisons

* chore: Restore legacy autoreload watcher if {watcher} not installed

* rename: autoload_r_support_if_needed()

* chore: use `rlang::is_false()`

* chore: use_build_ignore("_dev")
2025-04-24 13:53:40 -04:00
Garrick Aden-Buie
83219e3551 fix: Improve jquery node detection (#4203) 2025-03-25 21:26:27 -04:00
Garrick Aden-Buie
f55c26af4a docs: Link to outputOptions() from render functions (#4196)
* docs(downloadHandler): Link to `outputOptions()`

* docs: include `outputOptions()` in other render functions
2025-03-03 11:11:11 -05:00
Garrick Aden-Buie
9fbb2c5829 docs: Rewrite news for #4183 (#4195) 2025-02-28 08:06:54 -05:00
Winston Chang
531f31b66f textInput(), textAreaInput(), numericInput(), passwordInput(): allow updating value on blur (#4183)
* textInput: Add updateOn parameter and allow setting debounce delay

* `devtools::document()` (GitHub Actions)

* `yarn build` (GitHub Actions)

* Update news

* Remove debounce parameter

* `devtools::document()` (GitHub Actions)

* `yarn build` (GitHub Actions)

* Add updateOn parameter to numericInput, passwordInput

* Add updateOn to textAreaInput()

* `devtools::document()` (GitHub Actions)

* feat: Ignore change events unless from server messages when `updateOn="blur"`

* refactor: `updateOn="change"` instead of `"input"`

* feat: Update inputs on Enter or Cmd/Ctrl+Enter (textarea)

* chore: Document `...` and ensure they are empty

* chore: Use `rlang::arg_match()`

* chore: code style (air format)

* fix: textAreaInput, not inputTextArea

* docs(NEWS): Minor edit

* chore: If element has focus, ignore change event

---------

Co-authored-by: wch <wch@users.noreply.github.com>
Co-authored-by: Garrick Aden-Buie <garrick@adenbuie.com>
2025-02-26 12:45:26 -05:00
Winston Chang
58e152154a Stop using Babel; compile JS to ES2020 (#4066)
Co-authored-by: wch <wch@users.noreply.github.com>
Co-authored-by: Garrick Aden-Buie <garrick@adenbuie.com>
Co-authored-by: gadenbuie <gadenbuie@users.noreply.github.com>
Co-authored-by: Barret Schloerke <barret@posit.co>
2025-02-03 12:37:19 -05:00
Garrick Aden-Buie
55b37fdeb3 fix(insertTab): Render inserted nav html only once (#4179)
* fix: Fix checking if `scope` is a jquery element

Fixes rstudio/bslib#1159

* refactor: Don't check binding validity if `scope` isn't an element

* fix(insertTab): Render inserted nav html only once

* chore: Don't need to delay binding

* fix: Bind all after inserting nav controls

Output bindings require outputs to be attached to the DOM.

* chore: align comment

* chore: Add news item
2025-01-27 17:15:27 -05:00
Garrick Aden-Buie
b8a5aef53a feat: De-duplicate client console messages (#4177)
* feat: De-duplicate client console messages

* refactor(ShinyErrorConsole): Add `appendConsoleMessage()` static method

* fix: Make `appendConsoleMessage()` an instance method

* rename: `createClientMessageElement()`

* docs: add news item
2025-01-27 16:57:10 -05:00
Carson Sievert
d764ea9b4e Busy indicator improvements (#4172)
* Make sure spinner is visible when htmlwidget errors are visible

* Give recalculating outputs a min-height large enough to show the spinner

* tableOutput() now gets the spinner treatment

* yarn run bundle_extras

* Forward visibility hidden for all recalculating widgets, not just those with a error message (otherwise spinner won't be visible after a req())

* Update news
2025-01-22 14:14:20 -06:00
olivroy
8ad779f949 Various test lints (#4171)
Co-authored-by: Garrick Aden-Buie <garrick@adenbuie.com>
2025-01-21 15:08:00 -05:00
olivroy
7642fc84b7 Replace crayon by cli + address some TODOs to add some color (#4170)
* Replace crayon by cli + address some TODOs to add some color

* docs: add news

---------

Co-authored-by: Garrick Aden-Buie <garrick@adenbuie.com>
2025-01-21 11:00:51 -05:00
Garrick Aden-Buie
0952f3e0a7 ci: update for 2025 (#4178)
* ci: update for 2025

* chore: RStudio --> Posit
---------

Co-authored-by: gadenbuie <gadenbuie@users.noreply.github.com>
2025-01-14 13:26:41 -05:00
Garrick Aden-Buie
13ca8dfc57 fix: Schedule .modal("hide") for transitioning modals (#4173)
* fix: Schedule modal removal for transitioning modals

* refactor: Simplify and both call and schedule modal hiding at same time

* Increment version number to 1.10.0.9000

* docs: Add NEWS entry
2024-12-31 16:27:25 -05:00
Garrick Aden-Buie
79f42f5846 v1.10.0 (#4166)
* Increment version number to 1.10.0

* `yarn build` (GitHub Actions)

* Sync package version (GitHub Actions)

* chore: urlchecker::url_update()

✔ Updated: <https://shiny.rstudio.com/reference/shiny/latest/insertUI.html> to <https://shiny.posit.co/r/reference/shiny/latest/insertui.html> in NEWS.md
✔ Updated: <https://shiny.rstudio.com/reference/shiny/latest/modalDialog.html> to <https://shiny.posit.co/r/reference/shiny/latest/modaldialog.html> in NEWS.md
✔ Updated: <https://shiny.rstudio.com/reference/shiny/latest/Progress.html> to <https://shiny.posit.co/r/reference/shiny/latest/progress.html> in NEWS.md
✔ Updated: <https://shiny.rstudio.com/reference/shiny/latest/renderTable.html> to <https://shiny.posit.co/r/reference/shiny/latest/rendertable.html> in NEWS.md
✔ Updated: <https://shiny.rstudio.com/reference/shiny/latest/showNotification.html> to <https://shiny.posit.co/r/reference/shiny/latest/shownotification.html> in NEWS.md
✔ Updated: <https://shiny.rstudio.com/reference/shiny/latest/withProgress.html> to <https://shiny.posit.co/r/reference/shiny/latest/withprogress.html> in NEWS.md

* chore: revdepcheck

* chore: polish NEWS

* chore: update CRAN comments

* Polish NEWS

---------

Co-authored-by: gadenbuie <gadenbuie@users.noreply.github.com>
Co-authored-by: Carson <cpsievert1@gmail.com>
2024-12-16 09:30:53 -06:00
Joe Cheng
9a35b01e23 Fix observeEvent stack trace stripping (#4163)
* Fix observeEvent stack trace stripping

* Add unit test

* Add deep stack version of unit test
2024-12-09 20:50:53 -08:00
Joe Cheng
5bf0701939 Plot outputs incorrectly sized inside scaled outputs (#4139)
* Fix #4135: Plot outputs incorrectly sized inside scaled outputs

CSS zoom property affects el.getBoundingClientRect() but not
el.offsetWidth/Height. When reporting sizes of outputs from
client to server, we need to back out the CSS zoom because
those sizes are used as CSS width/height, which will be
affected by zoom.

(Note that something similar happens with CSS transforms but
we don't have a good way to deal with them)

* Squelch TS error

* `yarn build` (GitHub Actions)

* Add TODO

Co-authored-by: Garrick Aden-Buie <garrick@adenbuie.com>

* Rebuild JS

---------

Co-authored-by: jcheng5 <jcheng5@users.noreply.github.com>
Co-authored-by: Garrick Aden-Buie <garrick@adenbuie.com>
2024-12-08 01:25:32 -08:00
Garrick Aden-Buie
e5083f4938 feat: Avoid throwing errors for shared input/output IDs (#4101)
* refactor: Factor out message display from error handler

* feat: Add custom event for sending a client message

* feat: Report binding validity problem via event instead of throwing error

* feat: Don't need to hide shared input/output message

Now that it's not an error, it's safe to report

* refactor: Move `inDevMode()` logic into error console

* refactor: Rename `.error` --> `.event`

* feat: wrap client error message

It's otherwise hard to tell that the error is scrollable
Plus the scrolling is over the whole message rather than the part that overflows

* feat: always send client console messages to browser console as well

* chore: throw if `shiny:client-message` receives an event that isn't CustomEvent

* feat: Handle status in `showShinyClientMessage()`

* Renamed `showMessageInClientConsole()` to `showShinyClientMessage()` to improve clarity

* Added `status` argument to `showShinyClientMessage()` to allow for different message types

* refactor: Don't throw errors for duplicate IDs

Brings dev mode in line with current "prod" behavior,
where errors aren't thrown for duplciates. In both cases
we still get console or client messages.

* refactor: Clean up `status` inside `checkValidity()`

* refactor: Have `checkValidity()` handle emitting the client console event
2024-12-06 16:00:19 -05:00
Garrick Aden-Buie
ce6a562a3c chore: routine (#4161) 2024-12-06 15:16:29 -05:00
Dan Gealow
b6bcfc8683 Work around a selectize bug (re-fixes #3966) (#4142)
* Work around a selectize bug (re-fixes #3966)

---------

Co-authored-by: Garrick Aden-Buie <garrick@adenbuie.com>
2024-12-06 15:03:59 -05:00
Dean Attali
d37beeece7 ExtendedTask: add example to docs (#4087)
Co-authored-by: Garrick Aden-Buie <garrick@adenbuie.com>
2024-12-06 14:24:01 -05:00
Joe Cheng
79ee25620f Limit deep stack growth (#4156)
* Limit deep stack growth

* Improvements to deep stack trace culling

- Keep around the first deep stack trace; it may have useful
  information. (We may want to change this in the future to
  keep the first two stack traces, or even make it an option)
- Print out an indicator that we've elided stack traces, and
  how many

* Add comments

* Add NEWS item

* Add test for unlimited deep stacks

* Code review feedback

* Code review feedback

Co-authored-by: Carson Sievert <cpsievert1@gmail.com>

* Use head() over indexing

Co-authored-by: Carson Sievert <cpsievert1@gmail.com>

* Improve unit test robustness

* Remove vector indices from snapshot

* Make stack trace stripping work across deep stacks

* Pass tests

* Try passing tests again

* Rename keep_head to retain_first_n

* Remove misleading variable assignment

* Add more comments, refine dropTrivialTestFrames

* Don't call stripStackTraces if we're not stripping

* Use deep stack deduplication instead of elision

This hopefully will avoid any potential ..stacktraceon../off..
scoring issues, and will be more useful for users. The downside
is that it's still possible to have uselessly large deep stack
traces, but at least that will only happen now if you have
manually written gigantic async/promise chains by hand or maybe
did some clever metaprogramming. The coro case should be fine.

* Add coro-based unit test

* Use rlang::hash, it's much faster

* typo

Co-authored-by: Carson Sievert <cpsievert1@gmail.com>

* Remove unnecessary logic

* Simplify/robustify reactlog version checking test

* Warn only once on call stack digest cache miss

* Super conservatively wrap appendCallStackWithDupe in try/catch

* Use more specific attribute name

Co-authored-by: Carson Sievert <cpsievert1@gmail.com>

* Remove excessively cautious try/catch

---------

Co-authored-by: Carson Sievert <cpsievert1@gmail.com>
2024-12-06 10:17:05 -08:00
Joe Cheng
82c678a1eb Update NEWS.md for stack trace domain explosion 2024-12-03 13:37:58 -08:00
Joe Cheng
458924569a Stack trace domain explosion (#4155)
* Avoid way too many promise domains being activated

Using `captureStackTraces` in wrapForContext is a bad idea, it
piles on a new domain every time a handler is bound.

* Use captureStackTraces, it means the same thing

* Update promises version requirement

* Add test for stack trace growth

* Simplify stack trace snapshot tests

The `category` column isn't a good candidate for snapshot
testing, as its contents vary depending on how the package
was loaded/installed. During devtools::test() or similar,
shiny package code shows up as 'user'. But during CI, it
doesn't show up as anything.
2024-12-03 13:23:50 -08:00
Garrick Aden-Buie
501b012b2b chore: Remove zipfs from recommended vscode extensions (#4151) 2024-11-07 10:52:10 -05:00
Garrick Aden-Buie
ee1aac847a docs(runExample): display.mode follows DESCRIPTION (#4152)
Fixes #4077

The argument documentation wasn't updated to reflect that `runExample()` can run more than just Shiny's examples
2024-11-07 10:51:27 -05:00
bart1
7785a76a67 Closing bracket missing (#4150)
* type

* typo
2024-11-01 09:05:20 -05:00
Adam Foryś
79af1d6c92 Fix url bookmarking with possibility to modify excludes (#3762)
* Fix url bookmarking with possibility to modify excludes

* Update NEWS.md
2024-10-28 09:36:42 -05:00
Yihui Xie
a145add5d4 Use double-tilde for strikethrough in Markdown tests (#4144)
* Use double-tilde for strikethrough in Markdown tests

The current dev version of commonmark has disabled single tilde   for strikethrough: https://github.com/r-lib/commonmark/pull/33 Using double-tilde will make it consistent with Pandoc's Markdown (where single-tilde is for subscripts).

* Skip tests if commonmark is outdated

* Revert "Skip tests if commonmark is outdated"

This reverts commit 97bee20863.

---------

Co-authored-by: Carson Sievert <cpsievert1@gmail.com>
2024-10-15 11:21:53 -05:00
Dan Gealow
abf71389be Fix sporadic dates (#3664) (#3665)
* Remove dateInput and dateRangeInput handlers for keyup and input events

This prevents spurious updates while typing, but still sends when enter is pressed, focus is lost, or the GUI is clicked (due to the remaining `changeDate` and `change` handlers).

* chore: small edits to comments and NEWS item

---------

Co-authored-by: Garrick Aden-Buie <garrick@adenbuie.com>
2024-09-30 17:26:43 -04:00
Garrick Aden-Buie
2e2114f99d fix(busy): Show pulse if only UI are recalculating (#4137)
* fix(busy): Show pulse if only UI are recalculating

Because UI elements don't get spinners
2024-09-30 13:55:47 -04:00
Garrick Aden-Buie
09d415502f docs(NEWS): Fix name of sliderInput() function (#4136) 2024-09-27 11:14:40 -04:00
Garrick Aden-Buie
c489fef4ff fix(input_slider): Make sure last used handle is always above others (#4131) 2024-09-27 10:09:43 -04:00
Garrick Aden-Buie
9d12b0fca7 fix(conditionalPanel): Coerce condition result to boolean (#4127)
Co-authored-by: Kamil Zyla <kamil@appsilon.com>
2024-09-27 09:38:15 -04:00
Garrick Aden-Buie
cc9b9d4e6a feat(pulse): Tweak pulse animation and height (#4122) 2024-09-27 09:31:44 -04:00
Joe Cheng
34f9e4484d Merge pull request #4134 from rstudio/test/fix-reactivity-timing
fix: Timing of throttle/debounce reactivity test
2024-09-25 15:51:29 -07:00
Garrick Aden-Buie
03a3f8f886 test(reactivity): Consolidate identical tests into for loop 2024-09-25 10:09:17 -04:00
Garrick Aden-Buie
b900db0c74 test: Update the other test 2024-09-24 22:05:52 -04:00
Garrick Aden-Buie
5fb3ebc2d9 ci: run tests again 2024-09-24 22:00:19 -04:00
Garrick Aden-Buie
fbc6b2df57 chore: take out debugging code 2024-09-24 21:32:27 -04:00
Garrick Aden-Buie
6208225354 fix: Tweak updates to avoid overlapping events 2024-09-24 21:22:40 -04:00
Garrick Aden-Buie
e22b693418 chore: show value in debug too 2024-09-24 21:01:29 -04:00
Garrick Aden-Buie
c7ca49c634 debug: Add debugging messages for debounce/throttle test 2024-09-24 20:44:31 -04:00
Carson Sievert
d84aa94762 Start new version (#4113)
* Start new version

* `yarn build` (GitHub Actions)

* Sync package version (GitHub Actions)

---------

Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
2024-08-01 10:28:25 -05:00
Carson Sievert
89e2c18531 v1.9.1 release candidate (#4112)
* v1.9.1 release candidate

* `yarn build` (GitHub Actions)

* Sync package version (GitHub Actions)

---------

Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
2024-08-01 09:42:31 -05:00
Joe Cheng
43d36c08dc Remove double-scaling in coordmap.getPanelCss() (#4111)
Fixes #4110
2024-07-31 11:31:31 -05:00
Carson Sievert
4bc330e5dd Start new version (#4108)
* Start new version

* `yarn build` (GitHub Actions)

* Sync package version (GitHub Actions)

---------

Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
2024-07-29 17:21:35 -05:00
Carson Sievert
56ab530d87 v1.9.0 release candidate (#4105)
* Start v1.9.0 release candidate

* Check-in revdep results

* `yarn build` (GitHub Actions)

* Sync package version (GitHub Actions)

* `yarn build` (GitHub Actions)

* ran revdepcheck on cloud. 2 errors reported. Both seem like false positives

* Fix R CMD check note about Rd links targets missing package anchors

---------

Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
Co-authored-by: Barret Schloerke <barret@posit.co>
Co-authored-by: schloerke <schloerke@users.noreply.github.com>
2024-07-29 17:10:38 -05:00
Garrick Aden-Buie
599209a036 chore: make pulse and spinner opt-in (for now) (#4107)
* chore: make pulse and spinner opt-in (for now)

* Reword busy indication NEWS section

---------

Co-authored-by: Carson <cpsievert1@gmail.com>
2024-07-29 11:21:28 -05:00
Joe Cheng
15b5fa6c01 Click handler on scaled image getting clipped (#4094)
* Fix #3234: Click handler on scaled image getting clipped

There were two related problems here, both happening in the same scenario:
when an imageOutput with click handlers is showing an image at less than
its natural size (e.g. a 1000x1000 px .png file, being displayed in the
web page at 500x500 due to max-width or for whatever other reason), any
click where the image coordinate (1000x1000) exceeds the display size
(500x500).

In the example above, a user clicks at 300x300 in the 500x500 displayed
image. We call 300x300 the "CSS coordinates". This gets scaled up into
the position in the PNG's own coordinate system, "image coordinates":
in this case, 600x600. Since the 600x600 image coordinate is greater
than the 500x500 CSS coordinate limit, the following issues were
triggered.

1. When imageOutput(click=clickOpts(clip=TRUE)) (the default), these
   clicks weren't registering at all. There was code that detected
   clicks that were inside the imageOutput but outside the actual image,
   but this code didn't take scaling into account.

2. Even with clip=FALSE, the click would be triggered BUT the `x` and `y`
   values on the click event were incorrect--they would max out at the
   CSS coordinate limit. This because plot and image output divide the
   world into "panels" and clicks snap to the nearest panel. In the case
   of image outputs, the server doesn't provide any panels, so the
   client makes one big panel that covers the whole image--but that code
   was erroneously using CSS sizes, not image sizes.

* Update NEWS
2024-07-26 11:09:39 -05:00
Carson Sievert
3f4676d9a6 Enable busy indicators by default, add ability to disable/customize fade (#4104)
* Follow up to #4040: enable busy indicators by default

* Make our spinner invisible when wrapped inside a shinycssloaders::withSpinner() container

* Add the ability to disable/customize recalculating opacity (i.e., fade)

* Fix bug with fade not being applied correctly when the output container has no children

* `devtools::document()` (GitHub Actions)

* `yarn build` (GitHub Actions)

* Update NEWS.md

* Follow up to b7e7af: need to also rest opacity for :empty case (for initial calculation)

* Rd docs fixes/improvements

---------

Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
2024-07-24 12:57:42 -05:00
Winston Chang
bb89cf9235 Add Shiny.initializedPromise (#4063)
* Convert Shiny from interface to class

* Remove unused global Shiny type

* Add prettier plugin for organizing imports

* Disable eslint indentation rule

* Simplify types

* Add Shiny.connectedPromise and Shiny.sessionInitPromise

* Fix typing issue

* Move prettier plugin to devDependencies

* Rename Shiny class to ShinyClass, and export type

* Remove global Shiny type; use internal imports

* Small code cleanup

* Move initShiny() function into ShinyClass

* Rebuild type files

* Raise error if window.Shiny already exists

* Rename promises

* Add InitStatusPromise class

* `yarn build` (GitHub Actions)

* Update news

* Remove isConnected

* Update yarn.lock

* Rename isInitialized to initializedPromise

* Rebuild shiny.js

* `yarn build` (GitHub Actions)

* Update NEWS

---------

Co-authored-by: wch <wch@users.noreply.github.com>
2024-07-23 22:11:20 -05:00
Randy Zwitch
25c40967da Update issue template to use new forum.posit.co URL (#4038)
Co-authored-by: Garrick Aden-Buie <garrick@adenbuie.com>
Co-authored-by: Carson Sievert <cpsievert1@gmail.com>
2024-07-23 14:59:17 -04:00
Barret Schloerke
068b232e75 feat(reactlog): Add reactlogAddMark() (#4103) 2024-07-22 11:29:02 -04:00
Garrick Aden-Buie
0b7fda707e chore: Enable return of dependency CSS as Sass files (#4044)
* chore: Enable return of dependency CSS as Sass files

Makes it possible to extract the Sass files prior to compilation for the following CSS:

* shiny
* selectize
* ionrangeslider
* daterange picker

* refactor: Take a more functional approach

* fix: missing selectizeDir

* rename: __SassLayer --> __Sass
2024-06-13 16:08:54 -04:00
Carson Sievert
9fd4ba199e Close #4080: Require bslib 0.6 or higher (#4085) 2024-06-03 09:39:29 -05:00
Dean Attali
43e40c7969 news: fix function name typo (#4076) 2024-06-03 09:13:42 -05:00
Winston Chang
248f19333c Bump cachem dependency. Closes #4032 2024-05-31 21:01:05 -05:00
Garrick Aden-Buie
306c4f847b feat(options): shiny.client_devmode (#4073) 2024-05-30 17:19:41 -04:00
Carson Sievert
e689cdc522 Close #4068: take opacity from last frame of animation (#4069) 2024-05-28 10:33:20 -05:00
Winston Chang
3e0efd8484 Update formatting settings (#4065)
* Format JSON files on save

* Add prettier plugin for organizing imports

* Reorganize imports

* Fix 'routine' build issues

* `yarn build` (GitHub Actions)

---------

Co-authored-by: wch <wch@users.noreply.github.com>
2024-05-24 09:37:28 -05:00
Carson Sievert
4a8400d2a5 Delay longer before dimming opacity when spinners are active (#4062)
* make sure to delay and transition the change in opacity when busy indicators are active

* better approach

* Fix

* Delay a touch longer
2024-05-23 11:52:02 -05:00
Carson Sievert
e432bb0592 Hide the busy pulse when disconnected (#4061) 2024-05-22 12:41:59 -05:00
Carson Sievert
d002734afe Follow up to #4057: remove unused JS files (#4060) 2024-05-21 15:21:27 -05:00
Carson Sievert
54e7377f24 Fade in spinner opacity after initial delay (#4058)
* Fade in spinner opacity after initial delay

* Slightly quicker fade in
2024-05-21 15:06:30 -05:00
Carson Sievert
a49d24108f Close #4056: Gut busy indicator logic to pulse up until 1st idle (#4057) 2024-05-20 17:57:19 -05:00
Garrick Aden-Buie
733a4e8983 fix(pulse): Remove radius from pulse (#4053) 2024-05-15 15:30:18 -04:00
Garrick Aden-Buie
6309a6fca3 tests(busyIndicatorOptions): set seed in the test without a helper (#4052) 2024-05-10 17:23:54 -04:00
Carson Sievert
3d66940402 Add busy indication (#4040)
* First pass at a proper state machine for managing output progress state

* `yarn build` (GitHub Actions)

* Add useBusyIndicators(), spinnerOptions(), and pulseOptions()

* Bring in new spinner defaults

* Use an actual div instead of a pseudo-element since chromium can't be trusted to show them when animated

* Revert "Use an actual div instead of a pseudo-element since chromium can't be trusted to show them when animated"

This reverts commit 6167c1dfd7.

* Embed animation inside svg (to avoid Chromium bug). Consolidate options into a singular busyIndicatorOptions()

* Add to pkgdown reference

* `devtools::document()` (GitHub Actions)

* `yarn build` (GitHub Actions)

* Bump version

* `yarn build` (GitHub Actions)

* Sync package version (GitHub Actions)

* Apply suggestions from code review

Co-authored-by: Garrick Aden-Buie <garrick@adenbuie.com>

* Update snapshots

* `devtools::document()` (GitHub Actions)

* Address feedback

* Bring in more spinner type options

* fix use of fs

* Code review

* `devtools::document()` (GitHub Actions)

* Sync package version (GitHub Actions)

* Update snapshots

* Fix comments

* Make snapshot consistent cross-platform

* Fix namespace issue

* Reduce specificity of position relative

* Skip snapshot on windows; update news

* Whoops

* Scope spinner customizations to parent element by default

* Update snapshots

* Reorder spinner types

* Set a private random seed in tests

* Better id naming

---------

Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
Co-authored-by: Garrick Aden-Buie <garrick@adenbuie.com>
2024-05-10 14:58:43 -05:00
Carson Sievert
2872c87e32 Allow for progress binding to move from Idle to Invalidated status (#4047)
* Close #4046: Allow for progress binding to move from Idle to Invalidated status

* `yarn build` (GitHub Actions)

---------

Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
2024-05-07 17:46:46 -05:00
Carson Sievert
ecb591f2e1 Disable downloadLink()/downloadButton() until their href is ready (#4041)
* Close #3606: disable downloadLink()/downloadButton() until their href has been populated

* Update news
2024-05-06 09:36:59 -05:00
Carson Sievert
8e37d45948 Improve/fix output progress reporting (#4039)
* First pass at a proper state machine for managing output progress state

* `yarn build` (GitHub Actions)

* Improved naming

* Include ascii version of diagram (as well as the source file

* Update srcts/src/shiny/outputProgress.ts

Co-authored-by: Joe Cheng <joe@rstudio.com>

* `yarn build` (GitHub Actions)

* Only call showProgress for outputs that have actually changed their recalculating status

* Add some more commentary

---------

Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
Co-authored-by: Joe Cheng <joe@rstudio.com>
2024-05-02 18:01:29 -05:00
Winston Chang
c11f120bb9 Change eslint-disable comments to eslint-disable-next-line (#4037)
* Change eslint-disable comments to eslint-disable-next-line

* Allow floating promise

* `yarn build` (GitHub Actions)

---------

Co-authored-by: wch <wch@users.noreply.github.com>
2024-04-30 13:19:48 -05:00
Winston Chang
950c63049b Check that $socket exists before sending message (#4035)
* Check that socket exists before sending message

* `yarn build` (GitHub Actions)

---------

Co-authored-by: wch <wch@users.noreply.github.com>
2024-04-26 15:21:35 -05:00
Carson Sievert
3edf9bfad8 Fix opacity dimming on recalculating uiOutput() (#4028)
* Close #4027: Fix opacity dimming on recalculating uiOutput(). Also, only apply display:content when there are child elements

* Update inst/www/shared/shiny_scss/shiny.bootstrap5.scss

* Add news item
2024-04-10 13:16:41 -05:00
Carson Sievert
420a2c054c Start new version (#4023)
* Start new version

* `yarn build` (GitHub Actions)

* Sync package version (GitHub Actions)

---------

Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
2024-04-03 10:03:31 -05:00
Carson Sievert
5e566a057d Start v1.8.1.1 release candidate (#4020)
* Start v1.8.1.1 release candidate

* `yarn build` (GitHub Actions)

* Sync package version (GitHub Actions)

* Remove alpha from npm version

---------

Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
2024-04-03 09:26:01 -05:00
Carson Sievert
edd1db78e3 Warn instead of error when duplicate binding IDs are found in non-devmode (#4019)
* Close #4016. Warn instead of error when duplicate binding IDs are found in non-devmode

* Get rid of unreachable ShinyClientError()

* `yarn build` (GitHub Actions)

* Update srcts/src/shiny/bind.ts

Co-authored-by: Garrick Aden-Buie <garrick@adenbuie.com>

* `yarn build` (GitHub Actions)

* Move logic to where error gets thrown not constructed

* `yarn build` (GitHub Actions)

* Update NEWS

---------

Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
Co-authored-by: Garrick Aden-Buie <garrick@adenbuie.com>
2024-03-29 13:51:46 -05:00
Joe Cheng
47526a769a ExtendedTask should not be cloneable (#4015) 2024-03-27 19:06:21 -05:00
Carson Sievert
0474eeeead Start new version (#4014)
* Start new version

* `yarn build` (GitHub Actions)

* Sync package version (GitHub Actions)

---------

Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
2024-03-27 10:10:45 -05:00
Carson Sievert
e8cdc78f0f v1.8.1 release candidate (#4008)
* Start v1.8.1 release candidate

* Update urls and yarn build

* Sync package version (GitHub Actions)

* Check-in revdep results

* Groom news

---------

Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
2024-03-27 10:01:08 -05:00
Carson Sievert
7742b652ba Fix and simplify reactlog's version check approach. (#4012)
* Close #4011. Fix and simplify reactlog's version check approach.

* Better variable name

* Use test_path() for consistent path location

* Just use packageDescription()

* Update tests/testthat/test-reactlog.R

* Update tests/testthat/test-reactlog.R

* Update DESCRIPTION
2024-03-22 17:39:52 -05:00
Carson Sievert
7ed68ed927 Revert changes to shinyDeprecated() & update renderDataTables() tests to always use shiny's datatables implementation (#4010)
* Revert "feat: Deprecate with warnings, expect `renderDataTable()` to be deprecated (#4007)"

This reverts commit a8c6065b9f.

* Use shiny's datatables implementation when testing
2024-03-22 17:35:15 -05:00
Garrick Aden-Buie
ac06350e08 chore: restyle new examples-shiny apps (#4004)
* chore: restyle examples-shiny

* chore: restore select newlines

* More consistent approach to whitespace

---------

Co-authored-by: Carson <cpsievert1@gmail.com>
2024-03-21 17:43:30 -05:00
Garrick Aden-Buie
43698f0860 feat: Run examples from any package (#4005)
* chore: `inst/shiny` -> `inst/examples-shiny`

* feat(runExamples): Find examples in any package

* refactor: code style

* refactor: small code style changes

* docs: fix runApp typo

* chore: include package name in valid examples message

* chore(runExample): check that `package` is installed

* chore: use braced package name

* Update news

---------

Co-authored-by: Carson Sievert <cpsievert1@gmail.com>
2024-03-21 12:07:57 -05:00
avoidaway
c73e1a21b8 chore: remove repetitive words (#3999)
Signed-off-by: avoidaway <cmoman@126.com>
2024-03-21 11:30:24 -05:00
Garrick Aden-Buie
d855468398 chore: inst/shiny -> inst/examples-shiny (#4003) 2024-03-21 10:58:50 -05:00
Garrick Aden-Buie
b8efd88448 docs(MockShinySession): document unhandled error param (#4006) 2024-03-21 10:58:27 -05:00
Garrick Aden-Buie
a8c6065b9f feat: Deprecate with warnings, expect renderDataTable() to be deprecated (#4007)
* feat: Deprecate with a warning

Use `rlang::warn()` instead of `rlang::inform()` and use the lifecycle warning class so that lifecycle infrastructure works

* tests: expect that renderDataTable is deprecated

* tests: invert warning and error expectation
2024-03-21 10:57:50 -05:00
Carson Sievert
12a8b228d9 Follow up to #3998: correct version requirement in message. (#4002) 2024-03-21 09:12:01 -05:00
Sara Altman
47fb562151 Update examples to use bslib (#3963)
* update 01_hello

* Updates 06_tabsets example to use bslib

* Pre-emptively adds legacy versions of all of the original examples

* Switches tabset example to use navset_card_underline()

* Updates example 2

* Updates 03_reactivity

* Updates 04_mpg

* Updates 05_sliders

* Updates 07_widgets

* Deletes 08_html_legacy. Original example does not need updated.

* Updates 09_upload

* Updates 10_download

* Updates 11_timer

* Keep inst/example unchanged; add new examples under inst/shiny and update runExamples() to use that directory by default

* Update news

* Fix some code formatting issues

* Update NEWS.md

* Don't default to showcase mode

---------

Co-authored-by: Garrett Grolemund <grolemund@gmail.com>
Co-authored-by: Carson <cpsievert1@gmail.com>
2024-03-20 16:04:58 -05:00
Carson Sievert
f0059b71e5 Use bs-danger instead of bs-danger-text-emphasis for text color on error messages (#4001) 2024-03-20 12:18:05 -05:00
Carson Sievert
89aaa977e8 Update datatables.js from 1.10.5 to 1.10.22 and deprecate renderDataTable()/dataTableOutput() (#3998)
* Update datatables.js from 1.10.5 to 1.10.22. Deprecate renderDataTable()/DTOutput()

* Update news; go back to old types version

* Clean up

* Update NEWS.md

* Update NEWS.md
2024-03-19 14:50:15 -05:00
Kirill Müller
ae308e03ad Avoid R package warning in loadSupport() if autoload is disabled (#3513)
* Avoid bogus warning

* refactor: source globals first, then deal with helpers

* refactor: Factor out `warn_if_app_dir_is_package()` for readability

* chore: simplify diff

* docs(news): Add news item

* Hint to help file in message.

Co-authored-by: Garrick Aden-Buie <garrick@adenbuie.com>

---------

Co-authored-by: Garrick Aden-Buie <garrick@adenbuie.com>
Co-authored-by: Carson Sievert <cpsievert1@gmail.com>
2024-03-15 15:50:35 -05:00
Garrick Aden-Buie
c1a1542cfe fix(updateSelectizeInput): Clear current value before update if selected and sever = TRUE (#3967)
* fix(updateSelectizeInput): Clear current value before update if `selected` and `server = TRUE`

Fixes #3966

* chore: yarn build

* `yarn build` (GitHub Actions)

* docs(news): Add news item

* chore: Add comments for future selves

Co-authored-by: Carson Sievert <cpsievert1@gmail.com>

* `yarn build` (GitHub Actions)

---------

Co-authored-by: gadenbuie <gadenbuie@users.noreply.github.com>
Co-authored-by: Carson Sievert <cpsievert1@gmail.com>
2024-03-14 09:56:06 -05:00
Garrick Aden-Buie
3c4a908773 feat: Add onUnhandledError() (#3993)
* feat: Add `onUnhandledError()`

* docs(NEWS): Update previous news item

* docs(onUnhandledError): Add example

* docs(MockShinySession): Fix unhandledErrorCallbacks private field docs

* feat: Handle non-fatal unhandled errors, too

* docs(onUnhandledError): Add more detailed documentation

* `devtools::document()` (GitHub Actions)

* docs: Small edits
2024-03-14 10:21:59 -04:00
Garrick Aden-Buie
e2b7f91138 feat: Add shiny.error.unhandled error handler (#3989)
* feat(shiny.error.unhandled): Allow users to provide an unhandled error handler

* Extract `shinyUserErrorUnhandled()` to use in MockSession too

* tests(shiny.error.unhandled): Test that unhandled errors are handled safely

* docs: Clarify that session still ends with an unhandled error

* docs: Add news item
2024-03-08 13:36:36 -06:00
Garrick Aden-Buie
c73978cdd5 docs: update roxygen2 (#3988)
* fix: `@docType "package"` is deprecated

* fix: S3 methods need `@export` or `@exportS3method` tag.

* chore: devtools::document()
2024-03-08 09:15:37 -06:00
Andreas Deininger
6760c31818 Documentation: fixing typos (#3932)
* Documentation: fixing typos

* Commit changes after generation of package docs
2024-02-02 16:53:48 -06:00
olivroy
781ceaaa5c Remove ellipsis dependency (#3959)
* Remove ellipsis dependency

* Use the above `@importfrom rlang`

* move usethis namespace
2024-02-02 16:52:39 -06:00
Fenno Vermeij
fff283648b fix(downloadButton): Return tag directly (#2672)
* Fix `downloadButton()` not rendering in rmarkdown documents

---------

Co-authored-by: Garrick Aden-Buie <garrick@adenbuie.com>
2024-01-30 17:31:40 -05:00
Winston Chang
f71f1256b8 Fix duplicate ID check logic (#3978)
* Fix duplicate ID logic

* Build shiny.js
2024-01-24 14:42:20 -06:00
Nick Strayer
f26b1335d8 Dev mode aware client and duplicate input/output ID handling updates (#3956)
* Add field with devmode status to the initial config object sent over on connection

* Add indicator of "devmode" status to the client via an injected script tag on load. This is modeled after what is done for showcase mode.

* Add logic to flag all duplicated IDs when in devmode

* Only show error console in devmode.

* Remove left-over devmode status in code

* `yarn build` (GitHub Actions)

* Build shiny.js

* `devtools::document()` (GitHub Actions)

* `yarn build` (GitHub Actions)

---------

Co-authored-by: nstrayer <nstrayer@users.noreply.github.com>
Co-authored-by: Winston Chang <winston@posit.co>
Co-authored-by: wch <wch@users.noreply.github.com>
2024-01-24 12:37:27 -06:00
Nick Strayer
370ba1f288 Make error console sizing constant across base and bslib apps (#3947)
* Add more encapsulated sizes using css variables instead of `rem` units so console is consistantly sized across apps that set the body font size.

* `yarn build` (GitHub Actions)

* `yarn build` (GitHub Actions)

* `devtools::document()` (GitHub Actions)

* `yarn build` (GitHub Actions)

---------

Co-authored-by: nstrayer <nstrayer@users.noreply.github.com>
Co-authored-by: jcheng5 <jcheng5@users.noreply.github.com>
Co-authored-by: Winston Chang <winston@posit.co>
Co-authored-by: wch <wch@users.noreply.github.com>
2024-01-22 14:17:10 -06:00
Joe Cheng
54988c17c8 Merge pull request #3958 from rstudio/extended-task
Add ExtendedTask R6 class
2024-01-11 09:11:58 -08:00
Joe Cheng
65fe23fa02 Don't take reactive dependency on rv_status() during invoke 2024-01-11 08:59:46 -08:00
Joe Cheng
b22b06e3d2 Add NEWS 2024-01-10 19:00:11 -08:00
Joe Cheng
3677f4e1c6 Add unit tests for maskReactiveContext 2024-01-10 19:00:11 -08:00
Joe Cheng
d6eb0493b3 Code review feedback 2024-01-10 19:00:11 -08:00
Joe Cheng
4e13cdb365 Realized we no longer care about the bslib version
Now that bind_task_to_button is gone to bslib, there's no specific
code in Shiny that cares about task buttons
2024-01-10 19:00:11 -08:00
Joe Cheng
4e3710cdaa Use correct remote 2024-01-10 19:00:11 -08:00
Joe Cheng
5feedaf4c8 Add Remotes for bslib 2024-01-10 19:00:11 -08:00
Joe Cheng
ce29695e44 Remove bind_button_to_task (moved to bslib::bind_task_button) 2024-01-10 19:00:11 -08:00
Joe Cheng
f0f06a2c34 Update bind_button_to_task to use newest task button API 2024-01-10 19:00:11 -08:00
Joe Cheng
860a3fef86 Rebuild 2024-01-10 19:00:11 -08:00
Joe Cheng
6afadade5d Add bind_button_to_task feature 2024-01-10 19:00:11 -08:00
jcheng5
c1bda7fb7b yarn build (GitHub Actions) 2024-01-10 19:00:11 -08:00
jcheng5
509c165ee8 devtools::document() (GitHub Actions) 2024-01-10 19:00:11 -08:00
Joe Cheng
54e0ef7598 Add ExtendedTask to pkgdown.yml 2024-01-10 19:00:11 -08:00
Joe Cheng
03f2d5f014 Add ExtendedTask R6 class 2024-01-10 19:00:11 -08:00
Garrick Aden-Buie
122c1e74cd refactor: pass-through containers in BS5 only (#3960) 2023-12-20 19:15:09 -05:00
Garrick Aden-Buie
d29f4cdf21 fix(ui-containers): Use display: contents (#3957) 2023-12-19 22:27:50 -05:00
Joe Cheng
300fb217d1 Merge pull request #3954 from rstudio/persistent-progress
Allow outputs to stay in progress mode after flush
2023-12-12 12:23:25 -08:00
Joe Cheng
33dc41c4bd Add disabled argument to actionButton and updateActionButton 2023-12-11 17:04:09 -08:00
Joe Cheng
4b6e257dfc Don't add progressKeys more than once
Doesn't matter much but this is closer to the old behavior
2023-12-07 09:22:01 -08:00
Joe Cheng
1f23f37f89 Allow outputs to stay in progress mode after flush
Adds a req(FALSE, cancelOutput="progress") which behaves similarly to
cancelOutput=TRUE, but also keeps the output in .recalculating state
even across flush cycles. This is called "persistent progress" and an
output can leave this state when it is invalidated again and doesn't
call req(FALSE, cancelOutput="progress") during that flush cycle.

This will be useful for implementing long-running tasks that don't
hold up the flush cycle, leaving sessions responsive to do other
tasks.
2023-12-06 09:30:58 -08:00
Garrick Aden-Buie
59b1c46485 fix: Allow bindInputs() to no-op when attempting to bind currently bound inputs (#3946)
* fix: Do not re-bind previously bound inputs

* refactor: Add binding to the registry after binding happens

* fix: Spelling of `bindingsRegistry`

* chore: yarn build

* `yarn build` (GitHub Actions)

* fix: spelling

* feat: isRegistered can check if bound to input or output

* fix: Do not throw for shared input/output IDs

`input$caption` and `output$caption` may not be the best idea for several reasons, but it was previously allowed

Fixes #3943

* fix: check element directly to know whether it a bound input

* chore: yarn build

* fix: test `.shiny-bound-input` instead of data prop

* refactor: Remove `bindingsRegistry.isRegistered()` method

* refactor: Use a map for duplicateIds again

* refactor: Add `BindingTypes` type and use `bindingType` everywhere

* refactor: More concise duplicateIds typing

Co-authored-by: Nick Strayer <nick.strayer@rstudio.com>

* refactor: count by forEach + incrementing

Co-authored-by: Nick Strayer <nick.strayer@rstudio.com>

* `yarn build` (GitHub Actions)

* thanks, vscode

* docs: rewrite checkValidity() jsdoc to capture current state of things

* chore: yarn build

* docs: slight rewording

---------

Co-authored-by: gadenbuie <gadenbuie@users.noreply.github.com>
Co-authored-by: Nick Strayer <nick.strayer@rstudio.com>
2023-11-30 15:46:28 -06:00
Garrick Aden-Buie
01705c1299 fix(shiny.scss): Constrain notification panel to max-width: 100% (#3949) 2023-11-30 16:11:22 -05:00
Carson Sievert
18955a2abf Update tabPanel() snapshot tests in anticipation of bslib release (#3936)
Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
2023-11-29 15:38:48 -06:00
Nick Strayer
dbbe7f9679 Client error console and duplicate input/output binding errors (#3931)
Co-authored-by: nstrayer <nstrayer@users.noreply.github.com>
Co-authored-by: Winston Chang <winston@stdout.org>
2023-11-27 12:34:13 -06:00
Carson Sievert
61a51a869f Run yarn build (#3942)
Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
2023-11-20 13:32:32 -06:00
Carson
298822fc44 Start new version 2023-11-20 12:57:08 -06:00
Carson Sievert
283c71e772 v1.8.0 release candidate (#3928) 2023-11-20 12:55:11 -06:00
Carson Sievert
b1297395a9 Don't treat input/output as draggable inside of absolutePanel(draggable = T) (#3937) 2023-11-01 10:42:19 -05:00
Carson Sievert
b850cd2509 Change selectize.js selectOnTab option back to false (#3935)
Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
2023-10-31 16:45:35 -05:00
Carson Sievert
56878ebbaa Revert Shiny.renderContent() back to sync instead of async (#3929)
Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
2023-10-30 12:59:22 -05:00
Winston Chang
6a09fda08e Allow InputBinding.receiveMessage to be async (#3930)
Co-authored-by: wch <wch@users.noreply.github.com>
2023-10-30 11:26:04 -05:00
Carson Sievert
77bc4e9ec7 Update selectInput's binding to use selectize.js' getValue() method when relevant (#3926)
Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
2023-10-26 18:21:40 -05:00
Carson Sievert
a1b9fda809 Prevent .selectize() updates from destroying .data() and event listeners (#3923)
Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
2023-10-26 17:42:06 -05:00
Garrick Aden-Buie
97a12ec601 fix(shiny.scss): Ensure $body-emphasis-color is defined for all BS5 (#3924) 2023-10-26 14:36:49 -05:00
Winston Chang
81bdde64c4 Convert bindAll to an async function (#3904)
Co-authored-by: Carson <cpsievert1@gmail.com>
Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
2023-10-24 16:01:47 -05:00
Garrick Aden-Buie
c4ef42337b feat: Improve notification styles (#3913)
Co-authored-by: gadenbuie <gadenbuie@users.noreply.github.com>
Co-authored-by: Carson <cpsievert1@gmail.com>
Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
2023-10-20 10:55:23 -05:00
Carson Sievert
ce78d0dcf1 Fix selectize event namespacing issues (#3919)
Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
2023-10-20 10:21:29 -05:00
Carson Sievert
7069064dd6 Add non-minified selectize.js source; and respect shiny.minified option (#3918) 2023-10-19 18:38:30 -05:00
Carson Sievert
a0a83d5fe3 Merge pull request #3914 from rstudio/chore/shiny-sass-bs-3-4-5 2023-10-19 16:40:59 -05:00
Garrick Aden-Buie
8fbc4ad4c1 Merged origin/main into chore/shiny-sass-bs-3-4-5 2023-10-19 17:31:30 -04:00
Garrick Aden-Buie
5346a00373 docs: Add news item 2023-10-19 17:30:59 -04:00
Garrick Aden-Buie
2dc69aea37 chore(shiny-sass): Remove comments 2023-10-19 17:27:08 -04:00
Joe Cheng
be6f6716bf Merge pull request #3915 from rstudio/autoreload-indication
Soften visually jarring greyout when autoreloading
2023-10-18 12:23:47 -07:00
Joe Cheng
7f59f93692 Only show the lighter curtain if autoreload is on
I added this cause I'm slightly worried about other server environments
sending the same 1012 close code.
2023-10-16 17:58:02 -07:00
Joe Cheng
798b336df6 Make autoreload survive laptop suspend
Also simplify the implementation for softening the grey curtain when
autoreload is in progress (only applies to Shiny for Python)
2023-10-16 17:39:55 -07:00
Joe Cheng
bef6b4bfd9 Soften visually jarring greyout when autoreloading
This change detects when Shiny is autoreloading, and instead of
showing the typical disconnection treatment (dark grey), it
initially shows nothing and then quickly fades to very light
grey.

The goal is for instant autoreloads to feel seamless, but longer
autoreloads to make it clear when the autoreload has completed,
and still not feel as jarring as a full disconnect.
2023-10-16 17:39:55 -07:00
Carson Sievert
80ab088e2d Merge pull request #3910 from rstudio/rc-v1.7.5.1 2023-10-16 12:22:58 -05:00
Carson
481a692b07 Merge branch 'main' into rc-v1.7.5.1 2023-10-16 10:01:18 -05:00
Garrick Aden-Buie
8ae936ba01 feat(shiny-scss): Create variable defaults specific to the Bootstrap version 2023-10-11 11:59:08 -04:00
Garrick Aden-Buie
6dc377842f Revert shiny bootstrap sass back to pre-BS 5.3
Reverts back to commit f540679513
2023-10-11 11:06:11 -04:00
Carson
837307fe8c Remove alpha from the npm version 2023-10-06 09:52:39 -05:00
Carson
dfe359c1b6 shiny v1.7.5.1 2023-10-05 18:42:03 -05:00
Carson Sievert
b8923e9497 Address r-devel's change in is.atomic(NULL) behavior (#3908) 2023-10-03 10:54:55 -05:00
Winston Chang
9ebcbf8a2d wrapFunctionLabel: handle case when name is >10000 bytes (#3903)
Co-authored-by: Carson Sievert <cpsievert1@gmail.com>
2023-09-27 10:38:28 -05:00
Carson Sievert
a6fc6bf8cb Update to the development version of selectize.js (#3897)
Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
2023-09-14 19:02:31 -05:00
Carson Sievert
eddc3047d4 Fix regression in updateSelectizeInput() (#3890)
Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
2023-09-08 16:48:48 -05:00
Carson Sievert
6db17d4f67 Ensure Sass variables are defined for Bootstrap 3 Sass (#3892) 2023-09-08 10:39:25 -05:00
Winston Chang
d21f9493fb Update fileInput help page (#3886)
Co-authored-by: wch <wch@users.noreply.github.com>
2023-09-01 15:27:28 -05:00
Carson Sievert
e87f942e89 Update Shiny's CSS to respect BS5's dark color mode (#3882)
Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
2023-08-28 15:11:01 -05:00
Carson Sievert
1eb9ed7345 Upgrade to selectize.js 0.15.2 (#3875)
Co-authored-by: Garrick Aden-Buie <garrick@adenbuie.com>
Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
2023-08-28 14:59:43 -05:00
Carson Sievert
9d923d079a fileInput()'s button shouldn't have top-right or bottom-right border-radius (#3879) 2023-08-24 09:07:11 -05:00
Carson Sievert
b054e45402 Update staticimports (#3872) 2023-08-15 11:40:19 -05:00
Carson Sievert
8b1d30aefe use_dev_version() (#3871)
Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
2023-08-14 12:53:12 -05:00
Carson
ab87a0708d use_dev_version() 2023-08-14 09:56:22 -05:00
Carson Sievert
0b97ee1ecc 1.7.5 release candidate (#3867)
Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
2023-08-14 09:49:46 -05:00
Garrick Aden-Buie
68546c319e Increase touch target area of slider input (#3859) 2023-08-07 15:14:35 -04:00
Garrick Aden-Buie
69188fef22 chore(desc): Add GitHub repo to URL (#3864) 2023-08-03 13:20:33 -04:00
Garrick Aden-Buie
6be6dfbfeb Finer-grained control over shiny-provided input bindings (#3861)
Co-authored-by: Carson Sievert <cpsievert1@gmail.com>
Co-authored-by: Joe Cheng <joe@rstudio.com>
Co-authored-by: gadenbuie <gadenbuie@users.noreply.github.com>
2023-07-31 10:41:27 -05:00
Garrick Aden-Buie
6fc06281bd docs(navbarPage): Be less specific about collapsible breakpoint (#3853) 2023-07-07 10:42:39 -04:00
Barret Schloerke
f724128d41 Merge pull request #3850 from rstudio/rc-v1.7.4.1 2023-07-07 09:56:25 -04:00
Barret Schloerke
518ef0f9f8 Merge branch 'main' into rc-v1.7.4.1
* main: (55 commits)
  Catch errors receiving individual input messages (#3843)
  Clarify what's ignored by ignoreNULL (#3827)
  Remove tests/testthat/apps/ (#3841)
  Correctly set width on `textarea` input element (#3838)
  Update selectize.js documentation URLs (#3836)
  test(json digits): Try unsetting option in test to get default behavior (#3837)
  Rebuild docs
  Update README.md
  fix typo in the docs for bindCache (#3825)
  Allow for `shiny:::toJSON()` to respect if `digits` has class `AsIs` to represent `use_signif=` (#3819)
  More complete `downloadButton()` example
  Rename actionQueue to taskQueue, add more context to the NEWS item (#3801)
  Remove unneeded packages from package.json
  Rebuild docs
  Rebuild shiny.js
  Update @types/node
  Rebuild yarn.lock
  Fix brush resetting behavior. Closes #3785
  Bump fastmap dependency to 1.1.1
  Sync package version (GitHub Actions)
  ...
2023-07-07 09:39:01 -04:00
Winston Chang
f5b395485e shiny v1.7.4.1
Remove use of as.numeric_version()
Closes #3849
2023-07-07 09:33:14 -04:00
Garrick Aden-Buie
31aca7aa70 Catch errors receiving individual input messages (#3843) 2023-06-30 17:10:17 -04:00
Garrick Aden-Buie
b38a630224 Clarify what's ignored by ignoreNULL (#3827)
Co-authored-by: gadenbuie <gadenbuie@users.noreply.github.com>
2023-06-30 10:44:43 -04:00
Winston Chang
1b7709411b Remove tests/testthat/apps/ (#3841) 2023-06-16 16:55:14 -05:00
Garrick Aden-Buie
2b48aa0d91 Correctly set width on textarea input element (#3838)
Co-authored-by: gadenbuie <gadenbuie@users.noreply.github.com>
2023-06-12 15:57:49 -04:00
Viviane Girardin
6fdf23752e Update selectize.js documentation URLs (#3836)
Co-authored-by: Neal Richardson <neal.p.richardson@gmail.com>
Co-authored-by: Winston Chang <winston@stdout.org>
2023-06-09 15:43:21 -05:00
Barret Schloerke
8542f5d017 test(json digits): Try unsetting option in test to get default behavior (#3837) 2023-06-09 15:30:02 -05:00
Winston Chang
e7b830755a Rebuild docs 2023-06-01 15:44:18 -05:00
Gordon Shotwell
23c7b0683a Update README.md
Add Discord link
2023-06-01 15:43:20 -05:00
Tom Jemmett
5805895581 fix typo in the docs for bindCache (#3825) 2023-05-23 08:52:42 -05:00
Barret Schloerke
90539bff25 Allow for shiny:::toJSON() to respect if digits has class AsIs to represent use_signif= (#3819) 2023-05-16 16:14:03 -04:00
Winston Chang
62bb21d5b6 Merge pull request #3804 from rstudio/docs/ex-download-button 2023-04-14 15:48:19 -05:00
Garrick Aden-Buie
4f85268d44 More complete downloadButton() example 2023-04-13 09:04:40 -04:00
Carson Sievert
611e517bb8 Rename actionQueue to taskQueue, add more context to the NEWS item (#3801) 2023-03-31 14:38:28 -05:00
Winston Chang
4d05a568c1 Remove unneeded packages from package.json 2023-03-06 17:01:43 -06:00
Winston Chang
1330325519 Rebuild docs 2023-03-01 21:38:10 -06:00
Winston Chang
92d850efa6 Rebuild shiny.js 2023-03-01 21:26:59 -06:00
Winston Chang
7bf56125eb Update @types/node 2023-03-01 21:26:59 -06:00
Winston Chang
69f861cc8a Rebuild yarn.lock 2023-03-01 21:20:56 -06:00
Winston Chang
a94be7b128 Fix brush resetting behavior. Closes #3785 2023-03-01 20:58:26 -06:00
Winston Chang
703766fb2e Merge pull request #3782 from rstudio/plot-interact-init 2023-02-24 16:59:42 -06:00
Winston Chang
8e73749e21 Bump fastmap dependency to 1.1.1 2023-02-24 10:30:07 -06:00
wch
dc8ffa115b Sync package version (GitHub Actions) 2023-02-23 20:32:23 +00:00
Winston Chang
a0385da0d7 Rebuild shiny.js 2023-02-23 14:18:21 -06:00
Winston Chang
a6b7dee4cd Send initial values for plot interaction 2023-02-23 14:14:01 -06:00
Winston Chang
f9ff5c2637 Bump version to 1.7.4.9002 2023-01-25 11:19:40 -06:00
Winston Chang
6a1fbc57f4 Clarify comments 2023-01-25 11:18:20 -06:00
Winston Chang
38337a926f Ensure that reactiveValues keys and values are sorted (#3774) 2023-01-25 11:10:05 -06:00
Winston Chang
bf6b87886c Merge pull request #3775 from rstudio/map-loadtime 2023-01-24 13:55:37 -06:00
Winston Chang
33e6b0a305 Add on_load function for registering expressions to run on load 2023-01-23 17:25:26 -06:00
Winston Chang
cb5eac052f Initialize Map objects at load time instead of build time 2023-01-23 16:26:44 -06:00
Winston Chang
39fee3782f Merge pull request #3772 from rstudio/fix-slider-stoppropagation 2023-01-23 10:59:47 -06:00
Winston Chang
654f30a312 Udpate NEWS 2023-01-20 17:04:21 -06:00
Winston Chang
a763da2b94 Fix stopPropagation error in ion.rangeSlider 2023-01-20 17:00:12 -06:00
Jon Calder
0c177d30dc Fix two typos in insertUI() docs (#3712)
* Fix two typos in insertUI() docs

* document()

Co-authored-by: Carson Sievert <cpsievert1@gmail.com>
2023-01-13 11:41:44 -06:00
gsmolinski
20f8a181d4 Change size 'xl' of modalDialog to 'l' if Bootstrap 3 (#3593)
* closes issue #3631 - documenting that 'xl' modal dialog will be changed to 'm' in Bootstrap 3

* Update R/modal.R

adds note about how to switch to Bootstrap 4+ with bslib

Co-authored-by: Carson Sievert <cpsievert1@gmail.com>

* add note about how to use Bootstrap 4+ with bslib to get 'xl' modal dialog

* Update NEWS.md

Co-authored-by: Carson Sievert <cpsievert1@gmail.com>
2023-01-12 11:41:49 -06:00
Carson Sievert
eebcf70bb9 Add snapshot test for #3519 (#3520)
* Add snapshot test for https://github.com/rstudio/shiny/issues/3519 which was fixed via https://github.com/rstudio/bslib/pull/372

* sync package version (GitHub Actions)

* yarn build (GitHub Actions)

* `yarn build` (GitHub Actions)

* Sync package version (GitHub Actions)

Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
2023-01-12 10:38:06 -06:00
Winston Chang
e7d62f55ca Merge pull request #3666 from rstudio/async-load-script-2 2023-01-06 13:47:52 -08:00
Winston Chang
3a4e5f3982 Rebuild JS and CSS 2023-01-06 15:40:58 -06:00
Winston Chang
3381c3a6b9 Bump version to 1.7.4.9001 2023-01-06 15:39:42 -06:00
Winston Chang
e42c920587 Merge branch 'main' into async-load-script-2 2023-01-06 15:39:19 -06:00
Winston Chang
4635665394 Build shiny.js 2022-12-22 11:53:29 -06:00
Winston Chang
08ff066fa3 Append script elements one at a time 2022-12-22 11:53:13 -06:00
Winston Chang
816072fc29 Use Promise.allSettled 2022-12-21 16:40:45 -06:00
Carson Sievert
5eb442aa03 Make ?shiny-package topic internal in pkgdown (#3758)
* Make ?shiny-package help page internal

Otherwise, pkgdown wants it to appear in the reference, which we probably don't want

* Revert "Make ?shiny-package help page internal"

This reverts commit 4ab4cb0e46.

* Use pkgdown's  to drop the shiny-package contents (only in the pkgdown reference)

* Avoid 'incomplete final line' warning when reading pkgdown.yml
2022-12-16 10:05:12 -06:00
Carson Sievert
c32db50585 Run yarn build (#3757)
* Run yarn build

* `devtools::document()` (GitHub Actions)

* Sync package version (GitHub Actions)

Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
2022-12-15 11:37:11 -06:00
Carson Sievert
1d9dde52df Start new version (#3756) 2022-12-15 11:16:28 -06:00
Carson Sievert
6176f03ad0 v1.7.4 release candidate (#3749)
* Start release candidate

* Get rid of warnings about qplot() usage in tests

* Clean up news

* `yarn build` (GitHub Actions)

* Sync package version (GitHub Actions)

* Remote remotes (htmltools is now in CRAN)

* Change header syntax in NEWS.md (to match what usethis does)

Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
2022-12-15 11:12:19 -06:00
Winston Chang
0fc1be52eb Render deps before modal or notification element is created 2022-12-13 17:21:59 -06:00
Carson Sievert
f12334e839 Properly check for NaN values upon resizing a brushable image. (#3754)
Regression introduced by https://github.com/rstudio/shiny/pull/3644/files#diff-9aad79e444091956075dc1e1dc5ab9202b5e998f5d441e69f040319b6c00d100L228-L230

JS error discovered by 104-plot-interaction-select (with showcase mode)
2022-12-08 14:32:27 -06:00
Winston Chang
ffb6736f11 Don't add "use strict" to external libraries (#3746)
* Add missing var in loop

* `yarn build` (GitHub Actions)

Co-authored-by: wch <wch@users.noreply.github.com>
2022-12-06 14:17:36 -06:00
Winston Chang
f084d3a34f Merge pull request #3747 from rstudio/eslint-newline-after-var
Remove eslint `newline-after-var rule`
2022-12-06 13:07:43 -06:00
Winston Chang
0fe7cad876 Remove eslint newline-after-var rule 2022-12-05 16:34:23 -06:00
Carson Sievert
ecff638920 Don't supply width/height to the device if they aren't defined (#3740)
* Close #1409: don't supply width/height to the device if they aren't defined

* Update news

* Update unit tests to reflect that plotPNG()/startPNG() now handles NULL dimensions

* Add a note about NULL dimensions on plotPNG() help page

* Update news
2022-12-02 20:27:07 -06:00
Winston Chang
db2ad780c0 Don't ignore errors when loading or executing a script 2022-12-01 17:16:59 -06:00
Winston Chang
5cd848bd28 Await running each action in actionQueue 2022-12-01 17:01:00 -06:00
Carson Sievert
ed6022e3f2 Have renderPlot() error early if height/width of a plot aren't yet defined (#3739)
* Close #3704. Close #3735. Close #1409. Throw informative error in renderPlot() early if height/width of a plot aren't yet defined

* `devtools::document()` (GitHub Actions)

* Add unit tests

* Use consistent filename; add intentional failure (to get artifact uploads)

* Make output id argument name more unique

* Update news

* plotPNG() test isn't worth it

* Don't try to provide a suggestion on how to fix the issue (it's no worse than what we currently have, and we probably should be defaulting to an 'arbitrary' size anyway

* update news

* minimize diff

Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
2022-11-22 17:23:19 -06:00
Winston Chang
a063540407 Build shiny.js 2022-11-01 21:30:29 -05:00
Winston Chang
aa932532f3 Add sync and async versions of renderContent, renderHtml, renderDependencies 2022-11-01 21:30:15 -05:00
Winston Chang
8160f8c726 Add .d.ts files 2022-10-31 16:51:13 -05:00
Winston Chang
af900d1037 Use actionQueue 2022-10-31 16:51:13 -05:00
Winston Chang
49320e6edd Make HtmlOutputBinding.renderValue an async function 2022-10-31 16:51:13 -05:00
Winston Chang
4308887296 Fix types for message.multiple 2022-10-31 16:51:13 -05:00
Winston Chang
dffd8bc7fd Commit .d.ts files 2022-10-31 16:51:13 -05:00
Winston Chang
554f835293 Make sure not to send input values during dispatchMessage 2022-10-31 16:51:13 -05:00
Winston Chang
50e7b6768d Use async queue to handle incoming messages 2022-10-31 16:51:13 -05:00
Winston Chang
db222af7e0 Make sure dynamic scripts run in order 2022-10-31 16:51:13 -05:00
Winston Chang
5b688707b7 Add await for renderContent() calls 2022-10-31 16:51:13 -05:00
Winston Chang
8dfd8f5b33 Convert renderDependency() to async 2022-10-31 16:51:13 -05:00
Carson Sievert
20cc8e26b5 Use getBoundingClientRect() over offsetHeight/offsetWidth to get more precise sizing (#3720)
* Use getBoundingClientRect() over offsetHeight/offsetWidth to get more precise sizing

* Update news
2022-10-28 15:55:24 -05:00
Carson Sievert
e48e9c6904 Add fill arguments to plotOutput(), imageOutput(), and uiOutput() (#3715)
* Add fill arguments to plotOutput(), imageOutput(), and uiOutput()

* Update news

* Code review

* `devtools::document()` (GitHub Actions)

* `yarn build` (GitHub Actions)

* Sync package version (GitHub Actions)

* Update news

* Update to use bindFillRole()

Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
2022-10-26 11:52:26 -05:00
Joe Cheng
87c673f283 Bump version to v1.7.3.9000 2022-10-25 18:01:14 -07:00
Joe Cheng
dfaefa8905 Merge tag 'v1.7.3' 2022-10-25 17:59:18 -07:00
Joe Cheng
cd4f406234 Squelch R CMD check message
"Package has help file(s) containing install/render-stage \Sexpr{} expressions but no prebuilt PDF manual."
2022-10-24 18:37:15 -07:00
Joe Cheng
190b542613 Use v1.7.3 instead
Something in our yarn build toolchain doesn't like version numbers
with 4 segments
2022-10-24 16:54:54 -07:00
Joe Cheng
73e48ab5f4 Remove Remotes, add NEWS item 2022-10-24 16:22:42 -07:00
Barret Schloerke
62a95b9ce2 Reverting selectize logic change from #3644 (#3716) 2022-10-24 12:18:00 -04:00
Barret Schloerke
999eb1de3c Add fontawesome remote 2022-10-21 15:47:39 -04:00
Barret Schloerke
55985740de Skip template tests even if shinytest2 is available. Install shinytest2 from CRAN
We will bring these tests back after this release.
We will move shinytest2 to suggests after this release
2022-10-21 15:30:00 -04:00
Barret Schloerke
e82b71da65 Update template code to work with latest shinytest2 2022-10-21 14:54:05 -04:00
Joe Cheng
9ce1e6c549 Fix unit test to be compatible with fontawesome 0.4.0 2022-10-21 11:05:04 -07:00
Winston Chang
cda59da698 Remove types-jquery.patch (#3710)
Co-authored-by: wch <wch@users.noreply.github.com>
Co-authored-by: Barret Schloerke <schloerke@gmail.com>
2022-10-05 10:50:19 -04:00
Winston Chang
51da80d381 Merge pull request #3709 from rstudio/blob 2022-10-03 12:36:29 -05:00
wch
412606c594 yarn build (GitHub Actions) 2022-10-03 17:26:14 +00:00
Winston Chang
da2df5ac58 Use correct type for messages 2022-10-03 12:20:59 -05:00
Winston Chang
98f17e0cd2 Disable eslint rules only within scope 2022-10-03 11:41:28 -05:00
Winston Chang
9b2c04f298 Remove redundant setting 2022-09-30 19:57:03 -05:00
Winston Chang
ed4a97154d Remove makeBlob
Blob has long been available on all major browsers, so makeBlob is no longer needed.
2022-09-30 16:29:38 -05:00
Winston Chang
9dcd62f944 Update eslint 2022-09-30 16:17:19 -05:00
Winston Chang
213c645524 Upgrade esbuild and typescript 2022-09-30 15:59:24 -05:00
Winston Chang
f1c0ac2b30 Upgrade to yarn 3.2.3 2022-09-30 15:57:51 -05:00
Barret Schloerke
16c6d55f60 Enable TypeScript strict mode (#3644) 2022-09-29 16:03:05 -04:00
Hedley
6e40a3dd39 Update jQuery-UI to 1.13.2 (#3697) 2022-09-21 10:34:51 -04:00
Joe Cheng
04ad1453c1 Merge pull request #3694 from rstudio/rook-doc-link
Add link to Rook spec from docs
2022-09-07 17:38:36 -07:00
jcheng5
80eeff68ab Sync package version (GitHub Actions) 2022-09-07 14:27:51 -07:00
jcheng5
6128a3ab65 yarn build (GitHub Actions) 2022-09-07 20:43:50 +00:00
Joe Cheng
5f25537079 Add link to Rook spec from docs 2022-09-07 13:37:37 -07:00
Winston Chang
c21ba0baca Bump version to 1.7.2.9000 2022-07-19 09:18:16 -05:00
Winston Chang
ebf786c2eb Merge tag 'v1.7.2'
Shiny 1.7.2 on CRAN
2022-07-19 09:16:45 -05:00
wch
b39ffafea9 devtools::document() (GitHub Actions) 2022-07-19 00:16:11 +00:00
Winston Chang
4441945a68 Use inherits() instead of if(class(x)==y) 2022-07-18 19:11:24 -05:00
Winston Chang
cd95e058e6 Remove URL because CRAN doesn't like it 2022-07-18 19:11:24 -05:00
Winston Chang
a0144d77ef Remove broken link 2022-07-18 19:11:24 -05:00
Carson
64cec08a74 Check in most recent revdep results 2022-07-08 11:53:50 -05:00
Winston Chang
7a77b55e6a Merge branch 'main' into rc-v1.7.2 2022-07-05 20:08:10 -05:00
Winston Chang
54e5a6b43c Merge branch 'dvg-p4-fix-throttle' 2022-07-05 20:03:22 -05:00
Winston Chang
9653cc2893 Rebuild shiny.js 2022-07-05 20:01:22 -05:00
Winston Chang
47dc5b4116 Code and comment cleanup 2022-07-05 19:37:44 -05:00
dvg-p4
9db9ef527a Fixed check for isPending and rebuilt javascript 2022-07-04 10:21:22 -04:00
dvg-p4
9285a1f7fc Update srcts/src/time/throttle.ts
Based on suggestion

Co-authored-by: Winston Chang <winston@stdout.org>
2022-07-01 19:02:26 -04:00
dvg-p4
d22eb1524a Updated NEWS.md 2022-07-01 17:15:09 -04:00
dvg-p4
5e3971c776 Fixed major bug in throttle.ts 2022-07-01 16:58:41 -04:00
Carson
dbe4896102 Merge branch 'main' into rc-v1.7.2 2022-06-27 12:12:55 -05:00
Joe Cheng
ff5ef52dd5 Fix #3250 (#3602)
* Fix #3250

pruneStackTrace was interacting badly with dplyr errors. I'm still
not sure what causes these new cases, but the new behavior seems to
be much better, with no downside that I can think of.

* Fix existing unit tests

* Update news

Co-authored-by: Carson Sievert <cpsievert1@gmail.com>
2022-06-27 12:05:28 -05:00
Joe Cheng
634b1c7c3c Don't kill the session when a debounced/throttled reactive expr errors (#3624)
* Don't kill the session when a debounced/throttled reactive expr errors

Fixes #3581

* Update NEWS with PR number

Co-authored-by: Carson Sievert <cpsievert1@gmail.com>
2022-06-27 10:57:10 -05:00
Carson
1c9f8940a9 Merge branch 'main' into rc-v1.7.2 2022-06-24 17:53:49 -05:00
Carson Sievert
d4527cdc28 Use ragg::agg_png over Cairo::CairoPNG if available (#3654)
* Close #3626: use ragg::agg_png over Cairo::CairoPNG if available

* Update documentation
2022-06-24 17:50:58 -05:00
cpsievert
514206850a Sync package version (GitHub Actions) 2022-06-14 15:43:58 +00:00
cpsievert
809bc8c6de yarn build (GitHub Actions) 2022-06-14 15:42:16 +00:00
cpsievert
0d720616f3 devtools::document() (GitHub Actions) 2022-06-14 15:39:35 +00:00
Carson
0c325d422f Groom NEWS.md 2022-06-14 10:35:36 -05:00
Carson
d368aa72c3 Update URLs 2022-06-14 10:35:36 -05:00
Carson
27e1348dcb Start v1.7.2 release candidate 2022-06-14 10:35:36 -05:00
Carson Sievert
474f14003b Follow up to #3385: warn instead of message; update unit tests to reflect some parameters can now succeed when others fail (#3652) 2022-06-14 10:34:20 -05:00
Carson Sievert
8a5da25545 Fix/update news (#3651) 2022-06-14 09:18:51 -05:00
Barret Schloerke
540d68ed9f Update the _inputs_ and _values_ regular expr to support a trailing = (#3648) 2022-06-10 11:39:12 -04:00
Khaled Al-Shamaa
1ad49b153c Enable fileInput to set the capture attribute (#3481)
Co-authored-by: Barret Schloerke <barret@rstudio.com>
Co-authored-by: Barret Schloerke <schloerke@gmail.com>
Co-authored-by: Winston Chang <winston@stdout.org>
2022-06-10 10:30:34 -05:00
Winston Chang
15885cbb5f Update NEWS 2022-06-10 10:07:00 -05:00
Dean Attali
b6979d135c fix bookmarking bug #2297: don't break all bookmarking system if some URL params don't parse correctly (#3385)
Co-authored-by: Barret Schloerke <barret@rstudio.com>
2022-06-10 10:04:47 -05:00
Winston Chang
d4b19820a4 Update NEWS 2022-06-10 10:02:30 -05:00
Dieter Menne
8d529095a7 Corrected for stricter length checking in R 4.2.0 (#3625)
* Corrected for stricter length checking in R 4.2.0

* Update R/bootstrap-layout.R

Fine! I had thought of that case, but could not find that elegant solution

Co-authored-by: Carson Sievert <cpsievert1@gmail.com>

Co-authored-by: Carson Sievert <cpsievert1@gmail.com>
2022-06-10 09:59:14 -05:00
Winston Chang
77f9052ab5 Make mathjax configurable (#3650)
Co-authored-by: Neutron3529 <qweytr_1@163.com>
Co-authored-by: Joe Cheng <joe@rstudio.com>
2022-06-10 09:57:02 -05:00
Ryan Barnard
9fcc1fe8ad Fixed automatic guessing of Content-Type in downloadHandler (#3393)
* Set default downloadHandler contentType to NULL.

The change from %OR% to %||% broke automatic guessing of content type
since `NA %||% ...` evaluates to `NA`. Setting the default contentType
to NULL restores the previous behavior of automatically setting the
content type based on the file extension.

* Updated NEWS.md: downloadHandler contentType fix.

* Update NEWS.md

Co-authored-by: Winston Chang <winston@stdout.org>
Co-authored-by: Barret Schloerke <barret@rstudio.com>
2022-06-10 09:39:00 -05:00
Barret Schloerke
5d30b55372 Spelling defintion -> definition (#3649) 2022-06-09 16:52:27 -04:00
Carson Sievert
78d77ce373 insertUI() now supports execution of <script> (#3630) 2022-05-10 11:43:21 -05:00
Joe Cheng
2cae04186b Merge pull request #3628 from rstudio/joe/feature/autoreload-custom-url
Add ability for autoreload ws to be at a custom URL
2022-05-04 16:35:39 -07:00
Joe Cheng
59bddea1e9 Use external, not internal, sourcemaps for extras 2022-05-04 16:23:48 -07:00
Joe Cheng
d6bd3d9f9b Add ability for autoreload ws to be at a custom URL 2022-05-04 09:05:53 -07:00
Joe Cheng
8eb7b056f2 devmode should activate autoreload (#3620)
devmode should activate autoreload

It said it didn't, but until this commit, it appeared not to
2022-04-27 13:51:02 -07:00
Barret Schloerke
40ae9a903e Spelling (#3618) 2022-04-23 12:25:11 -04:00
Barret Schloerke
5b6c80d4b2 Update shinyAppTemplate() content to use {shinytest2} (#3599) 2022-04-22 16:10:11 -04:00
Dean Attali
fd7518018c Update internal docs: reexports.yml -> reexports.json (#3522) 2022-03-11 11:59:35 -05:00
Kathryn Doering
5c03326a8c Use HEAD for ref instead of master in runGitHub() (#3564)
Co-authored-by: Kathryn Doering <kathryn.doering@noaa.gov>
2022-02-14 15:53:33 -05:00
Barret Schloerke
2c82ee0235 Bump dev version (#3588) 2022-02-14 15:24:47 -05:00
Barret Schloerke
ac84be956a Opt-in to C collate order in test snapshots (#3515) 2022-02-14 14:12:25 -05:00
Winston Chang
0fb154cc1e Trigger input event even when there is no input binding (#3584)
Co-authored-by: Winston Chang <winston@stdout.org>
Co-authored-by: Barret Schloerke <schloerke@gmail.com>
2022-02-14 13:45:59 -05:00
Carson Sievert
837e8d33f6 Update stack trace test expectations (#3550) 2022-02-14 13:14:10 -05:00
Winston Chang
3365bfc395 Merge pull request #3583 from ismirsehregal/main 2022-02-09 17:27:18 -06:00
ismirsehregal
135fe21278 Update runapp.R
Fixed typo
2022-02-09 15:11:34 +01:00
Carson Sievert
fc7e237000 Pass args from knit_print.shiny.render.function() down to it's use of the knit_print() generic (#3569)
Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
Co-authored-by: Barret Schloerke <barret@rstudio.com>
Co-authored-by: schloerke <schloerke@users.noreply.github.com>
2022-01-11 12:21:18 -06:00
Winston Chang
de8134742d Update NEWS 2022-01-11 10:41:19 -06:00
Winston Chang
f814034835 Merge pull request #3570 from romainfrancois/shinyActionButtonValue 2022-01-11 10:38:28 -06:00
Romain Francois
6d9fad29f3 put the extension class on the left.
from: https://github.com/tidyverse/dplyr/issues/6154
2022-01-11 12:49:48 +01:00
Lionel Henry
313ae9044d Handle chained errors (#3567)
Closes tidyverse/dplyr#5552
Part of #3566
2022-01-10 18:33:14 -08:00
Barret Schloerke
9389160af0 Cache the reactlog version found. Remove mustWork argument to system_file(). (#3554) 2021-12-08 15:30:37 -05:00
Barret Schloerke
6a7ffeff68 master -> main; use shiny-workflows (#3535) 2021-11-19 17:50:57 -05:00
Winston Chang
bc6ff57cb7 Remove old unused JS files (#3547) 2021-11-17 22:01:19 -06:00
Carson Sievert
b52b9e4520 Some UI-related speed improvements (#3541) 2021-11-17 16:25:27 -06:00
Winston Chang
fb71ab6146 Editor configuration improvements 2021-11-16 15:38:21 -06:00
Carson Sievert
d8c7a634ff Fix failing tabPanel() test broken by testthat 3.1.0 (#3543) 2021-11-05 16:45:16 -05:00
Winston Chang
396dd2632e Merge pull request #3537 from rstudio/htmldep 2021-11-05 15:56:09 -05:00
Winston Chang
c11875a5f0 Fix appending to list 2021-11-05 15:52:14 -05:00
Winston Chang
2e599faf1f Fix comment 2021-11-05 15:47:23 -05:00
Winston Chang
a5a8385420 Use all_files=FALSE for html dependencies
This commit sets all_files=FALSE for html dependencies in www/shared.
2021-11-04 11:24:46 -05:00
Winston Chang
33ed698e5b Remove “file =“ 2021-11-04 11:15:01 -05:00
Winston Chang
ed547fdf40 Rebuild JS files 2021-11-03 21:28:15 -05:00
Winston Chang
0b1c35c92b Use .map() and .forEeach() instead of for loops 2021-11-03 21:28:11 -05:00
Winston Chang
d304bdf333 Rename HtmlDepSimplified to HtmlDepNormalized 2021-11-03 20:54:53 -05:00
Winston Chang
a9255e6b12 Extract jquery-ui dependency into function 2021-11-03 20:54:53 -05:00
Winston Chang
45429fb798 Streamline code for adding scripts and attachments 2021-11-03 13:56:37 -05:00
Winston Chang
1206d1d3ba Use array of objects to represent meta tags 2021-11-03 13:56:37 -05:00
Winston Chang
af44a447a1 Fix type specification of HTML dependency meta values 2021-11-03 11:40:49 -05:00
Winston Chang
d7fb6d1793 Fixes for strict null checks 2021-11-03 11:40:49 -05:00
Winston Chang
cb0083adb2 Update VSCode editor settings 2021-11-03 11:40:49 -05:00
Winston Chang
77bae68f26 Update NEWS 2021-11-03 11:40:48 -05:00
Winston Chang
e9f8b4d552 Use htmlDependencies with ‘src=file’ for showcase mode 2021-11-03 11:39:28 -05:00
Winston Chang
aee6b74cfb Minor cleanups 2021-11-03 11:39:28 -05:00
Winston Chang
29b6b03297 Extract restyle code into separate code path 2021-11-03 11:39:28 -05:00
Winston Chang
b5ebd8a645 Fix attachment handling and add more specific types 2021-11-03 11:39:28 -05:00
Winston Chang
356ba8c5a1 Add simplifyHtmlDependency() function 2021-11-03 11:39:28 -05:00
Winston Chang
5aa5cb1794 Make dep.src.href field optional 2021-11-03 11:39:28 -05:00
Winston Chang
09c609e417 Bump version to 1.7.1.9001 2021-11-03 11:39:28 -05:00
Winston Chang
10e7d11846 Allow array of attributes for stylesheets 2021-11-03 11:39:28 -05:00
Winston Chang
4e442312a7 Serve HTML dependencies from dynamic paths 2021-11-03 11:39:28 -05:00
Winston Chang
8ea97df3f2 Fix getid access of data-input-id attribute (#3538) 2021-11-03 11:38:54 -05:00
Winston Chang
a8c14dab96 Bump version to 1.7.1.9000 2021-10-04 11:09:26 -05:00
Winston Chang
00775b90e8 Bump version to 1.7.1 2021-09-30 14:48:12 -05:00
Winston Chang
c6ae4c0034 Update NEWS 2021-09-30 14:48:06 -05:00
Winston Chang
1efcaa0b5d Use esbuild option preserveSymlinks
This allows the node_modules directory to be a symlink, without causing weird
build problems.
2021-09-30 14:44:17 -05:00
Carson Sievert
e6d94f6f66 Fix regression in repeated appendTab()s when navbarMenu() is present (#3518) 2021-09-30 14:43:09 -05:00
Barret Schloerke
5a8a02626c add news item for #3512 2021-09-28 18:00:36 -04:00
Hadley Wickham
c23293750d Re-arrange conditions for testthat 1.0.0 compatibility (#3512) 2021-09-28 17:51:45 -04:00
Winston Chang
9de74048a2 Bump version to 1.7.0.9000 2021-09-28 16:39:35 -05:00
wch
0fc861afb4 yarn build (GitHub Actions) 2021-09-10 20:05:12 +00:00
wch
2300dae10b sync package version (GitHub Actions) 2021-09-10 20:02:58 +00:00
wch
dfbb98abfd Document (GitHub Actions) 2021-09-10 20:02:19 +00:00
Winston Chang
9670839235 Fix example parse errors 2021-09-10 14:55:53 -05:00
Winston Chang
1e2326c2b6 Update reexports 2021-09-10 14:46:30 -05:00
Carson
6f46b847e2 Address check NOTE: Undeclared package ‘htmlwidgets’ in Rd xrefs 2021-09-07 15:10:52 -05:00
Carson
8c44559a1f Fix DT Rd link 2021-09-07 14:48:34 -05:00
Carson
d245a972ee simplify gha 2021-09-07 14:23:22 -05:00
Carson
c153d0591f bump version 2021-09-07 14:14:50 -05:00
Barret Schloerke
2ce18ef324 Update GHA workflows to use latest versions (#3492) 2021-08-24 14:59:52 -04:00
Barret Schloerke
2792d65e40 Fix link to DT::renderDataTable() (#3490) 2021-08-20 09:14:57 -05:00
Barret Schloerke
7b00f605aa Remove rlang remote (#3487) 2021-08-19 18:07:23 -04:00
Barret Schloerke
4cb3f05e8e Adjust app port tests to use random port values (#3488) 2021-08-19 18:06:43 -04:00
Winston Chang
8e40c815eb Merge pull request #3485 from rstudio/wch-fix-checkbox-radio 2021-08-13 13:56:35 -05:00
Winston Chang
6dfd8bc0ff Only ignore node_modules at top level 2021-08-13 13:50:54 -05:00
wch
2ef397f024 yarn build (GitHub Actions) 2021-08-13 18:08:05 +00:00
wch
94749f6114 yarn lint (GitHub Actions) 2021-08-13 18:08:05 +00:00
Winston Chang
4a39588d00 Update NEWS 2021-08-13 13:00:57 -05:00
Winston Chang
f5d5832149 Fix invisible checkboxes and radio buttons in RStudio on Mac 2021-08-13 12:58:12 -05:00
Barret Schloerke
68deab9b0e Remove console.log("Shiny version: ", Shiny.version) statement (#3480) 2021-08-05 18:16:39 -04:00
Winston Chang
96efac2bd7 Merge pull request #3478 from rstudio/install_expr_news_entry 2021-08-05 10:17:50 -05:00
Barret Schloerke
a67059f9f9 update news 2021-08-04 15:31:56 -04:00
Barret Schloerke
cdc51c09c7 Add test for inject()ed quosures when extracting the cacheHint (#3476) 2021-08-04 13:35:50 -04:00
Barret Schloerke
a6f02cf214 Fix bash logic in action step (#3474) 2021-08-02 22:35:11 -04:00
Barret Schloerke
7600770a6e Fix Rituals workflow validating commits have not been made (#3473) 2021-08-02 22:19:31 -04:00
Barret Schloerke
1b3ed88bd1 exprToFunction() and installExprFunction() support quosures (#3472)
Co-authored-by: Barret Schloerke <schloerke@gmail.com>
Co-authored-by: Winston Chang <winston@stdout.org>
Co-authored-by: Carson Sievert <cpsievert1@gmail.com>
Co-authored-by: Joe Cheng <joe@rstudio.com>
2021-08-02 22:09:19 -04:00
Barret Schloerke
f01dc9f0fb Move user documentation up to the top of Readme (#3464) 2021-08-02 22:06:09 -04:00
Barret Schloerke
9a65890e92 Update esbuild-plugin-sass to latest version (#3463) 2021-08-02 21:41:02 -04:00
Carson Sievert
ffef0c2eb1 Interpret NULL discrete limits as NA, fixes #2666 (#2668)
Co-authored-by: Winston Chang <winston@stdout.org>
Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
2021-07-27 14:02:58 -05:00
Barret Schloerke
8b74338b0f Add sustainEnvAndQuoted(). Remove getQuosure() (#3468)
Documentation to come in a later PR

Co-authored-by: Barret Schloerke <schloerke@gmail.com>
Co-authored-by: Winston Chang <winston@stdout.org>
2021-07-26 17:54:37 -04:00
Winston Chang
ed3c676548 Merge pull request #3466 from rstudio/wch-exprfunction-fix 2021-07-16 16:14:38 -05:00
Winston Chang
30c0a2bd29 Update NEWS 2021-07-16 15:17:37 -05:00
Winston Chang
997e5e5ce5 Fix handling of getQuosure3(expr, env, quoted=TRUE) 2021-07-16 15:14:28 -05:00
Winston Chang
aba6b2e4db Fix NEWS entry 2021-07-15 17:52:59 -05:00
Winston Chang
3f48e3b0af Merge pull request #3462 from rstudio/wch-exprfunction-quosures 2021-07-15 17:51:22 -05:00
Winston Chang
b4879a342c Update NEWS 2021-07-15 17:50:40 -05:00
Winston Chang
5070146061 Fix example 2021-07-15 17:21:15 -05:00
Winston Chang
d28c3e15ad Update pkgdown.yml 2021-07-15 17:14:47 -05:00
Winston Chang
4b496be520 Update documentation 2021-07-15 17:11:36 -05:00
Winston Chang
979288a590 Add quosure tests for custom render functions 2021-07-14 16:31:23 -05:00
Winston Chang
9365d4f3c4 Update comment 2021-07-14 16:30:53 -05:00
Winston Chang
e1daf8aae7 Export getQuosure() and add internal getQuosure3() 2021-07-09 17:36:46 -05:00
Winston Chang
8a57dbf608 Rename get_quosure to getQuosure 2021-07-06 12:36:45 -05:00
Winston Chang
ac9b76c651 Modify exprToFunction to accept quosures 2021-07-02 15:45:10 -05:00
Winston Chang
139526ef2d Move expression/quosure functions to utils-lang.R 2021-07-02 14:25:46 -05:00
Winston Chang
d1e7e6c63a Add note about R version support 2021-07-02 14:04:35 -05:00
Winston Chang
29b574bf94 Merge pull request #3456 from heds1/update-rejected-ports 2021-07-01 16:34:25 -05:00
Barret Schloerke
7e4248bbca TypeScript: Globally declare Shiny variable, window.Shiny variable, and Shiny type (#3457) 2021-07-01 14:51:16 -04:00
heds1
fee267dc2e docs: update runapp port parameter docs, and add three more tcp ports to be blocked 2021-07-01 21:40:59 +12:00
Carson Sievert
9864130435 Use random inline styles to ensure transitionend fires everytime (#3452)
* Follow up to #3333: use random inline styles to ensure transitionend fires everytime

* yarn lint (GitHub Actions)

* Add missing '#'

* yarn lint (GitHub Actions)

Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
2021-06-30 15:26:49 -05:00
Carson Sievert
c9770cbd03 Close #3443: Fix sliderInput()'s grid tick positioning without Bootstrap (#3444) 2021-06-29 15:56:47 -05:00
Carson Sievert
ed6a40ba41 Close #3446: get removeModel() working with Bootstrap 4 (#3447) 2021-06-29 15:54:48 -05:00
Carson
3c22cdf90c roxygenize 2021-06-29 15:11:39 -05:00
Marcus Spittler
e55749b897 Update utils.R example to validate() (#2809)
Added an empty option to `choices` in `selectizeInput` in order to make the second `need` statement in `validate` meaningful. Otherwise the second `need` ("Please choose a state") is never displayed.
2021-06-29 15:10:42 -05:00
Carson Sievert
88cd87a5f7 Revert "Set selectize dropdownParent to "body" to prevent clipping" (#3450)
This reverts commit ce90d5cd0a.
2021-06-29 12:22:33 -05:00
Barret Schloerke
244fdc72bc Leverage more eslint rules (#3439) 2021-06-22 21:20:54 -04:00
Barret Schloerke
b9d163a71d TypeScript other distributed JS/CSS files (#3436) 2021-06-18 10:18:51 -04:00
Barret Schloerke
61ee467dee Replace dev versions with -alpha versions for JS code (#3435) 2021-06-17 16:02:39 -04:00
Carson Sievert
7c0829d553 Change from .nav-item to .dropdown-item when inserting inside .dropdown-menu (#3434)
* Change from .nav-item to .dropdown-item when inserting inside .dropdown-menu

* Update srcts/src/shiny/shinyapp.ts

* Update srcts/src/shiny/shinyapp.ts

* yarn lint (GitHub Actions)

* yarn build (GitHub Actions)

Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
2021-06-16 17:44:03 -05:00
Carson Sievert
68eb4c6965 update news for breaking insertTab() change (#3433) 2021-06-16 16:41:07 -05:00
Barret Schloerke
6d4015f61b ./package.json updates to make TS Types package cleaner to install (#3430)
Co-authored-by: Barret Schloerke <schloerke@gmail.com>
Co-authored-by: Carson Sievert <cpsievert1@gmail.com>
2021-06-16 16:08:50 -04:00
Barret Schloerke
d89513b7e0 Match casing for plot alt text "Plot object" (#3432)
* Match spelling for Plot Object phrase

From #3398

* Document (GitHub Actions)

* Consistent casing for `"Plot object"` for plot alt text

Co-authored-by: schloerke <schloerke@users.noreply.github.com>
2021-06-16 15:08:13 -05:00
Carson Sievert
a159594a45 insertTab(position = "after") by default (#3431)
* Follow up to #3404: change insertTab()'s default position so that default behavior doesn't change

* Update news

* Document (GitHub Actions)

Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
2021-06-16 15:01:36 -05:00
Carson Sievert
78c62ad819 Various cleanup (#3428)
* Follow up to #3366: don't change sliderInput()'s default accent color

* Update news

* nav_append not tab_append 🤦

* bslib no longer tries to mark a non-tabPanel as active
2021-06-15 16:45:23 -05:00
Barret Schloerke
b3247d5a3b Move ./srcts configs to top level to support types installation from GitHub (#3425) 2021-06-15 14:18:53 -04:00
Winston Chang
91f920e14c Merge pull request #3413 from rstudio/feature/selectize-dropdown-parent-body
Set selectize dropdownParent to "body" to prevent clipping
2021-06-15 11:50:37 -05:00
Carson Sievert
bcb7cde44b insertTab() now handles position correctly when target is NULL (#3404)
* Close #3403: insertTab() now handles position correctly when target is NULL

* Have insertTab()'s target default to NULL

* yarn tsc (GitHub Actions)

* yarn build (GitHub Actions)

Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
2021-06-14 15:51:38 -05:00
Carson Sievert
052c9458b7 yarn add node-gyp; yarn build (#3424) 2021-06-14 15:51:03 -05:00
Barret Schloerke
3fe8c27d21 Export TypeScript type definitions to local folder (#3418) 2021-06-14 14:25:05 -04:00
Barret Schloerke
1dd256b210 TypeScript: Remove any types / improve type definitions (#3414) 2021-06-14 14:22:39 -04:00
Carson Sievert
dc9c6ae769 Better color constrasting in sliderInput() (#3366)
* Better color constrasting in sliderInput()

Closes https://github.com/rstudio/bslib/issues/228

* Update build script; recompile

* bslib tabsets now include data-bs-toggle
2021-06-14 12:48:57 -05:00
Carson Sievert
2cdafed2e0 Use ggplot2::get_alt_text() if available to provide better default alt text (#3398)
* Close #3397: Use ggplot2::get_alt_text() if available to provide more informative default alt text for ggplots in renderPlot()

* Update R/render-plot.R

Co-authored-by: Winston Chang <winston@stdout.org>

* better Rd docs

* make logic more self-contained

* Add news

Co-authored-by: Winston Chang <winston@stdout.org>
2021-06-14 10:22:07 -05:00
JJ Allaire
ce90d5cd0a Set selectize dropdownParent to "body" to prevent clipping
To prevent clipping of the selectize drop-down we set the dropdownParent to "body". This might be necessary if e.g. overflow-x: scroll is set on it's container, which forces overflow-y to 'auto' (as per https://developer.mozilla.org/en-US/docs/Web/CSS/overflow-y).

See option docs here: https://github.com/selectize/selectize.js/blob/master/docs/usage.md

Additional discussion of usage here: https://github.com/selectize/selectize.js/issues/192
2021-06-09 19:41:10 -04:00
Barret Schloerke
b4caa9137d Distribute TypeScript code into separate files (#3317)
Co-authored-by: Barret Schloerke <schloerke@gmail.com>
Co-authored-by: Carson Sievert <cpsievert1@gmail.com>
2021-06-09 14:54:47 -04:00
Carson Sievert
dcca77c936 Fix tab input value updating for BS4 dropdowns (#3412)
* Fix tab input value updating for BS4 dropdowns

* Add comments

* yarn build (GitHub Actions)

* Better comment

* yarn lint (GitHub Actions)

* yarn build (GitHub Actions)

Co-authored-by: Barret Schloerke <barret@rstudio.com>
Co-authored-by: schloerke <schloerke@users.noreply.github.com>
Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
2021-06-02 15:55:32 -05:00
Carson Sievert
871b1baacc Follow up to #3410: bump version and update news (#3411) 2021-06-02 13:03:09 -05:00
Carson Sievert
4deb699066 Bootstrap 5 support (#3410)
* Bootstrap 5 support for modals & showcase mode

* selectizeInput() BS5 compatibility

* Both BS4 and 5 define window.bootstrap

* Document (GitHub Actions)

Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
2021-06-02 12:36:04 -05:00
Carson Sievert
ccc8e053c6 Use bslib's new nav() api to implement tabPanel() and friends (#3388)
* Use bslib's new nav() api to implement tabPanel() and friends

* bslib won't be re-exporting prepend/append tab since they've been superceded by insertTab()

* Update DESCRIPTION

* Use the new bslib::page_navbar()

* Leverage bslib::page_navbar()'s more intelligent title->windowTitle handling

Closes #2310

* fix name change

* Make sure navbarPage() isn't browsable by default
2021-06-02 12:10:41 -05:00
Barret Schloerke
6405056c92 Install Cairo macOS devel brew dependency (#3408) 2021-05-26 17:06:27 -04:00
Barret Schloerke
9f9304fdc5 Remove Font Awesome 5 message about the level-up icon (#3407) 2021-05-26 16:31:15 -04:00
Carson Sievert
3d3b05c7a5 Correctly render script tags defined as list() objects (#3395)
* Close #3345: correctly render script tags defined as list() objects

* implement boolean attrs; use vanilla JS

* Update news

* avoid toggleAttribute

* yarn lint (GitHub Actions)

* code review

Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
2021-05-20 17:44:34 -05:00
Carson Sievert
543a6b5836 Fix CRAN note (#3394)
* Follow up to #3392: update tabPanel() baselines

* Fix check NOTE

* Revert "Follow up to #3392: update tabPanel() baselines"

This reverts commit c97022c386.

Issue will be fixed in htmltools
2021-05-20 13:58:16 -05:00
Carson Sievert
b0de68919a tagify() dynamic UI before attempting to write the tags (#3392)
* Close #3391: properly tagify() dynamic UI before attempting to write the tags

* Document (GitHub Actions)

Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
2021-05-18 12:28:17 -05:00
Richard Iannone
d65ad5ea90 Modify icon() function to call fontawesome::fa_i() for equivalent functionality (#3302)
* Use `fontawesome::fa_i()` for FA <i> tags

* Remove fontawesome vendor files

* Add fontawesome pkg to Imports & Remotes

* Remove FontAwesome `person()` entry

* Remove Font Awesome license info

* Delete font-awesome.R

* Update 'Collate' field (removes 'font-awesome.R')

* Delete updateFontAwesome.R

* Prefer use of `fontawesome::fa()`

* Improve function documentation

* Update help file using roxygen

* Modify icon name

* Update icon name in example

* Modify icon name in example

* Update help files

* Update bootstrap.R

* Update icon.Rd

* Update bootstrap.R

* Revert `showcaseCodeTabs()` to use FA v4 name

* Revert icon name in example (back to FA v4)

* Remove `call. = FALSE` in `stop()`

* Remove `fontawesome` from Remotes

* Add min version req for the fontawesome pkg

* Increase minimum version requirement for fontawesome

* Update roxygen docs for `icon()`

* Document (GitHub Actions)

* Update icon.Rd

* Generate early return <i> tag for tabsetPanel logic

* Close #3384 and #3383: simplify and correct icon() logic

* Install htmltools PR for now

* Document (GitHub Actions)

* Avoid using tag attribs to hold non-attribute values

* Better legacy support

* No need to call prepTabIcon() twice

* code review

* Fix glyphicon class creation

* update news

Co-authored-by: Carson Sievert <cpsievert1@gmail.com>
Co-authored-by: rich-iannone <rich-iannone@users.noreply.github.com>
Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
2021-05-12 14:26:09 -05:00
Carson Sievert
383fa6c0e0 Follow up to #3372: fix oversight in refactor (#3387) 2021-05-10 09:58:30 -05:00
Barret Schloerke
8d40b3af70 Revert "Do not double pull within rituals"
This reverts commit 9c80d7a4ec.
2021-05-10 10:49:54 -04:00
Barret Schloerke
9c80d7a4ec Do not double pull within rituals 2021-05-07 15:15:41 -04:00
Winston Chang
2360bde13e Remove deprecated code and parameters (#3137)
* Remove deprecated reactive* functions

* Remove deprecated code

* Update NEWS

* Remove extractStackTrace and formatStackTrace

* remove responsive from bootstrapPage() wrappers

* Move extractStackTrace() to tests so they pass

* Don't force suggested pkgs in devel on GHA

Co-authored-by: Carson <cpsievert1@gmail.com>
2021-05-06 09:46:30 -05:00
Winston Chang
d25ae099d4 Merge pull request #3333 from rstudio/reportCssOnLoad 2021-05-05 18:12:17 -05:00
Winston Chang
2d492886e4 Prettify TS 2021-05-05 18:04:35 -05:00
Winston Chang
33741436c7 Merge remote-tracking branch 'origin/master' into reportCssOnLoad 2021-05-05 18:03:41 -05:00
Winston Chang
318cc7fcaf Rebuild JS files 2021-05-05 18:02:32 -05:00
Winston Chang
bebcf0b196 Add important flag 2021-05-05 18:02:32 -05:00
Winston Chang
f2be2e4eb1 Update comments 2021-05-05 17:48:39 -05:00
Winston Chang
a2ea017046 Add sendImageSize2 2021-05-05 17:40:46 -05:00
Winston Chang
fc338c8958 Use removeSheet() 2021-05-05 16:17:34 -05:00
Winston Chang
bbb27f1224 Make more CSS properties !important 2021-05-05 15:56:50 -05:00
Winston Chang
d2fbdb6c48 Add note about synchronous behavior in IE 2021-05-05 15:56:29 -05:00
Winston Chang
38c70842d9 Rebuild JS files 2021-05-05 15:18:01 -05:00
Winston Chang
0e22c4c591 Simplify IE CSS handling 2021-05-05 14:53:12 -05:00
Winston Chang
70e0eede16 New strategy for sending information when CSS loads 2021-05-05 14:50:39 -05:00
Barret Schloerke
4858a379e7 Make sure dev version of rlang is available (#3382) 2021-05-05 15:01:47 -04:00
Carson Sievert
3e33755a9e Reduce complexity and 'black-boxed' nature of tab panel logic (#3372)
* Follow up to #3315: reduce complexity and 'black-boxed' nature of tab panel logic

* asTags(selected = FALSE) is now root()

* tagAddRenderHook

* Add bslib to remotes

* Document (GitHub Actions)

* root() was recently changed to allTags()

* code review

* tagQuery() doesn't necessarily preserve order of attributes

* place href attribute before data attributes

* add nav-item/nav-link to BS4+ dropdowns

* Make sure .nav-item is removed in .dropdown-menu

Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
2021-05-05 10:05:24 -05:00
Carson Sievert
f2ad004f33 Install dev version of rlang (#3379)
Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
Co-authored-by: Barret Schloerke <schloerke@gmail.com>
2021-05-05 10:44:19 -04:00
Carson
16e0d9e355 Comment about the hoisting 2021-05-04 14:33:54 -05:00
Carson
d430b80191 Use sendImageSize instead of Shiny.bindAll to resend CSS info 2021-05-04 14:19:40 -05:00
Carson
2ffa8707ea Merge branch 'master' into reportCssOnLoad 2021-05-04 12:13:37 -05:00
Carson
cbd06cbd8e Merge branch 'master' into reportCssOnLoad 2021-05-04 12:11:56 -05:00
Carson Sievert
d3aa1acfbf Use tab instead of tooltip constructor to check Bootstrap version (#3377)
Closes https://github.com/rstudio/shinycoreci-apps/issues/138
2021-05-04 08:15:27 -05:00
Winston Chang
c2232ae07a Merge pull request #3373 from rstudio/nested-quo-to-func 2021-04-27 12:38:33 -05:00
Winston Chang
cf0a865d6f Remove ... args from function 2021-04-27 12:29:34 -05:00
Carson
4942b3e6ad Add news item 2021-04-22 16:49:40 -05:00
Joe Cheng
f374a1512a Fix rlang::inject with render functions
Render functions use quoToFunction() to convert quosures to
functions; quoToFunction() was using new_function, which leads
to non-tidy evaluation, so nested quosures are not evaluated.

See https://github.com/rstudio/shiny/pull/3361#issuecomment-820672180
2021-04-22 11:57:24 -07:00
Barret Schloerke
1558c848f4 Export register_devmode_option() (#3364) 2021-04-20 17:33:58 -04:00
Barret Schloerke
4a2bb8fc43 Add ORCID info (#3363) 2021-04-09 16:35:49 -04:00
Barret Schloerke
fad21af146 Make external libs builder leveraging esbuild (#3357) 2021-04-07 16:06:05 -04:00
Winston Chang
850a628978 Fix variable name 2021-04-06 12:52:14 -05:00
Winston Chang
4d2311841d Merge pull request #3334 from rstudio/boostrapPageJQuery
bootstrapPage() now includes jQuery so static rendering works as expected
2021-04-06 12:10:12 -05:00
Winston Chang
5c4175cd5f Merge pull request #3353 from rstudio/wch-fix-tab-title 2021-04-02 14:51:44 -05:00
Winston Chang
2931e40c7b Update 2021-04-02 14:50:36 -05:00
Winston Chang
6a6eae1ce1 Update R/bootstrap.R
Co-authored-by: Carson Sievert <cpsievert1@gmail.com>
2021-04-02 14:49:37 -05:00
Winston Chang
210642e96c Update R/bootstrap.R
Co-authored-by: Carson Sievert <cpsievert1@gmail.com>
2021-04-02 14:49:26 -05:00
Winston Chang
c97fad30ef Fix html tags in tab titles 2021-04-02 13:27:22 -05:00
Carson Sievert
268c9afec3 Close #3299: bootstrapLib() should always call setCurrentTheme() when shiny is running (#3300) 2021-03-26 15:12:54 -05:00
Carson Sievert
5c919ae565 Make ensureTabsetHasVisibleTab() is aware of BS4+ markup (#3349)
* Close https://github.com/rstudio/shinycoreci-apps/issues/126: Make ensureTabsetHasVisibleTab() aware of BS4+ markup

* yarn build (GitHub Actions)

* Update srcts/src/main.ts

* yarn lint (GitHub Actions)

* yarn build (GitHub Actions)

Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
2021-03-26 15:11:48 -05:00
Hadley Wickham
e29d92c5ff Allow trailing commas in more places (#3328)
* Allow trailing commas in more places

I grepped for list(...) and replaced with rlang::list2(...). This also enables !!! which is generally not important for Shiny because it automatically splices lists/tagLists, but I doubt it will affect any existing code.

* update news; no need to rlang::

* missed one

* Update NEWS.md

Co-authored-by: Hadley Wickham <h.wickham@gmail.com>

Co-authored-by: Carson Sievert <cpsievert1@gmail.com>
2021-03-23 14:24:21 -05:00
Carson
0a331e3366 update news 2021-03-22 16:00:39 -05:00
Carson Sievert
32d0e146ad Various improvements to tab panels (#3315)
* 'Native' Bootstrap 4 tabset panel support

* downgrade error to warning; improve the messaging

* Make tab anchor selectors more a bit more sensible and consistent across versions

* More of the same

* fix silly bug

* Be more careful about unpacking a .nav-item into a .dropdown-item

* Keep refactoring R logic to make it cleaner and easier to reuse elsewhere

* Go back to the purely class based CSS selectors for BS4 tab input

* Keep supporting off-label behavior of shiny.tag getting transformed into 'empty' nav/tab

* Add header and footer args to tabsetPanel()/navlistPanel() since there is precedence in navbarPage() and mention them in the warning

* Drop NULLs instead of creating an empty nav from them, closes #1928

* Remove tabPanelMenu() alias

* Add a card argument for wrapping content in a card

* Throw an error if card=T is used outside of a BS4+ context

* No more tabPanelMenu() alias

* Document (GitHub Actions)

* Port JS changes to TypeScript

* Allow liTag to be assigned a new value

* abort() is no longer being used

* Add some unit tests

* Document the new card argument

* Get tests passing on older R versions

* Get tests passing on older R versions

* Get tests passing on older R versions

* Skip snapshots on R < 3.6

* require dev version of htmltools

* remove card argument (at least for now)

* Document (GitHub Actions)

* Update tests/testthat/test-tabPanel.R

Co-authored-by: Winston Chang <winston@stdout.org>

* Have processDeps() call renderTags() on tagFunction() objects

Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
Co-authored-by: Winston Chang <winston@stdout.org>
2021-03-22 12:37:57 -05:00
Carson
c94f411fc6 Specify both href and file 2021-03-12 17:17:01 -06:00
Carson
22d408aa7b Close #3316: bootstrapPage() now includes jQuery so static rendering works as expected 2021-03-12 16:50:24 -06:00
Carson
a44fdc1b11 remove logs 2021-03-11 17:01:25 -06:00
Carson
50ca830ec6 Poll every 0.1sec for 10secs 2021-03-11 16:57:20 -06:00
Carson
e643cd3824 request on next tick 2021-03-11 12:37:41 -06:00
Carson
2660a50d31 try using requestAnimationFrame 2021-03-11 11:46:17 -06:00
Carson
927912efe3 Try sending multiple times 2021-03-11 11:13:51 -06:00
Carson
9b49a24e74 Try not debouncing 2021-03-11 11:03:28 -06:00
Carson
0824b22532 Add debug statements 2021-03-11 10:49:16 -06:00
Carson
000feead00 When refreshing a stylesheet, schedule a report CSS values once the sheet is loaded 2021-03-11 09:50:49 -06:00
Winston Chang
d582e53f73 Merge pull request #3311 from rstudio/update-jquery-3.6.0
Co-authored-by: Barret Schloerke <barret@rstudio.com>
Co-authored-by: Barret Schloerke <schloerke@gmail.com>
2021-03-03 09:47:47 -06:00
Barret Schloerke
52ad7d12cb jquery@3.6.0 is available. @types/jquery@3.6.0 is not ready yet. 2021-03-03 10:42:15 -05:00
Barret Schloerke
10810308f0 Install jquery and @types/jquery in ./srcts 2021-03-03 10:37:57 -05:00
Carson Sievert
4ce1058448 Remove old @param theme roxygen documentation and rely in @inheritParams bootstrapPage (#3312) 2021-03-02 16:34:35 -06:00
Winston Chang
0db06df77f Automatically record jQuery version 2021-03-02 13:56:14 -06:00
Winston Chang
fdca53d4d2 Update to jQuery 3.6.0 2021-03-02 13:40:33 -06:00
Barret Schloerke
8395598328 🤦 2021-02-25 15:56:43 -05:00
Barret Schloerke
1b8635db32 Initialize TypeScript (#3296) 2021-02-25 15:44:11 -05:00
Winston Chang
60db1e02b0 Merge pull request #3269 from rstudio/read-output
Tweak errors when reading from outputs
2021-02-12 15:31:45 -06:00
Winston Chang
a86e9c3609 Merge pull request #3287 from rstudio/validate-req-truthy
Tweaks to validate(), req(), and isTruthy() docs
2021-02-12 15:09:01 -06:00
Winston Chang
6d77b22f97 Add isTruthy to pkgdown 2021-02-12 14:59:15 -06:00
Winston Chang
e1b3756166 Merge pull request #3272 from rstudio/slider-dep
Remove deprecated arguments to sliderInput
2021-02-12 14:35:51 -06:00
Winston Chang
edf354f416 Merge pull request #3288 from rstudio/update-fa 2021-02-10 12:06:43 -06:00
Winston Chang
954a979a83 Add note about auto-generated code 2021-02-10 12:00:59 -06:00
Winston Chang
fe9a87fb06 Update NEWS 2021-02-10 09:58:44 -06:00
Winston Chang
1842a15f74 Update to Font-Awesome 5.15.2 2021-02-10 09:57:16 -06:00
Winston Chang
a568238472 Update font-awesome update script 2021-02-10 09:56:45 -06:00
Hadley Wickham
fa200022c5 Tweaks to validate(), req(), and isTruthy() docs
* Use more markdown/roxygen2 tags
* Pull isTruthy out into own file
* Rewrite validate for clarity
2021-02-09 17:37:36 -06:00
Winston Chang
a6347341e3 Merge pull request #3176 from rstudio/wch-faststack 2021-02-09 14:56:13 -06:00
Winston Chang
c41481e488 Merge pull request #3285 from rstudio/dotloop-bug
Fix logic bug in dotloop()
2021-02-09 14:51:19 -06:00
Winston Chang
767abc3c0c Create restoreCtxStack in .onLoad() 2021-02-09 14:46:28 -06:00
Hadley Wickham
e005c24fbf Fix logic bug in dotloop()
Ensures that req() works without error
2021-02-09 13:56:09 -06:00
Winston Chang
8580f544fc Update NEWS 2021-02-09 11:57:25 -06:00
Winston Chang
2daa8ec944 Replace queues with fastqueue 2021-02-09 11:57:25 -06:00
Winston Chang
2b92014ea5 Use fastmap::faststack() and remove Stack 2021-02-09 11:57:19 -06:00
Winston Chang
f540679513 Merge pull request #2954 from rstudio/remove-test-context
Remove context() calls from example app
2021-02-09 11:54:22 -06:00
Shinya Uryu
d165cc6e8e Typo (#3283) 2021-02-05 08:43:13 -06:00
Winston Chang
c1878fe54f Merge pull request #3278 from rstudio/wch-fix-test 2021-02-02 11:01:07 -06:00
Winston Chang
f05948629e Adjust test time 2021-02-01 21:10:52 -06:00
Winston Chang
3e37dab4a1 De-functionize tests 2021-02-01 19:02:18 -06:00
Winston Chang
6584e1f960 Recommend using bindEvent() (#3277) 2021-02-01 18:11:30 -06:00
Hadley Wickham
64c5a67a0e Use testthat 3e (#3274) 2021-01-29 10:34:14 -06:00
Barret Schloerke
aea4e560ea Display devmode in docs (#3275) 2021-01-29 11:32:34 -05:00
Winston Chang
12554a0004 Add info about render functions with bindCache 2021-01-29 09:53:58 -06:00
Barret Schloerke
83336ef9a5 Update bootstrap-accessibility plugin (#3259)
* Copy from installed bslib location, no relative file path

* Adopt the fix from https://github.com/rstudio/bslib/pull/241

Co-authored-by: Carson <cpsievert1@gmail.com>
2021-01-27 09:39:10 -06:00
Hadley Wickham
08ab21b50e Remove deprecated arguments to sliderInput 2021-01-27 08:42:28 -06:00
Hadley Wickham
5628346ae1 Tweak errors when reading from outputs 2021-01-26 13:00:18 -06:00
Winston Chang
b165127d20 Merge pull request #3268 from rstudio/dt-docs 2021-01-26 12:49:23 -06:00
Hadley Wickham
905e2238d4 Drop tableOutput from ref index 2021-01-26 12:47:30 -06:00
Hadley Wickham
47bb1f657c Doc fixes 2021-01-26 12:47:30 -06:00
Hadley Wickham
c917d18d67 Improve table output docs
* Combine render + output functions in one file
* Put more info in the description
* Mild polishing of param docs
2021-01-26 12:47:30 -06:00
Winston Chang
93568cd53f Merge pull request #3264 from rstudio/wch-rm-digest 2021-01-26 10:22:35 -06:00
Winston Chang
6af06559f4 Update NEWS 2021-01-26 09:36:30 -06:00
Winston Chang
43239a0485 Use rlang::hash instead of digest 2021-01-26 09:36:30 -06:00
Winston Chang
e05f4097d6 Merge pull request #3267 from rstudio/slider-docs 2021-01-26 09:35:37 -06:00
hadley
35e62eaee9 yarn build (GitHub Actions) 2021-01-26 13:52:12 +00:00
Hadley Wickham
858c2e66e6 Clarify supported types in sliderRange() 2021-01-26 07:35:36 -06:00
Winston Chang
0d156171d4 Bump version to 1.6.0.9000 2021-01-25 15:56:38 -06:00
Winston Chang
b57cb6c8e1 Fix URLs 2021-01-19 11:15:00 -06:00
Carson
5ddff1bd37 Merge branch 'master' into rc-v1.6.0 2021-01-15 14:46:44 -06:00
Carson Sievert
036f923e05 Run accessiblity plugin JS when DOM is loaded (via defer attribute) a… (#3256)
* Use bslib's patched version of bootstrap-accessibility plugin (see https://github.com/rstudio/bslib/pull/224)

* Use new minified file

Co-authored-by: Barret Schloerke <schloerke@gmail.com>
2021-01-15 14:43:00 -06:00
Carson Sievert
130f4764a7 Documentation improvements for v1.6 (#3255) 2021-01-14 10:35:00 -06:00
Carson
c4b5e5f8a2 Merge branch 'master' into rc-v1.6.0 2021-01-13 14:23:56 -06:00
Barret Schloerke
ecb21df941 Use url checker (#3249)
* Update rituals.yaml

* update docs links

* Fix 404 link

* http://fontawesome.io to https://fontawesome.com

* Update links (GitHub Actions)

* Update NEWS.md

* Only check urls in rc branches

* missing paren

Co-authored-by: schloerke <schloerke@users.noreply.github.com>
2021-01-13 14:18:12 -06:00
Barret Schloerke
71d11ec103 Merge branch 'master' into rc-v1.6.0
* master:
  Reduce promises version to 1.1.0 and safeguard visibility test (#3252)
2021-01-12 13:31:09 -05:00
Barret Schloerke
213f0d3a93 Reduce promises version to 1.1.0 and safeguard visibility test (#3252) 2021-01-12 12:29:18 -06:00
Carson
8948eca0f3 Use checkJsCurrent.sh to rebuild JS 2021-01-08 14:37:39 -06:00
Carson
aa0c841aff Close #3244: sliderInput()'s handles are now always round 2021-01-08 14:22:14 -06:00
Carson
a8449382f0 Start shiny v1.6 release candidate 2021-01-05 13:52:16 -06:00
Carson Sievert
5b27d9258e Don't change the return value of bootstrapPage() if bslib isn't relevant (#3236)
* Close #3235: Don't change the return value of bootstrapPage() if bslib isn't relevant

Also, improved error message if theme is a character vector with 2 or more elements

* yarn build (GitHub Actions)

* bump version

* yarn build (GitHub Actions)

* Don't add an additional level to the returned tree structure

* More straightforward use of do.call()

Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
Co-authored-by: Winston Chang <winston@stdout.org>
2021-01-05 13:21:38 -06:00
Winston Chang
2590cf3895 Drop GHA pr-commands and add GHA Rituals. Use pak to install (#3230)
Co-authored-by: Winston Chang <winston@stdout.org>
Co-authored-by: Barret Schloerke <schloerke@gmail.com>
2020-12-28 13:28:38 -05:00
Nick Strayer
a9f7068b2f bindCache() docs typos (#3232)
* vert -> very

* cachem::cache_mem() uses max_size argument to set size.

* Rebuilt docs after cache typo fixes

* Rerender docs with new roxygen version

* Installed cairo and rebuilt docs
2020-12-23 17:14:57 -06:00
Carson Sievert
1f9e4929a6 Follow up to #3228. shinyAppDir() now throws a classed condition when appDir is not a directory (#3229) 2020-12-23 10:20:48 -06:00
Carson Sievert
d56afca33e shinyAppDir() now throws an exception with a special class if no app.R/server.R file is found. (#3228)
shinytest:::is_app() can make use of this for better error reporting
2020-12-22 10:41:55 -06:00
Carson Sievert
8fa023b4ec Closes #223: Add selectize patch file to capture changes from #3217 (#3227) 2020-12-21 11:06:35 -06:00
Winston Chang
d9f73c4c6d Merge pull request #3212 from rstudio/wch-fix-selectize-enter 2020-12-21 10:42:55 -06:00
Winston Chang
68cf1c5410 Check for empty list 2020-12-21 10:40:24 -06:00
Winston Chang
a70220c6c4 Rebuild JS file 2020-12-19 23:02:20 -06:00
Winston Chang
99207d1d8f Simplify handling of empty options 2020-12-19 23:02:20 -06:00
Winston Chang
0baf2ecd70 Apply patches 2020-12-19 23:02:20 -06:00
Winston Chang
2c6f830223 Add patch for not triggering click on selectize 2020-12-19 23:02:20 -06:00
Winston Chang
98eb1b596d Update selectize-plugin-a11y comments 2020-12-19 23:02:20 -06:00
Winston Chang
145d222653 Add webdriver to remotes 2020-12-19 22:57:46 -06:00
Winston Chang
67e54572a8 Rebuild JS files 2020-12-19 22:52:01 -06:00
Winston Chang
3cc9b33a8d yarn upgrade 2020-12-19 22:51:24 -06:00
Barret Schloerke
12bc94fbc0 bump dev version to 1.5.0.9006 (#3221) 2020-12-19 16:32:22 -06:00
Winston Chang
b2379bfa5b Cache packages on Windows 2020-12-19 13:41:06 -06:00
Barret Schloerke
f4fc13fc2f Add devmode() features (#3174)
Co-authored-by: Barret Schloerke <schloerke@gmail.com>
Co-authored-by: Winston Chang <winston@stdout.org>
2020-12-18 14:31:31 -05:00
Nick Strayer
95081c43a7 Make sure setCurrentTheme() doesn't try and change bootstrap versions (#3210)
* Added check to make sure setCurrentTheme() doesn't try and change bootstrap version

* Update R/shiny.R

Style improvements via Carson

Co-authored-by: Carson Sievert <cpsievert1@gmail.com>

* Update error message to be more specific

Co-authored-by: Carson Sievert <cpsievert1@gmail.com>

* Make it clearer where the new bs_theme() call should be made.

* Add a check to make sure setCurrentTheme() receive a bs_theme() object

Co-authored-by: Nick Strayer <nick.strayer@gmail.com>
Co-authored-by: Carson Sievert <cpsievert1@gmail.com>
2020-12-18 13:28:16 -06:00
Winston Chang
bb3b3d5a47 Use rlang from CRAN 2020-12-18 12:39:29 -06:00
Carson Sievert
f635f98ccb Put pre-Chromium Edge in the same category as IE (#3220)
* Put pre-Chromium Edge in the same category as IE, closes #3219

* code review
2020-12-18 12:08:50 -06:00
Carson Sievert
eef44295db Close #3215, selectize's active item fg color now uses bslib's color-contrast() for more generalized contrasting (#3217) 2020-12-18 12:01:44 -06:00
Barret Schloerke
5e1afc61c1 Update private$currentThemeDependency label to be Theme Counter (#3206)
* Update `private$currentThemeDependency` label to be `Theme Iteration`

* Update R/shiny.R

Co-authored-by: Winston Chang <winston@stdout.org>
2020-12-16 15:31:50 -06:00
Carson Sievert
8edcbb3dc1 Revert "Make .shiny-text-output more aware of Bootstrap's pre styles (#3203)" (#3209)
This reverts commit 4eeb4a12a7.

This change was superfluous given that bslib's bs3compat CSS will provide <pre> styles and reduces the risk of overriding user rules targetting .shiny-text-output (https://github.com/rstudio/shinycoreci-apps/issues/95)
2020-12-16 13:41:01 -06:00
Malcolm Barrett
dca3722cb8 fix typo in docs (#3204)
Co-authored-by: runner <runner@Mac-1607960235106.local>
2020-12-16 13:37:16 -06:00
Stéphane Guillou
7eb0e93731 typos in documentation (#3205)
Co-authored-by: runner <runner@Mac-1607961254343.local>
2020-12-16 13:36:32 -06:00
Carson Sievert
6034c3ff7a Resend CSS styles when relevant element(s) mutate. (#3198) 2020-12-16 11:59:37 -06:00
Carson Sievert
4eeb4a12a7 Make .shiny-text-output more aware of Bootstrap's pre styles (#3203) 2020-12-11 18:55:27 -06:00
Winston Chang
6daa689888 Merge pull request #3201 from rstudio/wch-fix-datepicker 2020-12-11 15:51:46 -06:00
Winston Chang
cded44b40a Update NEWS 2020-12-11 15:51:08 -06:00
Winston Chang
290c9f6b20 Rebuild JS files 2020-12-11 15:51:08 -06:00
Winston Chang
be3d712fdf Set min/max date before setting value. Closes #3197 2020-12-11 15:51:08 -06:00
Winston Chang
f5666bcba1 Respect shiny.minified for bootstrap-datepicker.js 2020-12-11 10:02:01 -06:00
Winston Chang
f3c89bed01 Merge pull request #3199 from rstudio/fix-session-validate
Co-authored-by: Carson <cpsievert1@gmail.com>
2020-12-10 18:06:12 -06:00
Carson
9b0f170730 Skip POSIXlt slider tests on R3.6 and below 2020-12-10 15:24:07 -06:00
Winston Chang
74350cd443 Update NEWS 2020-12-10 12:28:46 -06:00
Winston Chang
61aa7bb3b0 validate_session_object: Also work with modules 2020-12-10 12:25:30 -06:00
Winston Chang
82fdbeda49 Fix test 2020-12-10 12:25:12 -06:00
Winston Chang
196b220faf All session parameters from the update* functions now default to getDefaultReactiveDomain() (#3195)
Co-authored-by: colin <colin@thinkr.fr>
2020-12-08 12:18:37 -06:00
Hadley Wickham
f41c484913 Respect reactiveConsole() in new errors (#3193) 2020-12-08 12:17:43 -06:00
Carson Sievert
a1a20b3f4b Add NEWS notes for #3042 and #3038 (#3191)
Co-authored-by: Winston Chang <winston@stdout.org>
2020-12-08 10:59:23 -06:00
Winston Chang
bbf9bee28e Add a warning message when value < min | value > max in sliderInput (#3194)
Co-authored-by: Carson Sievert <cpsievert1@gmail.com>
Co-authored-by: colin <colin@thinkr.fr>
Co-authored-by: Colin Fay <contact@colinfay.me>
2020-12-08 10:55:18 -06:00
Winston Chang
24a1ef9594 Clear selected date if not within min/max range (#3188) 2020-12-07 09:13:48 -06:00
Carson Sievert
c5adef0a05 Add 'auto' brush fill and stroke (#2864)
* Add 'auto' brush fill and stroke

* getStyle() from utils

* Update getThematicOption()

* Use getThematicOption() helper in startPNG(), too
2020-12-04 16:49:08 -06:00
Carson Sievert
508c197446 getCurrentOutputInfo() bugfix (#3189) 2020-12-04 16:38:48 -06:00
Carson Sievert
473ec834fe radioButtons() and checkboxGroup() accessibility (#3187)
Co-authored-by: Carson Sievert <cpsievert1@gmail.com>
Co-authored-by: JooYoung Seo <sjysky@gmail.com>
2020-12-04 15:53:53 -06:00
Carson Sievert
66968904bf Cleaner logic for conditional CSS styles (#2671)
* Cleaner logic for conditional CSS styles

It's really only plotOutput() that behaves differently;
previously it was not possible to specify a NULL width
or height and not get broken styles

* require dev version of htmltools

Co-authored-by: Joe Cheng <joe@rstudio.com>
2020-12-04 15:52:50 -06:00
Hadley Wickham
f169792e59 Experiment with error message (#3007) 2020-12-04 14:20:30 -06:00
Winston Chang
39a23af138 Merge pull request #3038 from rstudio/carson/bugfix/dateInput 2020-12-04 13:36:38 -06:00
Winston Chang
d8715819dc Build JS files 2020-12-04 13:27:51 -06:00
Carson
12444807e8 Better setting of bootstrap-datepicker start/end dates, closes #2703 2020-12-04 13:27:13 -06:00
Winston Chang
92077d47a1 Merge pull request #3042 from rstudio/carson/feature/aria-live 2020-12-04 13:08:03 -06:00
Winston Chang
4f54276e1b yarn build 2020-12-04 13:07:38 -06:00
Carson
ac30848019 Also default to aria-live='polite' when input bindings are about to receiveMessage 2020-12-04 13:07:11 -06:00
Carson
921650f53b When binding shiny outputs, have the 'aria-live' attribute default to 'polite', closes #2987 2020-12-04 13:07:11 -06:00
Winston Chang
72d81e8a85 Add label to private$currentThemeDependency 2020-12-04 12:32:55 -06:00
Carson Sievert
5c5974106d Properly attach jqueryui dependency when drag_drop plugin is used (#3185)
* Properly attach jqueryui dependency when drag_drop plugin is used, closes #3183

* write a unit test
2020-12-04 10:52:26 -06:00
Winston Chang
c2cbd3a127 Create session$currentThemeDependency only when needed (#3182)
Co-authored-by: Carson Sievert <cpsievert1@gmail.com>
2020-12-04 09:47:18 -06:00
Winston Chang
8e5aedec00 Do correct assignment of resizeObserverCreated (#3177) 2020-12-04 08:58:52 -06:00
Winston Chang
13965acb37 getCurrentOutputInfo(): only create reactives when needed (#3180) 2020-12-03 17:16:33 -06:00
Winston Chang
8a99b9d401 Add label to reactive
Co-authored-by: Barret Schloerke <barret@rstudio.com>
2020-12-03 17:09:30 -06:00
Carson Sievert
f739a1d476 Set resolve = FALSE when getting thematic's bg option (#3178) 2020-12-03 17:02:12 -06:00
Winston Chang
87dd00be13 getCurrentOutputInfo(): only create reactives when needed 2020-12-03 16:15:04 -06:00
Winston Chang
8cd393597a Remove old note about Bootstrap 3 2020-12-03 09:09:27 -06:00
Winston Chang
b7366ef672 Remove outdated comments 2020-12-02 20:56:33 -06:00
Winston Chang
3d6329dee8 Add cacheWriteHook and cacheReadHook (#3173) 2020-12-02 16:17:08 -06:00
Winston Chang
2171420e0c Fix NA check 2020-12-02 16:03:07 -06:00
Winston Chang
e44a9b1ded Replace %OR% with %||% from rlang (#3172) 2020-12-02 12:14:07 -06:00
Winston Chang
bde5a88295 Fix test 2020-12-01 13:18:59 -06:00
Carson Sievert
11babd5567 Improve color contrasting in date and slider input (#3167)
* leverage bslib's color-contrast() in sliderInput()'s Sass and reduce number of git patches

* Use color-contrast() instead of color-yiq() in Bootstrap Datepicker
2020-11-25 11:39:00 -06:00
Carson Sievert
4c35d483bc Wait longer to disable old stylesheets (#3168) 2020-11-25 11:13:18 -06:00
Carson Sievert
d049558728 shinyAppTemplate()'s shinytest tests should be calling expect_pass() (#2943)
Co-authored-by: Winston Chang <winston@stdout.org>
2020-11-24 14:34:45 -06:00
Carson Sievert
8eed42387c Make sure dateInput() warns on empty string (#3165)
Co-authored-by: Winston Chang <winston@stdout.org>
2020-11-24 10:34:39 -06:00
Winston Chang
5b3366f35a Replace renderCachedPlot() code with bindCache() (#3163) 2020-11-23 14:34:52 -06:00
Winston Chang
fea7397c3b Merge pull request #3160 from rstudio/wch-bindevent-reactlog 2020-11-23 11:05:25 -06:00
runner
4a33582482 Document 2020-11-23 14:49:22 +00:00
Winston Chang
1bad0553b7 Fix labels for eventReactive 2020-11-20 15:46:18 -06:00
Winston Chang
ac0b723bb0 bindEvent(): alter observers in place and fix labels 2020-11-20 14:51:35 -06:00
Winston Chang
39454a6c09 Use enquos0, inject, and zap_srcref from rlang (#3157) 2020-11-20 11:07:06 -06:00
Winston Chang
569157aded Add reactive session$getCurrentTheme() (#3116)
Co-authored-by: Carson <cpsievert1@gmail.com>
2020-11-20 10:54:51 -06:00
Carson Sievert
d2d7770c76 require newest bslib version, follow up to #3155 (#3159) 2020-11-20 10:01:59 -06:00
Carson Sievert
5da846f1ce Always ship selectize HTML dependencies with name='selectize', closes #3125 (#3155) 2020-11-20 09:46:08 -06:00
Winston Chang
713c9ec923 Add render function quosure tests 2020-11-20 09:38:16 -06:00
Winston Chang
b3369616d2 bindCache: accept cache arg when used with renderPlot 2020-11-19 15:14:10 -06:00
Winston Chang
082b8ef080 bindCache: add documentation about renderPlot 2020-11-19 15:13:39 -06:00
Hadley Wickham
0fb9226a9b Minor bindCache doc tweaks (#3156) 2020-11-19 15:04:26 -06:00
Winston Chang
bb55f45d94 More bindCache documentation edits 2020-11-18 13:21:03 -06:00
Winston Chang
5b12980b7a Update bindEvent documentation 2020-11-18 12:39:20 -06:00
Winston Chang
493ef59dda Update bindCache documentation 2020-11-18 12:37:06 -06:00
Barret Schloerke
b42d835cbf Test visibility with latest promises (#3151)
Co-authored-by: Winston Chang <winston@stdout.org>
2020-11-18 11:36:28 -06:00
Winston Chang
d1d177f80f Merge pull request #3149 from rstudio/wch-plot-cache 2020-11-17 21:57:46 -06:00
Winston Chang
433e5814ed Add note about cleanup 2020-11-16 14:09:11 -06:00
Winston Chang
2bf9f42b49 Better cacheHint for renderPlot 2020-11-16 13:47:46 -06:00
Winston Chang
65efb573bd Hoist attributes when wrapping render functions 2020-11-16 13:12:27 -06:00
Winston Chang
26a701215d Cleaner way to pass in fitDims to renderPlot function 2020-11-16 12:08:22 -06:00
Winston Chang
3be7a20f40 Use enquos0 2020-11-16 11:00:27 -06:00
Winston Chang
6f8092f5a4 bindCache.shiny.renderPlot: Draw plot at size specified by sizePolicy() 2020-11-16 11:00:27 -06:00
Winston Chang
652fcfe799 First implementation of bindCache() for renderPlot() 2020-11-16 10:59:25 -06:00
Winston Chang
d7d03ee6a8 Convert ... to quosures 2020-11-16 10:59:25 -06:00
Winston Chang
dc6335ed4d Round pixelratio to two decimals (#3147) 2020-11-16 10:06:38 -06:00
Winston Chang
b421f6bd7f Destroy correct object. Closes #3145 2020-11-13 19:30:13 -06:00
Winston Chang
d4358e0793 Fix renderCachedPlot expression handling 2020-11-13 17:53:55 -06:00
Winston Chang
a8dfa0771f Merge pull request #3144 from rstudio/wch-non-quosure 2020-11-13 17:08:41 -06:00
Winston Chang
6df3ce4b19 Rename blast() to inject() 2020-11-13 15:13:33 -06:00
Winston Chang
8f40f8cab8 Add additional quosure tests 2020-11-13 15:11:18 -06:00
Winston Chang
0d5a2cee58 Use brackets
Co-authored-by: Barret Schloerke <barret@rstudio.com>
2020-11-13 15:04:11 -06:00
Winston Chang
8db4f41fa9 Update bindCache documentation 2020-11-13 15:03:17 -06:00
Winston Chang
b85b03583b Add cache hint tests 2020-11-13 14:56:25 -06:00
Winston Chang
28e18fe87b Update examples 2020-11-13 13:45:48 -06:00
Dean Attali
2c1961acd7 added ... support to icon(); fixes #3140 (#3143)
Co-authored-by: Winston Chang <winston@stdout.org>
2020-11-13 13:25:03 -06:00
Winston Chang
04386f1a5e reactivePoll: store environment 2020-11-13 13:11:35 -06:00
Winston Chang
9c915e52ca Add get_quosure function 2020-11-12 23:45:23 -06:00
Winston Chang
6b6ab48377 Don't unwrap quosures for key or event expressions 2020-11-12 22:16:00 -06:00
Winston Chang
bf36d07670 Add tests for quosures in reactive() and observe() 2020-11-12 18:17:02 -06:00
Winston Chang
7166192143 Bump rlang version dependency 2020-11-12 17:57:04 -06:00
Winston Chang
509f0790db Reactive functions don't unwrap quosures automatically 2020-11-12 17:10:49 -06:00
Winston Chang
67a776a39a Don’t automatically unwrap quosures 2020-11-12 16:57:05 -06:00
Winston Chang
d3701df4e6 Safer method for remove_source 2020-11-12 16:57:05 -06:00
Carson Sievert
0195e34a7b pre.shiny-text-output shouldn't set border-radius by default (#3142) 2020-11-12 15:31:04 -06:00
Winston Chang
0aa49c8a93 Rebuild shiny.js 2020-11-10 14:16:43 -06:00
Winston Chang
437de58922 Remove source refs for nested functions 2020-11-09 16:23:28 -06:00
Winston Chang
fc76cf21fb Merge pull request #3127 from rstudio/with-cache-event 2020-11-09 13:31:08 -06:00
Winston Chang
23d1b25c46 Bump version to 1.5.0.9005 2020-11-09 13:16:02 -06:00
Winston Chang
8bfb59875f Temporarily disable deprecatedEnvQuotedMessage 2020-11-09 13:10:51 -06:00
Winston Chang
36e866743d Documentation fixes 2020-11-09 11:00:13 -06:00
Winston Chang
d35c6e35ce Use is_false function 2020-11-09 10:55:17 -06:00
Winston Chang
e9afd8c99e bindCache documentation updates 2020-11-09 10:52:19 -06:00
Winston Chang
43b7c41c4f Rename withCache and withEvent to bindCache and bindEvent 2020-11-08 21:47:11 -06:00
Winston Chang
921f60475e Update withEvent help 2020-11-06 15:33:01 -06:00
Winston Chang
58433cda01 Add tests for ignoreNULL 2020-11-06 14:20:20 -06:00
Winston Chang
ed5eca5496 withEvent: invoke render function with ... 2020-11-06 14:19:59 -06:00
Winston Chang
eff4a1f23e Add cache hint to reactive expressions 2020-11-06 12:41:57 -06:00
Carson Sievert
9f72b15fcf Resend CSS info (via bindAll) when a restyle (i.e., setCurrentTheme()) happens, closes #3119 (#3134) 2020-11-05 18:03:21 -06:00
Winston Chang
8069ff2b05 Fixes for tests 2020-11-05 17:02:56 -06:00
Winston Chang
10deddf2f0 Export quoToFunction 2020-11-05 16:57:35 -06:00
Winston Chang
3ad1c4076d Make renderCachedPlot accept quosures 2020-11-05 16:37:48 -06:00
Winston Chang
943f31e117 Fix cacheHint=FALSE 2020-11-05 16:37:18 -06:00
Winston Chang
c43bc195e7 Use cacheHint 2020-11-05 14:25:19 -06:00
Winston Chang
92b1e8f256 Fixes for withCache and render functions 2020-11-05 09:20:23 -06:00
Winston Chang
985970d320 Include user expression in cache key for render functions 2020-11-04 18:07:26 -06:00
Winston Chang
5eabaa5207 Allow render functions to accept quosures 2020-11-04 18:07:08 -06:00
Carson Sievert
7f60ecc725 Have slider's fg/bg defaults fallback to body colors if input colors are transparent, closes #3130 (#3131)
* Have slider's fg/bg defaults fallback to body colors if input colors are transparent, closes #3130

* Add comment

* Rename
2020-11-04 17:59:02 -06:00
Winston Chang
7c635e1283 Remove unused function 2020-11-04 12:53:50 -06:00
Carson Sievert
4727a7adf4 rename bootstraplib package to bslib (#3132) 2020-11-04 11:50:55 -06:00
Winston Chang
8940f14dde Fixes for R CMD check 2020-11-03 14:59:08 -06:00
Winston Chang
2fd0ce1a09 Add withEvent observer tests 2020-11-03 13:35:08 -06:00
Winston Chang
638bcc0f85 Mark some render functions as uncacheable 2020-11-03 13:12:23 -06:00
Winston Chang
d411da3114 Fix variable names 2020-11-03 13:04:11 -06:00
Winston Chang
0acae46835 Document withCache 2020-11-03 13:04:10 -06:00
Winston Chang
61cc61d9aa Add methods for withEvent and withCache 2020-11-03 13:03:35 -06:00
Winston Chang
194320d163 Remove cachedReactive() 2020-11-03 13:03:33 -06:00
Winston Chang
902bfb8628 Convert observeEvent and eventReactive to use withEvent 2020-11-03 13:02:57 -06:00
Winston Chang
b25d72f698 Streamline reactive() and observe() 2020-11-03 13:02:57 -06:00
Winston Chang
a4d8f541dd Fix test 2020-11-03 13:02:57 -06:00
Winston Chang
6aaf2ff4d5 Add withEvent.Observer 2020-11-03 13:02:57 -06:00
Winston Chang
b0f77d6591 Store original function as attribute on wrapper 2020-11-03 13:02:57 -06:00
Winston Chang
f2885dafd2 Add functions for extracting parts out of reactive expressions 2020-11-03 13:02:57 -06:00
Winston Chang
b0725e0153 Add withCache and withEvent functions 2020-11-03 13:02:49 -06:00
Winston Chang
4ce62034ce Convert reactive() and observe() to accept quosures 2020-11-03 13:01:27 -06:00
Winston Chang
7d4c0ad611 Remove extra argument 2020-11-03 13:01:17 -06:00
Winston Chang
d189cd9f23 Use cache objects from cachem package (#3118)
Co-authored-by: Carson Sievert <cpsievert1@gmail.com>
2020-11-03 12:01:17 -06:00
Winston Chang
f61ba70bb9 Merge pull request #3094 from rstudio/reactive-cached 2020-10-29 11:26:26 -05:00
Winston Chang
6e48692637 More code review changes 2020-10-29 11:13:22 -05:00
Winston Chang
f7b1bc0e5c Move key after ... 2020-10-29 10:19:16 -05:00
Winston Chang
a213d6f7e1 Increase size of diskCache 2020-10-29 10:16:07 -05:00
Winston Chang
a7d793ecf9 Code review feedback 2020-10-29 10:13:39 -05:00
Winston Chang
5d25481f66 Add remove_srcref for R<3.6 2020-10-29 10:13:10 -05:00
Winston Chang
77a8a783de cachedReactive: add tests for quosures 2020-10-28 20:11:03 -05:00
Winston Chang
0492eb7958 Update cachedReactive docs about cache collisions 2020-10-28 19:28:06 -05:00
Winston Chang
d37feea299 Rename args for cachedReactive 2020-10-28 19:16:12 -05:00
Winston Chang
ffb9ad2094 Merge pull request #3113 from rstudio/wch-fix-options-modules 2020-10-28 15:22:02 -05:00
Winston Chang
1e63dfc4c5 Bump recursion depth to 20 2020-10-28 15:15:12 -05:00
Winston Chang
051cc51d4b Handle shinyOptions in nested modules 2020-10-28 13:58:17 -05:00
Carson Sievert
56dd92fee8 Register all theme dependencies to be processes since _new_ HTML dependencies may be added to the theme object (#3115) 2020-10-28 13:58:07 -05:00
Winston Chang
51b835b57f Merge pull request #3114 from rstudio/wch-warn-package 2020-10-27 21:19:40 -05:00
Winston Chang
ccd7342986 Check for NAMESPACE file 2020-10-27 15:33:23 -05:00
Winston Chang
82decaa070 Fix use of shinyOptions in modules 2020-10-27 15:15:23 -05:00
Winston Chang
d1e808d090 Update NEWS 2020-10-27 15:12:27 -05:00
Winston Chang
7aad389338 Warn when running app in a R package directory 2020-10-27 15:12:24 -05:00
Winston Chang
7e07c460de Rebuild shiny.min.css 2020-10-27 14:07:24 -05:00
Carson Sievert
81a8ec3ce1 pre.shiny-text-output should have a border-radius set by default (#3111) 2020-10-23 13:20:25 -05:00
Carson Sievert
800f0a216d Get session$setCurrentTheme() working on IE11 & improve timing of disabling old stylesheets (#3097)
* disable stylesheet on next tick to avoid FOUC

* fix regex matching logic

* Avoid regex and remove stylesheet's ownerNode after disabling

* Use inline <style> as opposed to <link> tags when restyling for IE11 compatibility

* Be more careful to avoid possibility of removal modifying styleSheets

* Use inline <style> for IE; otherwise update the <link>

* Update srcjs/output_binding_html.js

Co-authored-by: Winston Chang <winston@stdout.org>

* Update browser.js to correctly detect IE11

* remove redundant if statements

Co-authored-by: Winston Chang <winston@stdout.org>
2020-10-23 11:06:42 -05:00
Winston Chang
dade7dc069 Increase default memory and disk cache size 2020-10-23 00:38:20 -05:00
Winston Chang
b271d0a9a2 Add valueExpr to cache key 2020-10-23 00:36:18 -05:00
Winston Chang
5daa0bc38e Handle future objects 2020-10-22 20:06:03 -05:00
Winston Chang
22665dc9b4 cachedReactive: add label arg 2020-10-22 16:00:41 -05:00
Winston Chang
a99f11fb10 Extract reactive label code into exprToLabel() 2020-10-22 15:58:50 -05:00
Winston Chang
81824575e6 Use consistent interface for preserving visibility 2020-10-22 00:01:32 -05:00
Winston Chang
f6d010056a Skip visibility tests with old versions of rlang 2020-10-21 23:50:24 -05:00
Winston Chang
ffd20bcc6e hybrid_chain: preserve visibility 2020-10-21 23:50:24 -05:00
Winston Chang
55eaaa869d Cache errors and visibility 2020-10-21 18:22:33 -05:00
Winston Chang
c2e66ca474 Split setVisible into two functions 2020-10-21 14:57:02 -05:00
Winston Chang
62b848c2e2 Throw error if no cache object 2020-10-21 14:55:48 -05:00
Winston Chang
dbb657bd91 Merge pull request #3091 from rstudio/carson/feature/border-radius 2020-10-21 09:30:50 -05:00
Winston Chang
de871b79b0 Use ellipsis to check for empty args 2020-10-20 21:19:14 -05:00
Winston Chang
146a6d459d Rebuild docs 2020-10-20 21:18:58 -05:00
Winston Chang
9fb1dd18a7 Mention quosures 2020-10-20 21:11:04 -05:00
Winston Chang
9ae894d9e3 Use spookyhash 2020-10-20 21:08:27 -05:00
Winston Chang
56e0fbdb05 Update tests for cachedReactive 2020-10-20 21:04:40 -05:00
Winston Chang
e6325629a9 Add eventExpr to cachedReactive() 2020-10-20 21:04:03 -05:00
Carson
9a3329acc7 yarn build 2020-10-20 18:13:55 -05:00
Carson
75ab225d84 Make sure shiny.scss can be compiled without Bootstrap 2020-10-20 18:09:41 -05:00
Carson
883668ac93 Use Bootstrap's border-radius mixin (mainly so BS4's enable-rounded works as expected) 2020-10-20 18:06:56 -05:00
Winston Chang
c5f2dece49 Specify UTF-8 encoding for error page
This supersedes PR #3039
2020-10-20 14:35:04 -05:00
Winston Chang
b55bc5318e Add cachedReactive example with actionButton 2020-10-16 15:59:40 -05:00
Winston Chang
a39450c2b2 Add tests for cachedReactive error handling 2020-10-16 15:26:58 -05:00
Winston Chang
b784068701 More documentation for cachedReactive 2020-10-15 18:58:41 -05:00
Winston Chang
bac4e68b89 Add support for async in cachedReactives 2020-10-15 17:19:34 -05:00
Winston Chang
20e95a4cab Add tests for cachedReactive 2020-10-15 17:19:34 -05:00
Winston Chang
96da457db3 Add cachedReactive 2020-10-15 17:19:34 -05:00
Winston Chang
37b8715cff Move resolve_cache_object out of renderCachedPlot 2020-10-15 17:19:34 -05:00
Barret Schloerke
7aa3a243ba Make template test less brittle and failures more verbose (#3096)
Also updated a pkgdown check
2020-10-15 11:32:50 -04:00
Winston Chang
f2b549f9cd Merge pull request #3095 from rstudio/get_option_null 2020-10-14 15:55:46 -05:00
Barret Schloerke
bc58dba0ad Add list default to getShinyOption("themeDependencyFuncs") call
Does NOT work on R <= v3.6.3

```r
x <- NULL
x[[length(x) + 1]] <- identity
```
2020-10-14 16:24:22 -04:00
Barret Schloerke
8ef9be5290 Explicitly state the default value in getShinyOption(x, default) calls 2020-10-14 16:23:07 -04:00
Winston Chang
d95560db09 Merge pull request #3085 from rstudio/carson/feature/restyle 2020-10-14 10:17:51 -05:00
Winston Chang
98f64df738 Dependency fixes 2020-10-14 10:06:42 -05:00
Winston Chang
8634e372da bs_dependency_dynamic -> bs_dependency_defer 2020-10-14 09:42:16 -05:00
Winston Chang
cbda7633e0 Update MockShinySession 2020-10-13 16:00:15 -05:00
Winston Chang
8f00cf50ca Fix typo 2020-10-13 15:57:52 -05:00
Winston Chang
acca28075b Merge branch 'master' into carson/feature/restyle
Also rebuild shiny.js
2020-10-13 15:56:53 -05:00
Winston Chang
9a563463dd Add namespacing for bs_dependency() 2020-10-13 15:32:00 -05:00
Winston Chang
1ede94b09e Remove registerThemeDependency from pkgdown 2020-10-13 15:30:56 -05:00
Winston Chang
7f41a54c4e Move bootstraplib to Imports 2020-10-13 14:49:51 -05:00
Winston Chang
6cfab79ce9 Make setCurrentTheme() a ShinySession method 2020-10-13 14:47:40 -05:00
Carson Sievert
f33b3c7eef Update R/bootstrap.R 2020-10-13 14:15:12 -05:00
Carson
93d78ae2b0 prevent caching on restyle and account for fact that href may include hostname 2020-10-13 12:37:02 -05:00
Winston Chang
c498b02289 textAreaInput() doesn't work as expected for relative width (#2049)
Squashed commit of the following:

commit a823dd5d7da6fafba69f783e112d71d9dcd09c5f
Author: Winston Chang <winston@stdout.org>
Date:   Mon Oct 12 12:59:41 2020 -0500

    Remove trailing whitespace

commit ae55b519fb0f7d97f559e2f487063366926aa41d
Author: Winston Chang <winston@stdout.org>
Date:   Mon Oct 12 12:52:04 2020 -0500

    Move NEWS item to correct location

commit aa89abc247be1bf5cdf093ff7fe7c51711821438
Merge: ee98773f a1ff7652
Author: Winston Chang <winston@stdout.org>
Date:   Mon Oct 12 12:47:21 2020 -0500

    Merge branch 'master' into shrektan-textarea-style

commit ee98773f1d
Author: shrektan <shrektan@126.com>
Date:   Sat Aug 24 10:35:23 2019 +0800

    correct the NEWS entry

commit b468d8f013
Author: shrektan <shrektan@126.com>
Date:   Sat Aug 24 10:32:52 2019 +0800

    the width of textarea should be specified in the parent div.

commit 5abdcf9260
Merge: 03079f0a b07e553b
Author: shrektan <shrektan@126.com>
Date:   Sat Aug 24 09:54:27 2019 +0800

    resolve conflicts

    Merge remote-tracking branch 'origin/master' into textarea-style

    # Conflicts:
    #	R/input-textarea.R

commit 03079f0a14
Author: shrektan <shrektan@126.com>
Date:   Mon May 7 16:08:05 2018 +0800

    Fixed a bug that `textAreaInput()` doesn't work as expected for relative `width`.
2020-10-12 13:01:44 -05:00
Winston Chang
30b62e6f18 Update bootstrap dependency code 2020-10-09 17:57:50 -05:00
Barret Schloerke
ec18ef651b Add missing space for html lang (#3093)
Followup from https://github.com/rstudio/shiny/pull/3087
2020-10-08 11:02:55 -04:00
Joe Cheng
aad23686fa Bump version number 2020-10-07 16:43:28 -07:00
Joe Cheng
1c85ecd7c0 Bump development version 2020-10-07 16:20:32 -07:00
Winston Chang
a1ff765235 Merge pull request #3055 from rstudio/joe/bugfix/freeze-invalidation 2020-10-07 17:36:16 -05:00
Hadley Wickham
a30ba9226d Implement reactiveConsole() (#3092)
* Implement reactiveConsole(). Fixes #2518

* Also includes makeReactiveBinding tweaks
  * use `reactiveConsole()` to provide a nicer example
  * simplified the implementation using `reactiveVal()`
  * remove from documentation indexes since you probably don't want to be promoting this function
2020-10-07 15:37:14 -05:00
Joe Cheng
980a1e53a7 tabsetPanel binding: unconditionally trigger change on receiveMessage
This brings it into line with all of the other input bindings.
The only exception is sliderInput, which has a more complicated
codepath that goes out of its way to force the slider, for its
own reasons; I didn't change the slider for fear of breaking
something, and it also doesn't exhibit the problem I'm here to
fix (next paragraph).

The goal is to ensure that if forgetLastInput is called on an
input, and then that input receives a message (updateXXXInput)
to update its value, BUT the new value is the SAME as its
existing value, that the input binding still acts like something
changed. This is because we need the id/value to go through
the InputSender code path, and alert the server if a previously
frozen input is now thawed.
2020-10-06 14:30:21 -07:00
Joe Cheng
00092cd2a8 NEWS 2020-10-06 14:29:29 -07:00
Joe Cheng
53ddb54936 Forgot to actually force invalidation for freezeReactiveValue(input) 2020-10-06 14:28:50 -07:00
Joe Cheng
ea1e307a51 Preserve existing (CRAN) behavior of freezeReactiveVal/freezeReactiveValues(non-input), but warn
We don't think anyone is using the freeze functions in the ways
that we are deprecating, if so they should contact us via the
link provided.

If it turns out nobody complains, we can remove the problematic
functions. If people complain, then we'll find out what they're
using them for and we can fix them properly.
2020-10-06 14:28:49 -07:00
Joe Cheng
17bc1e2e06 Force invalidation on freeze 2020-10-06 14:28:49 -07:00
Joe Cheng
ed8f3b730b Address ("fix" is too strong a word) #1791, #2946: freeze/thaw
1. freezeReactiveValue(input, "x") is called, inside a renderUI
   or in an observer that then calls updateXXXInput
2. Some reactive output tries to access input$x, this takes a
   reactive dependency but throws a (silent) error
3. When the flush cycle ends, it automatically thaws

What's *supposed* to happen next is the client receives the new
UI or updateXXXInput message, which causes input$x to change,
which causes the reactive output to invalidate and re-run, this
time without input$x being frozen.

This works, except when the renderUI or updateXXXInput just so
happens to set input$x to the same value it already is. In this
case, the client would detect the duplicate value and not send
it to the server. Therefore, the reactive output would not be
invalidated, and effectively be "stalled" until the next time it
is invalidated for some other reason.

With this change, freezeReactiveValue(input, "x") has a new side
effect, which is telling the client that the very next update to
input$x should not undergo duplicate checking.
2020-10-06 14:28:49 -07:00
Carson
0e109d5237 shiny.css should also be using bs_runtime_dependencies() 2020-10-05 16:21:14 -05:00
Winston Chang
f672226a3d Merge pull request #3087 from rstudio/jooyoungseo-lang-a11y 2020-10-05 15:42:26 -05:00
Carson
481dccd085 Don't export setCurrentTheme() (just provide it as a public session method) 2020-10-05 15:21:59 -05:00
Barret Schloerke
9612f1c3c8 Use a for loop over an lapply to get better error reporting 2020-10-05 15:56:27 -04:00
Barret Schloerke
9e1e5f61a3 Use inline template logic 2020-10-05 15:48:51 -04:00
Barret Schloerke
99a566f473 Tell htmltools that the template is a complete template 2020-10-05 15:17:27 -04:00
Barret Schloerke
1012307467 Make sure lang is set in helper method 2020-10-05 15:16:57 -04:00
Barret Schloerke
b729f45eaf Add missing assignment from merge w/ master 2020-10-05 14:36:11 -04:00
Barret Schloerke
cab799e6ee Add missing close bracket 2020-10-05 14:34:51 -04:00
Carson
a06322d155 No need to capture options since the options are set at render-time 2020-10-05 13:23:59 -05:00
Barret Schloerke
d836cb2a2c Use helper function to cleanly create <html> start tag given the lang val 2020-10-05 12:14:05 -04:00
Barret Schloerke
2249c7a28a Use @inheritParams bootstrapPage to inherit lang definition 2020-10-05 11:58:21 -04:00
Barret Schloerke
0d0422c0a7 Use lang <- getLang(ui) and ui <- setLang(ui, lang) methods 2020-10-05 11:57:17 -04:00
Barret Schloerke
5ea556ee77 Fix docs bug 2020-10-05 11:50:16 -04:00
Barret Schloerke
a34496663b Merge branch 'lang-a11y' of https://github.com/jooyoungseo/shiny into jooyoungseo-lang-a11y 2020-10-05 11:48:00 -04:00
Carson
abeaa71d8d wip generalized real-time theming via setCurrentTheme() 2020-10-02 17:32:57 -05:00
Carson
281a427718 Allow Shiny.renderDependencies() to re-render stylesheets, if requested
Also, make getCurrentTheme() aware of the reactive theme set by bootstraplib::bs_themer()
2020-10-02 11:13:19 -05:00
Carson Sievert
03ab966cdc Make shiny.css bootstraplib aware; use jquerylib (#3060)
* Sassify shiny.css (& make it themable); gut json2 dependency (was there for IE8 support)

* Always serve a compressed bundle; remove shiny.css

* Use getCurrentTheme() and make sure shinyDependencies is a function

* Make sure we have sass/rprojroot before running checkBuilt.sh

* Need repos set

* Compare against bleeding edge of sass

* Perform built check with testthat (copying the approach taken for pkgdown checks)

* Update tests/testthat/test-built-files.R

Co-authored-by: Winston Chang <winston@stdout.org>

Co-authored-by: Winston Chang <winston@stdout.org>
2020-10-02 10:59:59 -05:00
Winston Chang
3dcb810346 Merge pull request #3083 from rstudio/is-bs-theme 2020-10-01 14:17:18 -05:00
Carson
d6eef8b3e1 Add getCurrentTheme to pkgdown 2020-10-01 13:47:59 -05:00
Carson
a770f1cbf2 yarn build 2020-10-01 13:40:50 -05:00
Carson
a5687df9b4 make sure is_bs_theme() is available 2020-10-01 13:33:49 -05:00
Carson Sievert
202881cbbd Localized bootstraplib themes (#3062)
* Get rid of the bootstraplib option and simply use bootstraplib when a theme is active

* Restore previous bootstraplib theme when exiting a file/dir based runApp

* wip use latest htmltools+bootstraplib to sketch out local theme API

* Don't do anything with bootstraplib's global state and make sure bs_theme is an expected value

* typo

* better docs

* bugfix

* Use the new, more general, tagFunction() instead

* Set the theme object as a part of the page layout (instead of in shinyApp())

* rollback the structural changes to selectizeIt() to avoid breaking code that makes assumptions about the return value of selectInput()

* set shinyOption() in bootstrapLib(), not bootstrapPage()

* Add a helper for checking whether theme is a bs_theme

* Make theme a required arg in bootstrapSass

* Have bootstrapLib() call shinyOption() at render-time, and document why it works

* Have bootstrapPage() always place bootstrapLib(theme) at the top of the tagList()

* Only set shinyOption() when an application is running at render-time (otherwise; throw a warning)

* code review

* Export a new getCurrentTheme() for Shiny developers to access the theme's Sass code

* bump version
2020-10-01 13:19:18 -05:00
Winston Chang
24ac3b9d8b Reogranize shinyOptions documentation 2020-09-30 15:55:27 -05:00
Winston Chang
47c1fb88b9 Merge pull request #3080 from rstudio/wch-shinyoptions-session 2020-09-29 10:54:14 -05:00
Winston Chang
170b143b17 Document cache option, remove bootstraplib 2020-09-29 10:44:49 -05:00
Winston Chang
3854b49c35 Document shiny.autoload.r option 2020-09-29 10:37:08 -05:00
Winston Chang
bae4f604b5 Update NEWS 2020-09-29 10:34:43 -05:00
Winston Chang
36f32e14d3 Add shinyOptions scoping tests 2020-09-28 19:15:20 -05:00
Winston Chang
9e521e6927 Add missing paren 2020-09-28 17:44:05 -05:00
Winston Chang
4176f541fc Add test for captureAppOptions()
Co-authored-by: Barret Schloerke <barret@rstudio.com>
2020-09-28 17:40:34 -05:00
Winston Chang
18f2afbf85 Fix missing itemize 2020-09-28 16:34:16 -05:00
Winston Chang
f9a94d9758 Merge pull request #3075 from rstudio/wch-rm-ie-upload 2020-09-28 16:03:51 -05:00
Winston Chang
d1e672e3e3 Remove $saveFileUrl method 2020-09-28 16:03:19 -05:00
Winston Chang
202b924e63 Separate docs for options and shinyOptions 2020-09-28 10:43:08 -05:00
Winston Chang
4c3342aa99 Get rid of .globals$testMode 2020-09-25 14:44:59 -05:00
Winston Chang
b1e5dd1d1d Remove .globals 2020-09-25 14:16:10 -05:00
Winston Chang
d43ebfbdb9 Remove withLocalOptions 2020-09-25 14:15:34 -05:00
Winston Chang
cfadd8307b Copy app and session-level shinyOptions at instantiation time 2020-09-25 14:06:36 -05:00
Winston Chang
fa6cf9832d Add session-level shinyOptions 2020-09-24 20:55:17 -05:00
Winston Chang
0075b0da33 Annotate runApp and use initCurrentAppState() 2020-09-24 20:35:03 -05:00
Winston Chang
59c6367cb5 Use getCurrentAppState() for shinyOptions instead of .global$options 2020-09-24 20:33:35 -05:00
Winston Chang
194323a9ee Removed useless option setting
This option is immediately cleared by the next line of code.
2020-09-24 19:52:10 -05:00
Winston Chang
1ca437e4ee Add tests for captureAppOptions 2020-09-24 19:48:10 -05:00
Winston Chang
77e43b9f50 Rename consumeAppOptions to captureAppOptions and provide example 2020-09-24 19:47:48 -05:00
Winston Chang
a23f4b0224 Merge pull request #3078 from rstudio/wch-rename1 2020-09-24 19:03:23 -05:00
Winston Chang
0541c90980 Re-document 2020-09-24 14:53:38 -05:00
Winston Chang
b73a263de8 Rename server-orig.R back to server.R 2020-09-24 14:47:01 -05:00
Winston Chang
d7ffee68cf Merge branch 'wch-rename' into wch-rename1 2020-09-24 14:46:30 -05:00
Winston Chang
89cd42b904 Create server-resource-paths.R from server.R 2020-09-24 14:45:37 -05:00
Winston Chang
404185eb8c Merge branch 'wch-rename' into wch-rename1 2020-09-24 14:44:47 -05:00
Winston Chang
8c29a81b12 Create runapp.R from server.R 2020-09-24 14:43:46 -05:00
Winston Chang
9b42c6c379 Merge branch 'wch-rename' into wch-rename1 2020-09-24 14:42:48 -05:00
Winston Chang
03c2dd9e4b Rename server.R server-orig.R 2020-09-24 14:40:09 -05:00
Winston Chang
d8274c3d8c Create viewer.R from server.R 2020-09-24 14:37:25 -05:00
Winston Chang
85b5fb090f Add back shinyapp.R 2020-09-24 14:32:20 -05:00
Winston Chang
2adef311ed Merge branch 'wch-rename-fix' into main 2020-09-24 14:31:17 -05:00
Winston Chang
7050d0b8ad Remove shinyapp.R 2020-09-24 14:30:42 -05:00
Winston Chang
8358144a4f Rename file 2020-09-24 14:28:15 -05:00
Winston Chang
44e083e0a9 Re-document 2020-09-24 12:58:06 -05:00
Winston Chang
a5418cf6ee Rename app.R to shinyapp.R 2020-09-24 12:57:27 -05:00
Winston Chang
c74630d6eb Split knitr.R from app.R 2020-09-24 12:55:53 -05:00
Winston Chang
157d4ac9a9 Split knitr.R from app.R 2020-09-24 12:48:32 -05:00
Winston Chang
8228613c01 Create knitr.R from app.R 2020-09-24 12:47:21 -05:00
Winston Chang
b907e17b70 Rebuild shiny.js 2020-09-24 10:49:13 -05:00
Winston Chang
aa7000427c Update NEWS 2020-09-24 10:48:57 -05:00
Winston Chang
8562c90454 Remove allowDataUriScheme because it is no longer needed 2020-09-24 10:47:27 -05:00
Winston Chang
5a9a04cd72 Remove IE8 and IE9 file upload support 2020-09-24 10:47:27 -05:00
Winston Chang
6b32611356 Rebuild shiny.js 2020-09-24 10:41:01 -05:00
colin
770ebc394f updateRadioButton with character(0) (#3043)
Squashed commit of the following:

commit a095d75b67a0bad439e8d6c495ef81af25c0b1a9
Author: Winston Chang <winston@stdout.org>
Date:   Thu Sep 24 10:30:47 2020 -0500

    Update NEWS

commit 715a10ebd63c34eb2f464a7388e0b89b994bee0f
Author: Winston Chang <winston@stdout.org>
Date:   Thu Sep 24 10:24:24 2020 -0500

    Update docs for radioButtons about having none selected

commit eff9036884693002a84f84df16cf699be2358c1c
Author: Winston Chang <winston@stdout.org>
Date:   Thu Sep 24 10:15:59 2020 -0500

    Cleaner check for no selected radioButtons

commit 1666baa746f4dea986be4929720de2a5653acbb6
Merge: c0d35e84 b04ba393
Author: Winston Chang <winston@stdout.org>
Date:   Thu Sep 24 10:02:16 2020 -0500

    Merge branch '2688' of https://github.com/ColinFay/shiny into ColinFay-2688

commit b04ba393b8
Author: colin <colin@thinkr.fr>
Date:   Thu Sep 24 08:37:58 2020 +0200

    changed the test structure

commit 866a86946a
Author: colin <colin@thinkr.fr>
Date:   Sun Sep 13 20:50:44 2020 +0200

    restore old `$escape` behavior

commit d45af353fd
Author: colin <colin@thinkr.fr>
Date:   Fri Sep 11 08:54:25 2020 +0200

    added trailing ; and space before {

commit 5e95ee03a1
Author: colin <colin@thinkr.fr>
Date:   Thu Sep 10 21:55:02 2020 +0200

    return early if the value is undefined in setValue of radio

commit 24ac6ec624
Author: colin <colin@thinkr.fr>
Date:   Thu Sep 10 21:53:41 2020 +0200

    Testing that the type of val is a string, instead of relying on the length

commit 18ec3b8540
Author: colin <colin@thinkr.fr>
Date:   Wed Sep 9 22:08:45 2020 +0200

    Radio buttons can now be reset with character(0), and their value is set to NULL

    Close #2688 and close #2266

commit d7f66165d0
Author: colin <colin@thinkr.fr>
Date:   Wed Sep 9 22:08:06 2020 +0200

    Correct bug when $escape received an empty value
2020-09-24 10:38:12 -05:00
Joe Cheng
c0d35e84b1 Allow setting the state of RestoreContext (#3053)
* Allow setting the state of RestoreContext

This setter only sets public fields, but it's still necessary because
the RestoreInputSet R6 class is not exported.

(I needed this functionality for shinytableau config dialogs to do a
bookmark-like restore, but not at all based on querystring)

* Use list instead of values to prevent accidental mutation

See discussion here:
https://github.com/rstudio/shiny/pull/3053#discussion_r488948453

* Rebuild JS for new version number
2020-09-21 13:27:59 -07:00
Andrew Baxter
5e74478864 Remove test for date object length>1 (Closes #2936) (#3061)
Co-authored-by: Winston Chang <winston@stdout.org>
2020-09-16 17:11:06 -05:00
Winston Chang
46852e2051 Include sources in source maps
Uglify changed the option to include sources; this fix reinstates them.
2020-09-15 15:48:55 -05:00
Winston Chang
b9dded0bef Rebuild JS assets 2020-09-15 15:37:03 -05:00
Winston Chang
6d05f403a5 yarn upgrade 2020-09-15 15:34:47 -05:00
Winston Chang
8368634f85 Merge pull request #2959 from rstudio/joe/feature/select-choices-warning 2020-09-15 15:21:58 -05:00
Winston Chang
8d57d909b4 Merge branch 'master' into joe/feature/select-choices-warning 2020-09-15 15:21:45 -05:00
Winston Chang
9b7855d597 Add more authors 2020-09-15 15:13:42 -05:00
Winston Chang
6a5e1b9998 Add Barret to Authors 2020-09-15 13:15:04 -05:00
Carson Sievert
af6e558699 Make sure we only include one version of Bootstrap (#3048)
* Make sure we only include one version of Bootstrap and throw a warning if both bootstraplib and theme file is provided

* code review
2020-09-11 17:52:08 -05:00
Carson Sievert
26d4dddffd Remove modalButton() from pkgdown reference (it's not included on modalDialog()) (#3046) 2020-09-11 15:04:53 -05:00
Hadley Wickham
e2765b4881 Document modalButton with modalDialog (#2907) 2020-09-11 08:49:21 -05:00
Hadley Wickham
9796b25f33 Combine point events into one doc file (#2906) 2020-09-10 17:47:45 -05:00
Carson Sievert
01b8d3a314 More themable dateInput()/dateRangeInput() (#2964)
* upgrade bootstrap-datepicker from 1.6.4 to 1.9.0; setup infrastructure for bootstraplib theming

Note also that the 000 patch is no longer relevant as 1.9.0 includes the same fix https://github.com/uxsolutions/bootstrap-datepicker/pull/2009

* Patch sass code for BS4 support and more general color contrasting

* Wrap sass compilation into reusable function

* remove check warning

* Have bootstrapPage() use bootstraplib

* yarn build

* Use new output_template()

* Deprecate bootstrapLib() in favor of bootstraplib::bootstrap()

* Require bootstraplib 0.1.0.9001

* Sync up DESCRIPTION

* document

* rollback changes to pkgdown
2020-09-09 15:20:59 -05:00
Carson Sievert
50c48de0de More themable selectInput() (#2950)
* Add option to use bootstraplib and have selectInput() theming variables

* Use getShinyOption()

* Have useBsTheme() error out with informative messages if a theme isn't active

* Better Sass variables defaults that account for both bootswatch themes and bs_theme_base_colors()

* Add Carson as an author

* Provide better BS3/BS4 selectize sass variable defaults as a patch to the source files

* tidy up tools script

* add sass to suggests

* yarn install && yarn build

* Wrap sass compilation into reusable function

* Bring -color-item closer to -color-input

* Leverage the new sass::output_file()

* naming change

* Sync up with other PRs

* Sync up DESCRIPTION

* Forgot to update CSS output file logic

* document
2020-09-09 15:02:05 -05:00
Carson Sievert
bfc90da054 More themable sliderInput() (#2958)
* More themable sliderInput()

* Slider's accent color default should derive from primary theme color

* Remove custom theming args (skin, accentColor, sassVars) but still support theming via bootstraplib

* Wrap sass compilation into reusable function

* remove check warning

* Make font-family configurable; auto-contrast fromto handle text color; increase color contrasting (for accessbility)

* Sync up with other PRs

* Sync up DESCRIPTION

* Forgot to update CSS output file logic

* document

* code review
2020-09-09 14:38:10 -05:00
JooYoung Seo
9d8d6fd6b1 Resolve NEWS conflict 2020-09-09 15:17:25 -04:00
Winston Chang
43344d9a78 Merge pull request #3009 from jooyoungseo/landmark-a11y
Added a11y semantic landmarks for main and sidebar panels
2020-09-09 13:33:04 -05:00
Winston Chang
01a593c857 Rebuild docs 2020-09-09 13:14:39 -05:00
Winston Chang
1b2dd11a4c Merge pull request #2944 from daattali/patch-2 2020-09-09 13:12:36 -05:00
Winston Chang
d90a2c4801 Add links to functions
Co-authored-by: Carson Sievert <cpsievert1@gmail.com>
2020-09-09 13:12:04 -05:00
Winston Chang
f065c21ee6 Merge pull request #2945 from daattali/patch-3
Documentation: say that withProgress returns the value of its express…
2020-09-09 13:11:20 -05:00
Winston Chang
d0324bd497 Merge pull request #3027 from ColinFay/issue-3024 2020-09-09 13:10:31 -05:00
Hadley Wickham
e57fba07db Allow passing server function directory to testServer() (#2965) 2020-09-03 17:01:02 -05:00
Winston Chang
5cb279cf4e Merge pull request #3035 from rstudio/wch-cache-log
Make sure cache logging appends to file
2020-09-02 10:46:45 -05:00
Winston Chang
4f728b0387 Merge pull request #3034 from rstudio/wch-disk-cache-logic 2020-09-02 10:46:33 -05:00
Winston Chang
927ae08a47 Remove unneeded paste0 2020-09-02 10:42:57 -05:00
JooYoung Seo
a28dc47e30 Added es5-shim removal in NEWS.md (#3032) 2020-09-01 21:01:41 -04:00
Winston Chang
b43ee13dd8 Make sure cache logging appends to file 2020-09-01 19:30:42 -05:00
Winston Chang
ad5ad5a675 Update NEWS 2020-09-01 19:20:47 -05:00
Winston Chang
198f7d171e Fix DiskCache pruning logic when max_n and max_size are used. Closes #3033 2020-09-01 19:19:55 -05:00
JooYoung Seo
549425cb81 Merge master branch 2020-08-31 19:12:26 -04:00
JooYoung Seo
6023165268 Merge master branch 2020-08-31 19:02:41 -04:00
Carson Sievert
2a7273c254 Merge pull request #3030 from rstudio/plot-arg-order
Move `alt` parameter after `...`
2020-08-31 17:23:04 -05:00
Winston Chang
8640934410 Move alt parameter after ... 2020-08-31 16:28:43 -05:00
Winston Chang
20bc4e7caa Merge pull request #3006 from jooyoungseo/alttext 2020-08-31 15:49:24 -05:00
Barret Schloerke
9f83058b78 Do not record the reactlog when enabling shinytest (#3025) 2020-08-31 10:39:14 -04:00
colin
ffedf29db4 Other Rds generated by running devtools::document() on the package 2020-08-29 22:27:49 +02:00
colin
00219d342a All update*Input docs now inheritsParams from their standard counterpart
Will close #3024
2020-08-29 22:26:10 +02:00
Winston Chang
753400144d Update diskCache docs and rebuild 2020-08-28 08:58:30 -05:00
Winston Chang
854a732f47 Update NEWS 2020-08-28 08:57:38 -05:00
Winston Chang
03eaf07526 Merge pull request #3016 from aalucaci/issue-2984
Issue 2984
2020-08-28 08:56:16 -05:00
Carson Sievert
d04c12d8cb Merge pull request #3023 from rstudio/carson/bugfix/downloadButton
Change the evaluation rules for the icon promise in downloadButton()
2020-08-27 13:36:44 -05:00
Carson Sievert
afddd3543e Apply suggestions from code review
Co-authored-by: Barret Schloerke <barret@rstudio.com>
2020-08-27 13:35:06 -05:00
Carson
d9459a855d Allow icon arg to reference other downloadButton args 2020-08-27 11:12:09 -05:00
Carson
efbcfca126 Change the evaluation rules for the icon promise in downloadButton(), fixes #3022 2020-08-27 11:07:09 -05:00
Angela Lucaci-Timoce
916675a9bd renderCachedPlot: improved documentation 2020-08-26 21:03:00 +02:00
Colin Fay
7b43617954 downloadButton() icon can now be changed via the icon parameter (#3010) 2020-08-25 15:17:49 -05:00
Winston Chang
09b89bccfd Fix NEWS entry 2020-08-25 13:14:58 -05:00
Winston Chang
1190ee07a9 Remove unused cacheContext class 2020-08-25 13:12:01 -05:00
Barret Schloerke
c4dcf405bb Fix reactiveValuesToList reactlog label (#3017)
Co-authored-by: Barret Schloerke <schloerke@gmail.com>
Co-authored-by: Winston Chang <winston@stdout.org>
2020-08-25 11:49:22 -04:00
JooYoung Seo
c844ea6f07 Added missing alt arg 2020-08-20 10:51:32 -04:00
JooYoung Seo
19704c151a White space formatting to match the lines together
Co-authored-by: Barret Schloerke <barret@rstudio.com>
2020-08-20 10:00:43 -04:00
JooYoung Seo
1281ba18cd Cleaned code 2020-08-19 17:17:40 -04:00
JooYoung Seo
f1f2fae420 Update R/shinyui.R
Used attr instead of attributes()

Co-authored-by: Carson Sievert <cpsievert1@gmail.com>
2020-08-19 15:43:46 -04:00
JooYoung Seo
5809070b05 Used isTRUE inverse instead of isFALSE 2020-08-19 15:23:36 -04:00
JooYoung Seo
2c492540ce Merged master 2020-08-19 15:04:02 -04:00
JooYoung Seo
61556b505d Used attribute instead of option 2020-08-19 15:02:01 -04:00
Winston Chang
d6a4bc87e8 Fix whitespace 2020-08-19 11:48:35 -05:00
JooYoung Seo
e49f4696e6 Updated NEWS.md 2020-08-19 10:50:23 -04:00
JooYoung Seo
4219f50141 Added a11y semantic landmarks for main and sidebar panels 2020-08-19 10:43:55 -04:00
JooYoung Seo
19da003291 Redocumented for alt param 2020-08-18 17:19:45 -04:00
JooYoung Seo
f0765e3d6a Updated alt param description 2020-08-18 17:05:47 -04:00
JooYoung Seo
8dac345512 Updated NEWS.md 2020-08-18 16:44:43 -04:00
JooYoung Seo
ce101843f0 Made alt param reactive 2020-08-18 15:43:04 -04:00
JooYoung Seo
d56dc3a237 Update R/render-cached-plot.R
Co-authored-by: Barret Schloerke <barret@rstudio.com>
2020-08-18 14:25:16 -04:00
JooYoung Seo
28cffb2e25 Update R/render-plot.R
Co-authored-by: Barret Schloerke <barret@rstudio.com>
2020-08-18 14:24:08 -04:00
JooYoung Seo
d2d169fea3 Update R/render-plot.R
Co-authored-by: Barret Schloerke <barret@rstudio.com>
2020-08-18 14:23:17 -04:00
JooYoung Seo
a5eb1b15d2 Added alt param 2020-08-16 16:11:18 -04:00
JooYoung Seo
23dbb0b41c Unified eol in Gruntfile.js for all the platforms (#3001)
* Unified eol char for all the platforms

* Reran yarn build after merging master
2020-08-13 16:54:44 -04:00
Winston Chang
c72ae68de5 Merge pull request #2993 from jooyoungseo/selectize-a11y 2020-08-13 13:56:39 -05:00
JooYoung Seo
7c1f87aed3 Rebuilt via WSL 2020-08-12 19:20:42 -04:00
JooYoung Seo
6ec0ac1651 Reran yarn after updating grunt 2020-08-12 16:34:08 -04:00
JooYoung Seo
9dc84e5c2b Merge branch 'master' into selectize-a11y 2020-08-12 15:24:29 -04:00
JooYoung Seo
1e17b55f49 Got rid of es5 info and corrected selectize version 2020-08-12 15:24:18 -04:00
JooYoung Seo
6a4c8556a3 Merge branch 'master' into lang-a11y 2020-08-12 15:07:46 -04:00
JooYoung Seo
488f1c8b83 Made sure lang length to be 1 2020-08-12 15:07:23 -04:00
JooYoung Seo
e2537d8e93 Used withr for applying datepicker patches 2020-08-12 12:56:13 -04:00
JooYoung Seo
6d35cb6c77 yarn grunt instead of yarn build 2020-08-07 11:20:27 -04:00
Carson Sievert
8ce7f64679 Merge pull request #2995 from jooyoungseo/IonRangeSlider-updateScript
Tweaked updateIonRangeSlider.R
2020-08-07 09:40:42 -05:00
JooYoung Seo
5cd6250f05 Updated NEWS.md 2020-08-06 17:17:08 -04:00
JooYoung Seo
4872cd91a5 Reran yarn build 2020-08-06 17:00:54 -04:00
JooYoung Seo
08e84e2ca0 Tweaked updateSelectize.R 2020-08-06 16:22:47 -04:00
JooYoung Seo
40889c9637 Used withr when applying patches and doing yarn build 2020-08-06 16:12:11 -04:00
JooYoung Seo
010ba6f214 Update tools/updateIonRangeSlider.R
Co-authored-by: Carson Sievert <cpsievert1@gmail.com>
2020-08-06 15:12:26 -04:00
JooYoung Seo
2f8dc860ff Update tools/updateIonRangeSlider.R
Co-authored-by: Carson Sievert <cpsievert1@gmail.com>
2020-08-06 15:11:55 -04:00
JooYoung Seo
88f61f0d45 Update tools/updateIonRangeSlider.R
Co-authored-by: Carson Sievert <cpsievert1@gmail.com>
2020-08-06 15:11:37 -04:00
JooYoung Seo
16a5aa7489 Update tools/updateIonRangeSlider.R
Co-authored-by: Carson Sievert <cpsievert1@gmail.com>
2020-08-06 15:11:19 -04:00
JooYoung Seo
89fd2b2ed3 Tweaked updateIonRangeSlider.R 2020-08-06 13:14:11 -04:00
JooYoung Seo
a16769061e Removed es5 shim 2020-08-05 20:31:33 -04:00
JooYoung Seo
3be76145b7 Updated grunt file to minify selectize-plugin-a11y 2020-08-05 20:23:23 -04:00
JooYoung Seo
e9d27fa632 Update tools/updateSelectize.R
Co-authored-by: Carson Sievert <cpsievert1@gmail.com>
2020-08-05 17:36:16 -04:00
JooYoung Seo
be706e4bb7 Added updating scripts and LICENSE info 2020-08-05 17:15:02 -04:00
JooYoung Seo
b87c4d5623 Appended a11y plugin to options 2020-08-05 11:33:58 -04:00
JooYoung Seo
03a260f26a Defaulting a11y plugins 2020-08-04 22:32:11 -04:00
JooYoung Seo
ae3e007a5f Updated selectize-plugin-a11y 2020-08-04 16:58:23 -04:00
JooYoung Seo
cfbf76d898 Added selectize-plugin-a11y 2020-08-04 14:45:34 -04:00
Carson Sievert
0b82b121cb Merge pull request #2978 from jooyoungseo/dateInput-a11y
* Fixed #2951: Added labels and title for dateInput and dateRangeInput
2020-08-03 09:48:46 -05:00
JooYoung Seo
643ebb4946 Merge branch 'master' of https://github.com/rstudio/shiny into dateInput-a11y 2020-07-31 17:12:40 -04:00
Carson
8693eed3ec use expect_equal() instead of grepl() in expectation 2020-07-31 15:05:05 -05:00
Winston Chang
766b910150 Add info about calling registerInputHandler from .onLoad 2020-07-28 13:58:36 -05:00
Winston Chang
545843ffe6 Fix pkgdown.yml 2020-07-28 12:59:39 -05:00
Winston Chang
39e7b23d5b Merge pull request #2934 from hadley/render-text-print 2020-07-28 11:15:15 -05:00
Hadley Wickham
9d0db6f74c Remove renderPrint from pkgdown index 2020-07-27 15:37:39 -05:00
Winston Chang
78fb25329c NEWS edits 2020-07-27 14:39:37 -05:00
Winston Chang
7db6a7b57a Update NEWS 2020-07-27 14:38:00 -05:00
Winston Chang
76f70179c0 Merge pull request #2982 from ColinFay/patch-2 2020-07-27 14:36:50 -05:00
Winston Chang
d6aecfe9ae Update NEWS 2020-07-27 14:28:13 -05:00
Winston Chang
1354d3dec1 Merge pull request #2981 from ColinFay/patch-1 2020-07-27 14:26:36 -05:00
colin
955ae817d8 switched from * to + in the regex that checks resource path 2020-07-27 21:20:03 +02:00
colin
aee9589c1a Simple regex in addResourcePath 2020-07-25 22:42:09 +02:00
colin
48ac0f55c3 check that the prefix is not only made of dots 2020-07-25 22:38:41 +02:00
colin
831c0a340c redoc the runExample() 2020-07-24 11:46:54 +02:00
Colin Fay
210d297d18 Update server.R 2020-07-24 11:08:28 +02:00
Colin Fay
afbcf9039e Allow to pass resource path that starts with .
This will close #2980
2020-07-24 09:33:52 +02:00
JooYoung Seo
e8eadc1a09 Updated test 2020-07-23 11:11:02 -04:00
JooYoung Seo
f234b7015c Date format instead of format 2020-07-22 16:49:22 -04:00
JooYoung Seo
8de38b3415 Updated NEWS.md 2020-07-22 13:22:45 -04:00
JooYoung Seo
0f132fc180 * Fixed #2951: Added labels and title for dateInput and dateRangeInput 2020-07-22 13:10:45 -04:00
Hadley Wickham
e597c24f35 Merged upstream/master into hadley-render-text-print 2020-07-19 12:59:01 -05:00
Joe Cheng
1d7a913d29 Add tests 2020-07-17 09:56:33 -07:00
Joe Cheng
f89131205d Warn on 1000+ choices for selectInput/selectizeInput 2020-07-17 09:56:05 -07:00
Winston Chang
abc6a98d0f Merge pull request #2974 from jooyoungseo/news-patch 2020-07-16 18:10:59 -05:00
JooYoung Seo
9415e79ff3 Merge branch 'master' of https://github.com/rstudio/shiny into news-patch 2020-07-16 16:47:56 -04:00
JooYoung Seo
6269022536 Followed convention for NEWS.md 2020-07-16 16:47:43 -04:00
Joe Cheng
6ad2125ee7 Calling runApp("app.R") ignored options passed into shinyApp() (#2969)
* Calling `runApp("app.R")` ignored options passed into `shinyApp()`

Fixes #1942.

This was caused by shinyAppDir_appR (which was called by shinyAppDir
and shinyAppFile, which were called when runApp() was used with either
no args or a path) dropping shinyApp() options on the floor.

Fixing this was not as simple as not dropping those options. Before
this commit, the app.R file was not invoked until after the host and
port options (possibly others) were already finalized. This commit
changes the effective sequence of events during startup.

- Calling shinyAppFile() or shinyAppDir() that points to a single-file
  app, now causes the app.R file to be sourced immediately; previously,
  sourcing would happen only at onStart(). (Honestly, the new behavior
  seems less surprising anyway.)

- The support files (R/*.R) for app.R were sourced during onStart. I've
  moved this so that the support files are sourced right before app.R
  is, and re-sourced every time app.R reloads.

* Code review feedback

* Code review feedback: improve test

* Roxygenize
2020-07-16 13:46:32 -07:00
JooYoung Seo
f5d7523a4f Merge pull request #2937 from jooyoungseo/fileInput-a11y
Improved fileInput keyboard accessibility
2020-07-16 16:16:55 -04:00
JooYoung Seo
ce31b9af7e Removed an issue URL from NEWS.md 2020-07-16 16:13:21 -04:00
JooYoung Seo
fc5d980a52 Resolved NEWS.md conflict 2020-07-16 15:43:35 -04:00
JooYoung Seo
9ea726732a Merge branch 'master' of https://github.com/rstudio/shiny 2020-07-16 15:40:10 -04:00
JooYoung Seo
db5f9cca73 Added Bootstrap accessibility plugin (#2911)
Co-authored-by: Winston Chang <winston@stdout.org>
2020-07-16 14:26:11 -05:00
JooYoung Seo
06fb4f6972 Merge branch 'master' of https://github.com/rstudio/shiny 2020-07-16 15:25:28 -04:00
Winston Chang
f045f9cf1b Merge pull request #2970 from rstudio/joe/feature/ui-http-response-2 2020-07-16 14:11:37 -05:00
Winston Chang
1752f57c7d Remove html5shiv and respond.js 2020-07-16 13:56:00 -05:00
Joe Cheng
7eb4bc15b8 Use soft breaks in NEWS 2020-07-16 10:09:43 -07:00
Joe Cheng
707b5ea851 Avoid spurious use of connections 2020-07-16 10:08:51 -07:00
Joe Cheng
fe9f679051 on.exit(add = TRUE)
Co-authored-by: Carson Sievert <cpsievert1@gmail.com>
2020-07-16 10:03:43 -07:00
Joe Cheng
368a49be36 Add PR number to NEWS 2020-07-15 15:53:34 -07:00
Joe Cheng
80f0c5f5d7 Allow function-based UI to respond to non-GET requests 2020-07-15 15:51:36 -07:00
Joe Cheng
a5a7224228 Allow function-based UI to return a complete HTTP response
This allows the UI handler to have total control over the response,
including status code (for redirects) or content type (for serving
up files).
2020-07-15 14:36:54 -07:00
JooYoung Seo
d616cf045b Resolved NEWS.md 2020-07-15 11:17:52 -04:00
JooYoung Seo
8186ae060d Merge branch 'master' of https://github.com/rstudio/shiny 2020-07-15 11:12:04 -04:00
Carson Sievert
c46e80c711 Merge pull request #2941 from rstudio/showtext-fix
Include the pixelratio when setting showtext dpi
2020-07-14 13:53:22 -05:00
Carson
0735ebd7a8 update news 2020-07-14 13:52:18 -05:00
Carson
391bbaa73b Do the same when replaying plot 2020-07-14 13:45:34 -05:00
Carson
fed96c0e45 Include the pixelratio when setting showtext dpi 2020-07-14 13:45:34 -05:00
JooYoung Seo
f97f89a371 Merge branch 'master' of https://github.com/rstudio/shiny 2020-07-10 13:32:21 -04:00
Winston Chang
6352a5322b Rebuild documentation 2020-07-10 11:01:51 -05:00
JooYoung Seo
3473427484 Merge branch 'master' of https://github.com/rstudio/shiny 2020-07-10 11:30:59 -04:00
Winston Chang
d6c1733f0c Merge pull request #2917 from jooyoungseo/icon-a11y 2020-07-10 10:27:50 -05:00
JooYoung Seo
d641ac197b Merged recent shiny release 2020-07-10 11:16:10 -04:00
JooYoung Seo
6a0e41b05e Updated test-bootstrap.R 2020-07-10 11:09:44 -04:00
Winston Chang
e21a9a095e Merge pull request #2961 from rstudio/joe/misc/yarn-upgrade 2020-07-08 12:32:39 -05:00
Joe Cheng
56e1a0b939 Further dep upgrades 2020-07-03 09:23:52 -07:00
Joe Cheng
f9f9127a64 Build JS 2020-07-03 09:21:23 -07:00
Joe Cheng
e0628c4ae3 Upgrade build tools; fix Gruntfile.js for Windows 2020-07-03 09:17:37 -07:00
JooYoung Seo
43be342dea Merge branch 'master' of https://github.com/rstudio/shiny 2020-07-02 12:05:27 -04:00
Winston Chang
9cc7419700 Clarify how testServer expression is evaluated 2020-07-01 15:16:46 -05:00
Winston Chang
f559caf4d0 Bump version to 1.5.0.9000 2020-07-01 15:16:46 -05:00
Winston Chang
42af54ca04 Remove context() calls from example app 2020-06-30 13:27:08 -05:00
Dean Attali
9f55cd46d8 Documentation: say that withProgress returns the value of its expression. I didn't know if it does or doesn't and had to test it out, it should be explicit 2020-06-27 13:24:37 -04:00
Dean Attali
5956f6b123 Small documentation addition in withProgress (I did not re-compile roxygen) 2020-06-27 13:18:43 -04:00
JooYoung Seo
41e42b8a53 Improved fileInput keyboard accessibility 2020-06-24 13:28:02 -04:00
JooYoung Seo
f6f5fbd6fb Merge branch 'master' of https://github.com/rstudio/shiny 2020-06-24 13:09:11 -04:00
Hadley Wickham
c7618e3991 Combine documentation of renderPrint() and renderText()
Since they're so closely related, and it makes it easier to see how they differ.
2020-06-23 08:13:55 -05:00
Winston Chang
da6df5da9e Rebuild docs with dev version of roxygen
This is to work around errors in R CMD check with R-devel:
  Non-file package-anchored link(s) in documentation object
2020-06-19 12:15:55 -05:00
Winston Chang
480cc79de4 Merge branch 'master' into rc-v1.5.0 2020-06-19 11:45:14 -05:00
Barret Schloerke
231c13d9a5 run revdep. updates redep_cran notes 2020-06-19 11:09:15 -04:00
Winston Chang
000406ec0b Remove Remotes field 2020-06-18 15:14:11 -05:00
Winston Chang
44e0a8bcb2 Remove links from NEWS.md
The links can cause R CMD check --as-cran to fail, because of rate-limiting by GitHub.
2020-06-18 14:29:35 -05:00
Winston Chang
d2e88c7a2f Refer to shinytest migration function 2020-06-17 10:46:36 -05:00
JooYoung Seo
638cddcd5e Merge branch 'master' of https://github.com/rstudio/shiny 2020-06-11 16:33:21 -04:00
JooYoung Seo
a3924f4ab1 Updated aria code and NEWS.md 2020-06-11 16:23:57 -04:00
JooYoung Seo
5798c396ec Fixed an incorrect line in tools/README.md for IonRangeSlider 2020-06-11 15:07:43 -05:00
JooYoung Seo
b1983f0a83 Fixed an incorrect line in tools/README.md for IonRangeSlider 2020-06-11 15:51:31 -04:00
JooYoung Seo
aca9f562e1 Provided auto-label for icon() instead of aria-hidden 2020-06-11 11:51:31 -04:00
JooYoung Seo
8c6a830521 Updated NEWS.md 2020-06-09 15:48:38 -04:00
JooYoung Seo
9142cf19c0 Fixed lang attribute in templates 2020-06-09 14:55:45 -04:00
JooYoung Seo
887b7fb34a Fixed app.r for NULL value of lang argument 2020-06-09 14:29:15 -04:00
JooYoung Seo
1392547783 Redocumentation 2020-06-09 14:20:36 -04:00
JooYoung Seo
735b9b8c7a Updated related scripts, templates, and NEWS.md 2020-06-09 14:19:53 -04:00
JooYoung Seo
cba974ec34 Documentation 2020-06-08 20:10:17 -04:00
JooYoung Seo
421d588a2f Fixed lang attribute in template 2020-06-08 20:09:29 -04:00
JooYoung Seo
8b848277d2 Added lang ShinyOption 2020-06-08 20:08:23 -04:00
JooYoung Seo
8ae19c7243 Added lang attribute to the default template 2020-06-08 16:29:10 -04:00
Winston Chang
1e5051ef79 Merge pull request #2918 from ginberg/master
replace devtools by remotes
2020-06-05 09:42:53 -05:00
ginberg
d293dbc10f replace devtools by remotes 2020-06-05 15:26:07 +02:00
JooYoung Seo
703f481a9a Improved accessibility for icon() 2020-06-04 16:45:04 -04:00
Winston Chang
68f0c12cab Merge pull request #2902 from rstudio/alan-newsmd 2020-05-20 17:39:33 -05:00
Alan Dipert
8c7598f45d Drop testModule() from NEWS.md, fixes #2901 2020-05-20 22:33:02 +00:00
Barret Schloerke
192c4f239e bump version to 1.5.0. Build JS 2020-05-18 16:38:55 -05:00
Carson Sievert
64e09315fc Merge pull request #2900 from rstudio/jquery-3.5.1
Bump jQuery 3.5.0 to 3.5.1
2020-05-18 16:38:22 -05:00
Carson
db0c4155b8 news update 2020-05-18 16:28:36 -05:00
Carson
f971bfd80a Finish updating to jQuery 3.5.1, add a tools script, add documentation to tools/README.md 2020-05-18 16:25:40 -05:00
Carson
948244b45c Revert "Fixes #2896 by avoiding fatal JS exception in some collapsible navbar scenarios by patching a BS3 bug introduced https://github.com/twbs/bootstrap/pull/16011"
This reverts commit 4ba02c97a7.
2020-05-18 15:47:01 -05:00
Carson
c7fecbed7a bump jQuery 3.5.0 -> 3.5.1 2020-05-18 15:46:10 -05:00
Carson Sievert
f22cae98ef Merge pull request #2897 from rstudio/fix-collapsible-navbar
Fix collapsible navbar
2020-05-15 14:02:13 -05:00
Carson
4ba02c97a7 Fixes #2896 by avoiding fatal JS exception in some collapsible navbar scenarios by patching a BS3 bug introduced https://github.com/twbs/bootstrap/pull/16011 2020-05-15 12:38:24 -05:00
Winston Chang
0581dc7763 Remove old manual test app. Closes #2892 2020-05-12 16:30:24 -05:00
Winston Chang
77261d4872 Merge pull request #2891 from rstudio/wch-update-fontawesome 2020-05-12 16:26:10 -05:00
Winston Chang
cfd14ef169 Update NEWS 2020-05-12 16:25:12 -05:00
Winston Chang
c7cc76b044 Update tools/README.md
Co-authored-by: Barret Schloerke <barret@rstudio.com>
2020-05-12 16:16:57 -05:00
Winston Chang
44e1096753 Update README 2020-05-12 16:12:47 -05:00
Winston Chang
dc1c48ad4e Rebuild docs 2020-05-12 16:12:02 -05:00
Winston Chang
d9d29220cc Update NEWS 2020-05-12 16:04:05 -05:00
Winston Chang
6f744ef311 Update Font-Awesome to 5.13.0 2020-05-12 16:04:05 -05:00
Winston Chang
f7071f2231 Add updateFontAwesome script 2020-05-12 16:04:05 -05:00
Alan Dipert
ef75c9a35f Move callModule() to separate .Rd; add various links to docs (#2889)
* Move callModule() to separate .Rd; add various links to docs

* Remove callModule param from moduleServer docs

* document

* Update R/modules.R

* Rebuild docs

* Add callModule to pkgdown

Co-authored-by: Winston Chang <winston@stdout.org>
2020-05-12 12:46:41 -07:00
Winston Chang
4ca3c6c96a Clearer language for shinyAppTemplate prompt 2020-05-12 11:33:17 -05:00
Joe Cheng
82e98410ed isTempPath is now isTemp, simplified semantics (#2886)
* isTempPath is now isTemp, simplified semantics

- Now requires both the path and temp dir to exist
- isTemp(tempdir()) is now false
- Doesn't matter if it's files or directories

* Fix tests under R 3.4 and earlier

* fix comment

Co-authored-by: Carson Sievert <cpsievert1@gmail.com>
2020-05-11 20:05:12 -07:00
Winston Chang
dcd92f03db Merge pull request #2867 from rstudio/alan-mocksession-methods 2020-05-11 21:33:54 -05:00
Alan Dipert
ba6c747e55 Merge remote-tracking branch 'origin/master' into alan-mocksession-methods 2020-05-11 21:47:06 +00:00
Alan Dipert
b53b766ee5 Add reactive/promise test 2020-05-11 21:30:12 +00:00
Barret Schloerke
cd737fccb5 Run pre-revdepcheck for v1.5.0. Found 2 errors. Made 2 PRs (#2885) 2020-05-11 17:06:06 -04:00
Alan Dipert
7fb3acea96 get() => !!as.symbol() 2020-05-11 21:00:50 +00:00
Alan Dipert
867052f974 Fix new CMD check note 2020-05-11 20:49:36 +00:00
Alan Dipert
038e010819 testServer() doc update 2020-05-11 20:34:40 +00:00
Alan Dipert
7f5e42fdd5 Fix pkgdown test 2020-05-11 19:46:11 +00:00
Alan Dipert
2fe9b3dcbe Fix tempdir()-related problem 2020-05-11 18:55:28 +00:00
Winston Chang
89dbfcecbf Ensure file encoding is specified for sort_c 2020-05-11 13:42:10 -05:00
Alan Dipert
f4bda6b91f Ensure temp files passed to downloadHandler() content functions are deleted on session close 2020-05-11 18:28:39 +00:00
Alan Dipert
dba72ac8a7 Call session ended callbacks, fix related existing/broken test 2020-05-11 18:20:37 +00:00
Barret Schloerke
aedbfb11af Use GitHub Actions (#2876) 2020-05-11 14:18:10 -04:00
Winston Chang
43fd380e25 Merge pull request #2881 from rstudio/joe/feature/better-delete-file 2020-05-11 13:09:51 -05:00
Joe Cheng
2872100ff0 Code review feedback 2020-05-11 11:06:51 -07:00
Alan Dipert
afe81048c9 Pass namespaced names to renderFile() 2020-05-11 17:51:35 +00:00
Alan Dipert
9d44857d77 get_mocked_publics() cleanup 2020-05-11 17:49:10 +00:00
Alan Dipert
4a7d186f27 renderCachedPlot() support, minor reorg and misc. fixes 2020-05-08 23:02:06 +00:00
Joe Cheng
5b1fd12edd Unit tests 2020-05-08 14:28:46 -07:00
Joe Cheng
8309a2aed9 Safer default file deletion behavior for renderImage 2020-05-08 14:18:57 -07:00
Alan Dipert
e15d6a2239 sp 2020-05-08 19:56:52 +00:00
Alan Dipert
abf04ac96f roxygenation 2020-05-08 19:50:04 +00:00
Carson Sievert
8ec6275f9a Merge pull request #2879 from rstudio/revert-renderedFamily
remove renderedFamily info field
2020-05-08 14:44:05 -05:00
Carson
3e2bfb20f5 remove renderedFamily info field
Because no information is better than wrong information
https://bugzilla.mozilla.org/show_bug.cgi?id=1252821
2020-05-08 13:36:05 -05:00
Winston Chang
ee13087d57 Merge pull request #2878 from rstudio/revert-ragg 2020-05-08 13:29:43 -05:00
Alan Dipert
f2fd7de9db roxygenation 2020-05-08 18:28:41 +00:00
Carson
dcfd7e05ce shiny.useragg should default to FALSE 2020-05-08 13:27:54 -05:00
Winston Chang
e47b69c33a Merge pull request #2874 from rstudio/wch-app-template-tweaks 2020-05-08 10:58:55 -05:00
Winston Chang
383f78c8ca Fix link 2020-05-08 10:58:19 -05:00
Alan Dipert
54042d5150 export MockShinySession; document 2020-05-07 23:02:00 +00:00
Alan Dipert
90e6ffc928 <<- to <- 2020-05-07 22:57:09 +00:00
Alan Dipert
be65f49bbd sapply => names() <- + lapply 2020-05-07 22:43:47 +00:00
Alan Dipert
d81b8ff98f ensyms => list 2020-05-07 22:42:20 +00:00
Alan Dipert
9b5201e33c Return invisible in noop functions 2020-05-07 22:38:01 +00:00
Alan Dipert
588c1b91b9 Test reactive() + downloadHandler 2020-05-07 22:30:45 +00:00
Alan Dipert
eb63734792 getCurrentOutputInfo() works, and tests 2020-05-07 21:36:42 +00:00
Alan Dipert
22cc585180 downloadHandler() test 2020-05-07 21:14:27 +00:00
Alan Dipert
bd1631a649 downloadHandler() test 2020-05-07 21:12:46 +00:00
Alan Dipert
e12bde6cdb getCurrentOutputInfo() 2020-05-07 20:23:38 +00:00
Alan Dipert
7763ceefc0 Update private$downloads docs 2020-05-07 18:55:45 +00:00
Alan Dipert
05a7d998b9 registerDownload() and private$renderFile 2020-05-07 18:53:07 +00:00
Carson Sievert
4b676ac327 Merge pull request #2873 from rstudio/output-info-docs
Document the return value of getCurrentOutputInfo()
2020-05-07 12:14:58 -05:00
Carson
6ad1322734 Output context isn't well-defined 2020-05-07 12:08:32 -05:00
Alan Dipert
03248735ac Un-noop a couple things we need to implement 2020-05-07 16:36:31 +00:00
Winston Chang
8e5651490c Merge pull request #2851 from rstudio/tabsetPanelBody_value_check 2020-05-07 11:17:21 -05:00
Barret Schloerke
0d7aa2a101 undo id parameter for example 2020-05-07 12:14:16 -04:00
Winston Chang
83669ced3d App template tweaks 2020-05-07 10:52:16 -05:00
Winston Chang
2a33d23165 Make runnable example for downloadButton 2020-05-07 10:51:24 -05:00
Alan Dipert
b7ae915784 Remove unnecessary constructor 2020-05-07 15:37:24 +00:00
Winston Chang
9fcfa25460 Merge pull request #2872 from rstudio/wch-sort-c 2020-05-07 10:26:28 -05:00
Carson
946eae00bd roxygen 2020-05-07 10:21:17 -05:00
Carson
e8ef33c9a1 Explain the return value of getCurrentOutputInfo() 2020-05-07 10:18:32 -05:00
Barret Schloerke
8c8654f2d8 feedback from @wch. Keep 'value' arg, drop 'id' 2020-05-07 10:55:12 -04:00
Winston Chang
4b744791f2 Add sort_c function for sorting in C locale 2020-05-07 09:47:02 -05:00
Barret Schloerke
5327cb33f9 Merge branch 'master' into tabsetPanelBody_value_check
* master:
  Remove trailing comma and extra return statement
  Remove check note about function not found
2020-05-07 10:44:02 -04:00
Barret Schloerke
d9ddc6fd90 Merge pull request #2871 from rstudio/schloerke-patch-2 2020-05-07 10:43:17 -04:00
Barret Schloerke
a94c2cfa1e Merge pull request #2870 from rstudio/schloerke-patch-1 2020-05-07 10:35:07 -04:00
Barret Schloerke
614bc6b480 Remove trailing comma and extra return statement 2020-05-07 10:34:09 -04:00
Barret Schloerke
47585174d8 Remove check note about function not found 2020-05-07 10:32:36 -04:00
Barret Schloerke
5dd11bcc9b Merge branch 'master' into tabsetPanelBody_value_check
* master: (63 commits)
  Use getStyle() to support old browsers
  safe-guard against NA values
  make shiny.useragg an unofficial option that takes priority over quartz
  smaller bump in version
  update news and add to comment
  Wrap styles in reactive() so that calling getCurrentOutputInfo() doesn't always invalidate
  Use is_available() more widely and remove unneeded complexity in check_suggested()
  comments
  generalize internal is_installed and use it in startPNG()
  Remove reference to helper-load.R that's no longer there
  Minor updates to shinyAppTemplate docs
  code review with Winston
  default to FALSE for now
  let showtext know about the resolution
  Pass check
  Rollback the custom device arg (may come later) in favor of a shiny.useragg option
  Auto values aren't resolved until plot time, so if we see one, resolve it
  change device bg default only if the thematic option is set
  somehow messed up rebase
  missed passing device in renderCachedPlot()
  ...
2020-05-07 10:22:59 -04:00
Alan Dipert
160d2123b2 roxygen tweaks 2020-05-07 05:42:53 +00:00
Alan Dipert
ca55ed3a21 Down to 1 missing method and 1 missing field 2020-05-06 22:58:07 +00:00
Alan Dipert
34fe820a26 Fix ls() usage, revert MockShinySession roxygen tags 2020-05-06 22:18:56 +00:00
Winston Chang
c7a4d23662 Merge pull request #2740 from rstudio/joe/feature/bs4-compat-plot-colors 2020-05-06 15:51:11 -05:00
Alan Dipert
432a7120f2 Clarify test logic; better output 2020-05-06 20:44:18 +00:00
Alan Dipert
7e8b5d28f7 fix tests 2020-05-06 20:18:24 +00:00
Carson
079871df38 Use getStyle() to support old browsers 2020-05-06 15:17:06 -05:00
Carson
c95d3ef07d safe-guard against NA values 2020-05-06 15:16:22 -05:00
Carson
acad455ccb make shiny.useragg an unofficial option that takes priority over quartz 2020-05-06 15:10:42 -05:00
Alan Dipert
fcc7df32ad Add instance methods in the constructor 2020-05-06 19:09:49 +00:00
Carson
c7f0484c37 smaller bump in version 2020-05-06 13:24:57 -05:00
Carson
3dac31a771 update news and add to comment 2020-05-06 13:21:17 -05:00
Alan Dipert
16357963d5 Add more noops and errors 2020-05-05 23:05:24 +00:00
Alan Dipert
7d7492b9aa roxygen flailing 2020-05-05 21:51:04 +00:00
Carson
26dff7e00e Wrap styles in reactive() so that calling getCurrentOutputInfo() doesn't always invalidate 2020-05-05 15:30:04 -05:00
Carson
cf410e310f Use is_available() more widely and remove unneeded complexity in check_suggested() 2020-05-05 13:30:01 -05:00
Carson
5d4855f86c comments 2020-05-05 12:26:58 -05:00
Carson
6d7e2b8a06 generalize internal is_installed and use it in startPNG() 2020-05-05 12:26:44 -05:00
Barret Schloerke
d37be0d059 Update tests/testthat/test-tabPanel.R
Co-authored-by: Hadley Wickham <h.wickham@gmail.com>
2020-05-05 12:39:02 -04:00
Barret Schloerke
d419ec5776 Update tests/testthat/test-tabPanel.R
Co-authored-by: Hadley Wickham <h.wickham@gmail.com>
2020-05-05 12:38:57 -04:00
Alan Dipert
c01f100858 WIP noop refactor party; collation brokn 2020-05-05 03:46:25 +00:00
Winston Chang
d8e380b53f Merge pull request #2860 from mine-cetinkaya-rundel/app-template-edits 2020-05-04 17:27:05 -05:00
Alan Dipert
6881c39c8d Use noop() 2020-05-04 20:19:00 +00:00
Mine Çetinkaya-Rundel
e7fa540403 Remove reference to helper-load.R that's no longer there 2020-05-02 11:20:44 +01:00
Mine Çetinkaya-Rundel
e92ba27893 Minor updates to shinyAppTemplate docs
More detail on how shinyAppTemplate choices + streamline shinytest/testthat listing
2020-05-02 11:05:50 +01:00
Carson
210792397d code review with Winston 2020-05-01 16:20:15 -05:00
Alan Dipert
91385967c1 A good test of real/mock session difference 2020-05-01 21:01:01 +00:00
Alan Dipert
0c8d27964b add mock method notify func 2020-05-01 20:01:24 +00:00
Alan Dipert
ed4fcb71f1 testServer(): Users can now pass in their own session 2020-05-01 15:03:50 +00:00
Carson
0738f6a2d6 default to FALSE for now 2020-04-30 18:14:20 -05:00
Carson
1e2a874067 let showtext know about the resolution 2020-04-30 17:50:19 -05:00
Carson
9d2f8cbd8a Pass check 2020-04-30 17:50:19 -05:00
Carson
dd1c653365 Rollback the custom device arg (may come later) in favor of a shiny.useragg option 2020-04-30 17:50:19 -05:00
Carson
1a0a53a26f Auto values aren't resolved until plot time, so if we see one, resolve it 2020-04-30 17:50:19 -05:00
Carson
97ea4e2a26 change device bg default only if the thematic option is set 2020-04-30 17:50:19 -05:00
Carson
b408d9348d somehow messed up rebase 2020-04-30 17:50:19 -05:00
Carson
44cfde7a0c missed passing device in renderCachedPlot() 2020-04-30 17:50:19 -05:00
Carson
db3d7ee436 bump version 2020-04-30 17:50:19 -05:00
Carson
a05f713e26 code review with Barret 2020-04-30 17:50:19 -05:00
Carson
dfb492493c Provide a device argument to renderPlot() and plotPNG() 2020-04-30 17:50:19 -05:00
Carson
7ddf4169b8 no need to call thematic 2020-04-30 17:50:19 -05:00
Carson
89d6a3d91a User-supplied bg to renderPlot should take 1st priority 2020-04-30 17:50:19 -05:00
Carson
16196eeaaa ragg will take priority over Cairo 2020-04-30 17:50:19 -05:00
Carson
393d4163c8 Auto-theming interface will come from thematic 2020-04-30 17:50:19 -05:00
Carson
5855aa2689 First pass at an auto-theming interface 2020-04-30 17:50:19 -05:00
Carson
4e59f55f11 wip font support 2020-04-30 17:50:19 -05:00
Carson
b269487a47 port auto-theming logic to new thematic package 2020-04-30 17:50:19 -05:00
Carson
dce4028786 sequential colorscale now mixes fg/bg with accent (for the endpoints) 2020-04-30 17:50:19 -05:00
Carson
819ad4c770 newpage should always come before ggplot_build 2020-04-30 17:50:19 -05:00
Carson
b10b6d4833 default to bg='white', not transparent 2020-04-30 17:50:19 -05:00
Carson
a3d224beaf suggest scales; other R CMD check things 2020-04-30 17:50:19 -05:00
Carson
164ad8c521 Add autoThemeOptions() to pkgdown 2020-04-30 17:50:19 -05:00
Carson
4c8ec8befe allow autoTheme options to be reactive 2020-04-30 17:50:19 -05:00
Carson
0692334a27 cleanup 2020-04-30 17:50:19 -05:00
Carson
be912cf2ce Set default scales via plot_env for old ggplot2 and options for new ggplot2 2020-04-30 17:50:19 -05:00
Carson
f942c088ec mix colors using scales::colour_ramp 2020-04-30 17:50:19 -05:00
Carson
330da2dcbb code review feedback; introduce autoThemeOptions() 2020-04-30 17:50:19 -05:00
Joe Cheng
afad0395ff Use htmltools::parseCssColors 2020-04-30 17:50:19 -05:00
Carson
ecd72f1bc0 Add sequential colorscale for ggplot2 based on the accent color
Also, some R CMD check fixes and other cleanup
2020-04-30 17:50:19 -05:00
Carson
867daeead7 Add accent (link) color and qualitative color palettes
Also, improved approach to adjusting various defaults based on fg/bg/accent
2020-04-30 17:50:19 -05:00
Carson
a20c3a397e make sure ggplot_apply_auto_colors always returns a built plot 2020-04-30 17:50:19 -05:00
Carson
a1a22e811f Report font-family and colors in getCurrentOutputInfo() if .shiny-report-theme class is present
Also, rename autocolors to autotheme as we'd like to support fonts and possibly more in the future

    Also, wrap ggplot2 default overriding and building logic into one function, so plotly can use it in a self-contained fashion
2020-04-30 17:50:19 -05:00
Joe Cheng
3fbbabd68a Better autocolors for bars and other geoms that don't have colour; lighter lattice defaults 2020-04-30 17:50:19 -05:00
Joe Cheng
47c1202535 Tweak ggplot2 colors to look closer to defaults 2020-04-30 17:50:19 -05:00
Joe Cheng
83a5feaaa8 More autocolor fixes
- Don't set graphical params if fg/bg are not set
- Make maybe_set_palette return the old palette
2020-04-30 17:50:19 -05:00
Joe Cheng
6e767fc71d More robust un-setting of autocolor params
Before this commit, any error would cause the params not to be restored.
If the error was in the initial parameter setting itself (as can occur
with lattice_set_params() at the moment), then not even the graphics
device would be restored, meaning that stopping the app and attempting
to plot would result in graphics being sent to a temp file somewhere
instead of the default graphics device.
2020-04-30 17:50:19 -05:00
Joe Cheng
303f264326 Implement plot.autocolors for cached plots 2020-04-30 17:50:19 -05:00
Carson
f73671845c Add support for lattice and better default palette() for col scaling 2020-04-30 17:50:19 -05:00
Carson
82c04caf3a facet strips shouldn't have stroke and fill should be a semi-lighten fg color 2020-04-30 17:50:19 -05:00
Carson
d8080d1336 only assign default for aes that are relevant and non-transparent 2020-04-30 17:50:19 -05:00
Carson
fc09d1c09a Support a named vector as an override to computed colors 2020-04-30 17:50:19 -05:00
Carson
65a47c01ec grep for hex codes properly and return exit length 0 character string if input is length 0 2020-04-30 17:50:19 -05:00
Carson
e9f2e0d7d7 wip 2020-04-30 17:50:19 -05:00
Winston Chang
ddcb31897d Merge pull request #2858 from rstudio/currentOutputInfo 2020-04-30 17:05:13 -05:00
Carson
eecdc0e24c update news 2020-04-30 14:56:14 -05:00
Carson
f642bcc954 Have getCurrentOutputInfo() return NULL instead of error if called in a non-reactive context (extension of #2707) 2020-04-30 14:54:09 -05:00
Carson Sievert
7dedac5880 Merge pull request #2857 from rstudio/jquery-3.5
Bump to jQuery 3.5.0
2020-04-30 14:47:22 -05:00
Carson
ee5362f81a news 2020-04-30 14:37:10 -05:00
Carson
1475137d4d yarn build 2020-04-30 14:27:10 -05:00
Carson
8ba028ebbb Use native String.trim() method since $.trim() is now deprecated 2020-04-30 10:35:14 -05:00
Carson
7cd385e8c2 Bump jquery 3.x to 3.5.0, closes #2856 2020-04-30 10:06:21 -05:00
Alan Dipert
41694b3666 testServer(): Properly capture module return values 2020-04-29 22:13:00 +00:00
Winston Chang
25314f370e Merge pull request #2852 from rstudio/remove_test 2020-04-28 11:14:06 -05:00
Barret Schloerke
664b88c1bc remove duplicate param docs 2020-04-28 11:06:45 -04:00
Barret Schloerke
d6adffa273 testServer does not return results. Do not test for it. 2020-04-28 10:58:44 -04:00
Barret Schloerke
5bd039a335 use 'id' instead of 'value' for tabPanel/tabPanelBody 2020-04-28 10:55:53 -04:00
Barret Schloerke
0782cc3c21 code feedback for tabPanelBody 2020-04-27 16:57:26 -04:00
Barret Schloerke
c73628cca1 Move 'value' to first arg position for tabPanelBody. 'value' is now required. Add tests 2020-04-27 16:10:36 -04:00
Winston Chang
8ffc5aa20c Merge pull request #2849 from daattali/patch-1 2020-04-27 13:50:31 -05:00
Winston Chang
89c2f09864 Clearer wording for dryrun option 2020-04-27 13:21:02 -05:00
Dean Attali
ee3115653c typo in NEWS 2020-04-25 01:15:25 -04:00
Winston Chang
48115fc150 Merge pull request #2842 from rstudio/missing_monitorHandle 2020-04-24 15:34:01 -05:00
Winston Chang
d804a363ae Merge pull request #2837 from rstudio/testServer_args 2020-04-24 15:33:49 -05:00
Barret Schloerke
867c084990 check if function, not if not null 2020-04-24 16:30:21 -04:00
Barret Schloerke
8ffbfca97b do not call monitorHandle unless it is set 2020-04-24 15:51:23 -04:00
Barret Schloerke
ca9a72d25c testServer should return invisible() 2020-04-24 10:06:35 -04:00
Barret Schloerke
acdbe8ef5e use list instead of rlang::list2 2020-04-23 17:47:52 -04:00
Alan Dipert
5cc3a5b71c Dynamic dots for MockShinySession$setInputs() (#2838)
* MockShinySession: add $click()

* Fix return value of MockShinySession$click()

* session$click() test w/ observeEvent

* session$click() test w/ observeEvent

* $click() examples

* $click, $setInputs: add \\dontrun

* $setInputs(): make dots dynamic

* document

* rm $click()
2020-04-23 16:36:27 -05:00
Winston Chang
bd587fd21b Fix pkgdown.yml 2020-04-23 16:36:01 -05:00
Barret Schloerke
0f580ff23d remove '../' from loadSupport calls as they will be found automatically now 2020-04-23 14:55:21 -04:00
Winston Chang
b0b105babc Merge pull request #2836 from hadley/interactive-helper-docs
Combine docs for nearPoints() and brushedPoints()
2020-04-23 13:46:03 -05:00
Hadley Wickham
3b0cc5f3a8 Rebuild docs 2020-04-23 13:37:26 -05:00
Barret Schloerke
e50981ccc0 replace ... with args in testServer 2020-04-23 14:19:03 -04:00
Winston Chang
24f3c20f26 Merge pull request #2814 from rstudio/hidden_tabset
Add `type = "hidden"` to `tabsetPanel`
2020-04-23 12:46:15 -05:00
Hadley Wickham
ca5d71a491 Combine docs for nearPoints() and brushedPoints()
* Mouse -> pointer
* Simplify panelvar docs
* Add new ggplot2 and brushing sections
2020-04-23 08:49:24 -05:00
Winston Chang
a022a2b4a4 Merge pull request #2766 from rstudio/joe/feature/autoreload-error
Support shiny.autoreload even when there are errors
2020-04-22 16:10:38 -05:00
Winston Chang
0cb618b9b1 Merge pull request #2834 from hadley/output-args
Remove deprecated arguments from plotOutput/imageOuput
2020-04-22 09:39:22 -05:00
Winston Chang
1f4927683e Merge pull request #2829 from rstudio/wch-migrate-shinytest
Add migrateLegacyShinytest function
2020-04-22 09:21:46 -05:00
Winston Chang
7c74399a5d Documentation edits 2020-04-22 09:18:06 -05:00
Winston Chang
52903b6ecd Do not flush when setting a returned value for a mock shiny ses… (#2832)
Do not flush when setting a returned value for a mock shiny session
2020-04-22 09:09:42 -05:00
Alan Dipert
a43244916b loadSupport(): fix global.R support, run global.R in appropriat… (#2831)
* loadSupport(): fix global.R support, run global.R in appropriate dir

* loadSupport(): Use withr::with_dir, fix global.R-related tests

* shiny.autoload.r: Ensure dir set to appDir before sourcing R/ files

* Use file.path.ci() to ensure case-insensitive filesystem compat in loadSupport() and findEnclosingApp()

* loadSupport(): Ensure proper source order of R/ files

* loadSupport(): Clarify test
2020-04-22 08:54:06 -05:00
Hadley Wickham
35be892e69 Remove deprecated arguments from plotOutput/imageOuput
These were deprecated in 0.11.1, which was released on 2015-02-11, i.e. >5 years ago.
2020-04-22 08:45:40 -05:00
Barret Schloerke
536e8ffb28 Do not set a returned value for an app
An app never has access to the returned value of a server function.  This DOES makes sense for modules, but not shiny apps.
2020-04-21 16:57:56 -04:00
Barret Schloerke
0241f07105 Do not flush when setting the returned value in a mocked shiny session
This requires $flushReact() to be called when wanting to access reactive values that do not require inputs to be set
2020-04-21 16:57:15 -04:00
Winston Chang
3570af90ab Update test for new function name 2020-04-17 17:32:45 -05:00
Winston Chang
fa3fa9e2ef Add migrateLegacyShinytest function 2020-04-17 17:28:03 -05:00
Winston Chang
83e2bb028f Small fixes 2020-04-17 17:27:37 -05:00
Alan Dipert
f50b7c4301 testServer() and loadSupport(): if app is a path, and not an ap… (#2823)
* Improve makeMask comment

* Added skeleton function and example

* Refinements to app template

* Template update

* Rename tests/shinytests/ to tests/shinytest/

* App template updates

* mask creation: clean up, document, and align with rlang::new_data_mask()

* Revert minor in mock session

* Document/fix mock session $setEnv() and $setReturned() behavior

* document

* simplify buildMask()

* minor

* simplify buildMask()

* simplify buildMask()

* add 12_counter test app to exercise runTests + testServer

* Add appobj test

* WIP loadSuppor for apps passed to testServer

* Revert "WIP loadSuppor for apps passed to testServer"

This reverts commit 2d519aca15.

* Found and fixed app obj lifecycle methods that testServer was not exercising when applicable

* Rename 12_counter to 12_template

* Rename utils.R to sort.R

* Updates from code review

* Move 12_template to app_template dir

* Add informative comments

* Simplify mask building, default app to "." in testServer()

* testServer(): Error when arguments provided to a server function

* Fix tests; don't default autoload to FALSE if not found

* Use withr::with_options in one particularly confusing shiny.autoload.r-related test

* testServer(): if app is a path, and not an app, walk up dirs until an app is found

* Fix tests on Windows - rprojroot uses winslash='/'

* testServer(): raise findEnclosingApp() call

* Add library(shiny) to top of test app

* document

* Use require(shiny) in testServer() it works without library(shiny)

* Revert "testServer(): raise findEnclosingApp() call"

This reverts commit 5801dee2a4.

* document

* loadSupport(): appDir now defaults to . and findEnclosingApp() occurs

* loadSupport() and testServer(): default app/appDir to NULL

* Remove sketchy test involving detach()

* Move findEnclosingApp() to utils.R

* Dropped rprojroot dep and moved findEnclosingApp() to utils

* Better error message

* findEnclosingApp(): Fix case when root is an app

Co-authored-by: trestletech <jeff.allen@trestletechnology.net>
Co-authored-by: Winston Chang <winston@stdout.org>
2020-04-17 16:04:40 -05:00
Winston Chang
41c9a0c395 shinyAppTemplate tweaks (#2828)
* shinyAppTemplate: Add dryrun option and print out changes

* Code cleanup

* Add shinytest version check

* Move is_template logic into function

* Use dirExists function

* Use version check compatible with dev version

* Small fixes

* More refactoring

* Fix message about shinytest

* Documentation formatting fixes
2020-04-17 15:53:51 -05:00
Barret Schloerke
12401b6588 Merge pull request #2826 from rstudio/barret_runTests2
Update runTests() add print method
2020-04-17 13:50:21 -04:00
Barret Schloerke
8edf8905a5 Merge pull request #2827 from rstudio/drop_serverR
Drop server.R template file
2020-04-17 13:37:26 -04:00
Barret Schloerke
d5cb8d187c code feedback 2020-04-17 13:24:00 -04:00
Barret Schloerke
328a066f0f merge news items 2020-04-17 11:08:37 -04:00
Barret Schloerke
42d314d592 safeguard testing by checking for some suggested packages 2020-04-17 11:02:19 -04:00
Barret Schloerke
d89d546e53 make sure shinytest is installed from github. Needs latest version 2020-04-17 10:40:20 -04:00
Barret Schloerke
1a558143c7 add comments 2020-04-17 10:39:45 -04:00
Barret Schloerke
ad7ffa2245 use mkdir_p to always create directories 2020-04-17 10:09:16 -04:00
Barret Schloerke
717ac420d9 fix test 2020-04-17 09:59:34 -04:00
Barret Schloerke
abff323eb6 display the test folder name when it fails 2020-04-17 09:50:54 -04:00
Barret Schloerke
03bc1ccd4a remove autoload.r test, as that code path doesn't exist anymore 2020-04-17 09:50:47 -04:00
Barret Schloerke
da408eeaff removed dplyr 2020-04-17 09:50:45 -04:00
Barret Schloerke
a2ba9bb26a Test module app 107_scatterplot. Use pretty paths when printing the runTests output 2020-04-17 09:50:42 -04:00
Barret Schloerke
16c41ed046 Document 2020-04-17 09:50:39 -04:00
Barret Schloerke
aeb3c9f094 Test many combinations of shinyAppTempalte combos. Do not full matrix as shinytest is slow to execute 2020-04-17 09:50:37 -04:00
Barret Schloerke
2562cc8220 shiny.autoload.r is not required for runTests anymore 2020-04-17 09:50:29 -04:00
Barret Schloerke
0647cd85e9 If no module is used with shinytest, do not test the module 2020-04-17 09:49:52 -04:00
Barret Schloerke
d57e7389d2 feedback - remove all non-module/server test files in the testthat dir if the R folder is not used 2020-04-17 09:49:50 -04:00
Barret Schloerke
3cb3316a95 Copy all files, but if they are glue files... use the template 2020-04-17 09:49:47 -04:00
Barret Schloerke
8ba03e1205 Have output$sequence test be conditional on if the r dir is used 2020-04-17 09:49:45 -04:00
Barret Schloerke
6a69d3c07b feedback - no expr = 2020-04-17 09:49:42 -04:00
Barret Schloerke
c054b8c9ab feedback - drop adhoc 2020-04-17 09:49:39 -04:00
Barret Schloerke
db6f7cceea feedback - Do not require req(input$size) 2020-04-17 09:49:37 -04:00
Barret Schloerke
0898ee1fba Remove runTests output 2020-04-17 09:49:27 -04:00
Barret Schloerke
6366c0a684 Add full template + runTests test 2020-04-17 09:48:01 -04:00
Barret Schloerke
f56eb42c90 use adhoc.R in stead of server.R in shinyAppTemplate 2020-04-17 09:48:01 -04:00
Barret Schloerke
6f3f21921e No longer need helper-support. testthat.R should do this before running 2020-04-17 09:47:56 -04:00
Barret Schloerke
b8c016c3e9 print the app folder name (if available), not just the test file name 2020-04-16 19:13:51 -04:00
Barret Schloerke
e5d3b1c1d5 Code feedback. snake case legacy_shinytest fn. add comments / change error 2020-04-16 19:13:51 -04:00
Barret Schloerke
fe140b6319 Update tests with the design that shinytest legacy can not be called. Add assert=FALSE where appropriate 2020-04-16 19:13:48 -04:00
Barret Schloerke
4e1e0aad8a Update to use withr / loadSupport 2020-04-16 19:13:03 -04:00
Barret Schloerke
84a5515a3d Throw error on legacy shinytest testing instead of allowing the legacy test structure 2020-04-16 19:13:03 -04:00
Barret Schloerke
0d5073f8ff Commit revert 2020-04-16 19:13:03 -04:00
Barret Schloerke
05a4a101db Update app to be consistent. Add testthat contexts 2020-04-16 19:13:03 -04:00
Barret Schloerke
848f18be2b Add contexts and pass all tests 2020-04-16 19:13:03 -04:00
Barret Schloerke
21c9079087 Update failure name 2020-04-16 19:13:03 -04:00
Barret Schloerke
2935192eec Enable broken adhoc test 2020-04-16 19:13:03 -04:00
Barret Schloerke
f896db033f Rename output 2020-04-16 19:13:03 -04:00
Barret Schloerke
b197afe1a0 Edit docs 2020-04-16 19:13:03 -04:00
Barret Schloerke
dd07f7f580 Document 2020-04-16 19:13:03 -04:00
Barret Schloerke
8376f9093b white space and small comments 2020-04-16 19:13:03 -04:00
Barret Schloerke
38b8ed7bf9 Add an environment argument to runTests 2020-04-16 19:13:03 -04:00
Barret Schloerke
aa74ea0d0a Remove code specifically looking for shinytest only files. This is not necessary as it will still work in the current setup. 2020-04-16 19:13:03 -04:00
Barret Schloerke
e5d3f62043 add another testing app that has a module that returns a reactive value 2020-04-16 19:13:03 -04:00
Barret Schloerke
d2d0e70678 Each testing environment must require their own loadSupport call if necessary 2020-04-16 19:13:03 -04:00
Barret Schloerke
aceb7d0467 Add assert logic 2020-04-16 19:13:03 -04:00
Barret Schloerke
c7ac1fa630 add print method 2020-04-16 19:13:03 -04:00
Barret Schloerke
5855a5b26c Reprint error 2020-04-16 19:13:03 -04:00
Barret Schloerke
0301af62b8 Add todo 2020-04-16 19:13:03 -04:00
Barret Schloerke
32e9757bf7 pass tests 2020-04-16 19:12:59 -04:00
Barret Schloerke
d2b883c4b5 Merge error / result column as pass can be used to determine what the value is 2020-04-16 19:06:45 -04:00
Alan Dipert
816f40a2d5 Consolidate testServer() fixes and enhancements (#2815)
* Improve makeMask comment

* Added skeleton function and example

* Refinements to app template

* Template update

* Rename tests/shinytests/ to tests/shinytest/

* App template updates

* mask creation: clean up, document, and align with rlang::new_data_mask()

* Revert minor in mock session

* Document/fix mock session $setEnv() and $setReturned() behavior

* document

* simplify buildMask()

* minor

* simplify buildMask()

* simplify buildMask()

* add 12_counter test app to exercise runTests + testServer

* Add appobj test

* WIP loadSuppor for apps passed to testServer

* Revert "WIP loadSuppor for apps passed to testServer"

This reverts commit 2d519aca15.

* Found and fixed app obj lifecycle methods that testServer was not exercising when applicable

* Rename 12_counter to 12_template

* Rename utils.R to sort.R

* Updates from code review

* Move 12_template to app_template dir

* Add informative comments

* Simplify mask building, default app to "." in testServer()

* testServer(): Error when arguments provided to a server function

* Fix tests; don't default autoload to FALSE if not found

* Use withr::with_options in one particularly confusing shiny.autoload.r-related test

Co-authored-by: trestletech <jeff.allen@trestletechnology.net>
Co-authored-by: Winston Chang <winston@stdout.org>
2020-04-16 10:26:55 -05:00
Carson Sievert
7e7f38005a Merge pull request #2820 from rstudio/with-path
New path tag causes scoping issue in showcase mode
2020-04-14 13:47:13 -05:00
Barret Schloerke
fb834f7207 roxygen sorted the reexports 2020-04-14 14:30:42 -04:00
Winston Chang
5a3e5296d0 Fix typo 2020-04-14 12:51:20 -05:00
Winston Chang
a0e8d8f2d8 Update NEWS 2020-04-14 11:25:42 -05:00
Carson
9c6dfff531 document 2020-04-14 10:55:05 -05:00
Carson
84d9580bae New path tag causes scoping issue in showcase mode 2020-04-14 10:42:10 -05:00
Jeff Allen
8d6de642ea [WIP] Add skeleton function and example (#2704)
* Added skeleton function and example

* Refinements to app template

* Template update

* Rename tests/shinytests/ to tests/shinytest/

* App template updates

* Rename 12_counter to 12_template

* Rename utils.R to sort.R

* Updates from code review

* Move 12_template to app_template dir

* Add informative comments

* Add shinyAppTemplate to pkgdown.yml

* Fixes for LaTeX docs

Co-authored-by: Winston Chang <winston@stdout.org>
2020-04-14 09:45:10 -05:00
Winston Chang
b20b812cfe Merge pull request #2819 from hadley/opts-id
Don't set default id in clickOpts() and friends
2020-04-14 09:04:50 -05:00
Hadley Wickham
9b23ff6a19 Don't set default id in clickOpts() and friends
This was especially confusing given that each function tests that the id is not NULL.
2020-04-14 08:31:27 -05:00
Winston Chang
cc5278a117 Don't print loading R/ dir messages (#2817)
* Don't print loading R/ dir messages

* Remove obsolete tests
2020-04-13 18:10:32 -05:00
Barret Schloerke
ca6459afe4 add !important attr to .nav-hidden css class 2020-04-09 15:29:01 -04:00
Barret Schloerke
f8477f007d use a list. Use @cpsievert 's wording suggestion. 2020-04-09 15:26:08 -04:00
Barret Schloerke
82d1ad278c merge master 2020-04-09 12:43:55 -04:00
Barret Schloerke
761fb608d3 Add updateActionLink (#2811)
* Add updateActionLink function and example

* document

* add news item
2020-04-09 12:27:45 -04:00
Barret Schloerke
af328eee90 add news items. Add tabPanelBody() function. Document 2020-04-09 11:47:25 -04:00
Barret Schloerke
0fde11ae72 document 2020-04-09 10:44:07 -04:00
Barret Schloerke
73919b1943 add type = 'hidden' for tabsetPanel to hide the tab headers 2020-04-09 10:43:47 -04:00
Winston Chang
1433439215 Merge pull request #2737 from rstudio/inline-markdown
Add shiny::markdown() for inline Markdown
2020-04-08 11:28:27 -05:00
Alan Dipert
4c8dc09f67 NEWS.md 2020-04-08 16:15:22 +00:00
Alan Dipert
80b43942b0 Bump glue dep 2020-04-08 16:14:01 +00:00
Winston Chang
b709b53b6a Merge pull request #2807 from rstudio/serverModule-testModule
moduleServer/testServer overhaul
2020-04-08 10:58:03 -05:00
Alan Dipert
f4e3e5b618 server => module 2020-04-08 05:06:30 +00:00
Alan Dipert
bac7299359 Remove strings from expect_error 2020-04-08 04:57:14 +00:00
Alan Dipert
fc6f535edd Clarify testServer lexenv assertions 2020-04-08 04:54:32 +00:00
Alan Dipert
7e2ffab62c Use base versions of a couple rlang::env_* functions 2020-04-08 04:44:25 +00:00
Alan Dipert
214d721380 Move session$env sanity check out of makeMask and into testServer 2020-04-08 04:41:51 +00:00
Alan Dipert
2f8227e652 Un-inline assignment 2020-04-08 04:36:00 +00:00
Alan Dipert
c0c02d290f Remove unused variable 2020-04-08 04:35:40 +00:00
Alan Dipert
bc2aa71888 Use vapply in mapNames() 2020-04-08 04:27:40 +00:00
Alan Dipert
7f187d1553 Add markdown() NEWS item 2020-04-08 03:04:46 +00:00
Alan Dipert
81b1f4fdc1 Inline markdown tests, add to docs 2020-04-07 22:48:04 +00:00
Alan Dipert
15f088f10a Merge remote-tracking branch 'origin/master' into inline-markdown 2020-04-07 20:47:11 +00:00
Alan Dipert
286f12522b document 2020-04-07 18:40:40 +00:00
Alan Dipert
9d8a6d0142 Document new R6 methods 2020-04-07 18:40:34 +00:00
Alan Dipert
a2dd97cc74 Merge remote-tracking branch 'origin/master' into serverModule-testModule 2020-04-06 23:13:33 +00:00
Alan Dipert
1d9a6ea3c0 getEnv() => env, docs 2020-04-06 23:11:51 +00:00
Alan Dipert
3ca8b1017b Tests pass \o/ 2020-04-06 22:36:09 +00:00
Winston Chang
ecd7c76aee Merge pull request #2764 from rstudio/runTests-aggregate
Tweak runTests() output format
2020-04-06 15:59:06 -05:00
Alan Dipert
70edcd62b9 Getting there 2020-04-03 23:04:50 +00:00
Alan Dipert
90f531888c fix one failing test 2020-04-03 22:06:14 +00:00
Alan Dipert
953de733e7 nested module tests pass now, many others fail %-) 2020-04-02 23:26:02 +00:00
Alan Dipert
e0ed443319 WIP mock session scoped proxy 2020-04-02 21:33:57 +00:00
Alan Dipert
1487720fd8 WIP more markdown() tests 2020-04-01 21:38:39 +00:00
Alan Dipert
828567e0ce Add failing proxy-related and ns() related tests 2020-04-01 21:31:39 +00:00
Alan Dipert
78da4c7fce Merge remote-tracking branch 'origin/master' into serverModule-testModule 2020-04-01 07:26:43 +00:00
Alan Dipert
7f80bfd2cb document 2020-04-01 07:01:57 +00:00
Alan Dipert
7e3deb5e3f document 2020-04-01 06:55:44 +00:00
Alan Dipert
5475ec4f0c document 2020-04-01 06:48:34 +00:00
Alan Dipert
58b4585b57 Doc and test updates 2020-04-01 06:45:18 +00:00
Alan Dipert
cf9ab1c47b appobj coercion works 2020-03-31 21:36:20 +00:00
Alan Dipert
65233cdd5c First passing app dir test for testServer overhaul 2020-03-31 06:33:01 +00:00
Alan Dipert
9d13cb644d test-module.R => test-server.R 2020-03-31 05:36:03 +00:00
Alan Dipert
dd9e0343e8 More test progress 2020-03-31 05:29:42 +00:00
Alan Dipert
bb4aaa2a78 Bring back scope tests 2020-03-31 05:02:31 +00:00
Alan Dipert
0023418b94 More test reorg 2020-03-30 22:55:27 +00:00
Alan Dipert
ec2c9ecea0 Split up and rename various tests 2020-03-27 22:43:29 +00:00
Barret Schloerke
59759398a6 Update actionButton example (#2806)
* Update actionButton example

* Fix link name in example
2020-03-27 17:00:56 -04:00
Alan Dipert
c4852cb451 Desired environment semantics are working 2020-03-25 22:40:08 +00:00
Winston Chang
99880d6e8a Merge pull request #2796 from rstudio/actionButton_class
Add css class examples for actionButton and actionLink
2020-03-24 09:52:23 -05:00
Alan Dipert
b005799d92 Add back many working/converted tests 2020-03-23 23:01:53 +00:00
Barret Schloerke
72f86dac27 Update Node.js build scripts (#2800)
* automatic formatting

* Update to the latest & greatest

* `./tools` `yarn build`

* Remove `newer` from grunt as it causes more problems than it solves. yarn build
2020-03-20 15:59:10 -04:00
Barret Schloerke
83628facb3 Use roxygen2 reexport setup for htmltools and fastmap (#2795)
* Remove all hard copied man files

* Move fastmap reexports into ./R/rexport-fastmap.R

* Update htmltools man script to look for the latest tag and make a reexports file

* document

* Update htmltools reexports to listen to ./inst/_htmltools_reexports.json file. Fix pkgdown failure.

* Allow for any package reexports. Currently fastmap and htmltools

* remove progress dependency

* add back skip on cran for pkgdown

* Test pkgdown only if called using devtools::test or within CI

* Removed outdated import docs file. Moved pkgdown and reexports files into ./tools/documentation. Updated travis file.

* add local test for pkgdown

* updated comments and added a debug comment

* print the repo url and close it

* print the downloaded repo tag info

* use gh package and make sure it's installed

* add PAT to travis and remove username from gh::gh call

* skip pkgdown test on cran and add comments
2020-03-20 14:25:18 -04:00
Alan Dipert
f6e171823a Merge remote-tracking branch 'origin/master' into serverModule-testModule 2020-03-19 20:48:07 +00:00
Barret Schloerke
9b743a319f Add ./revdep folder output and script (#2790)
* Revdep check. 719 - CRAN, 117 - BioConductor; 0 new problems; 3 failed to check

* fix last few install failures.  836 pass. 0 untested. 0 failures.

* add revdep script
2020-03-19 11:43:37 -05:00
Barret Schloerke
eedf2a6cc8 add examples for actionButton and actionLink which adds extra css classes 2020-03-17 14:21:20 -04:00
Winston Chang
e1e738f772 Change indenting of module examples 2020-03-17 13:01:50 -05:00
Winston Chang
182ff3df88 Merge tag 'v1.4.0.2'
Shiny 1.4.0.2 on CRAN
2020-03-16 12:34:10 -05:00
Barret Schloerke
23fde95f9e Add class 'function' to reactive and reactiveVal objects (#2793)
* add the class 'function' to a reactive object

* add the class 'function' to a reactiveVal object

* add test to make sure the reactive and reactiveVal objects are functions

* Add news item
2020-03-16 10:42:28 -04:00
Barret Schloerke
78f9132eb3 Fix Travis checks (#2791)
* make sure the server is only run if the example is interactive

* get travis to pass for now

* Update modules.R

* Add S3 class to MockShinySession

* un-skip test

* Update roxygen level

Co-authored-by: Alan Dipert <alan@dipert.org>
2020-03-12 17:42:38 -04:00
Winston Chang
84b7211588 Bump version to 1.4.0.2 2020-03-12 15:42:26 -05:00
Winston Chang
2793e15c26 Add link 2020-03-12 15:41:21 -05:00
Winston Chang
36bd76607a Skip debounce/throttle tests on CRAN 2020-03-12 15:41:16 -05:00
Barret Schloerke
e17f416bb0 Update roxygen level 2020-03-12 16:30:18 -04:00
Barret Schloerke
a577b1e22e un-skip test 2020-03-12 16:20:13 -04:00
Alan Dipert
2d324c77c1 Add S3 class to MockShinySession 2020-03-12 13:18:23 -07:00
Alan Dipert
88374eca74 Update modules.R 2020-03-12 13:16:55 -07:00
Barret Schloerke
386135788b get travis to pass for now 2020-03-12 16:12:05 -04:00
Barret Schloerke
a943d955dd make sure the server is only run if the example is interactive 2020-03-12 15:58:46 -04:00
Winston Chang
15476ac32e Merge pull request #2789 from rstudio/skip-tests-timing
Skip debounce/throttle tests on CRAN
2020-03-12 11:16:20 -05:00
Winston Chang
17fb5b9eae Add link 2020-03-12 10:00:36 -05:00
Winston Chang
fd27a0dfa2 Skip debounce/throttle tests on CRAN 2020-03-12 09:46:18 -05:00
Winston Chang
5ffe69ec6c Merge tag 'v1.4.0.1' 2020-03-12 09:21:07 -05:00
Carson
f5723b2a4d revert man/ changes to reflect CRAN version of htmltools 2020-03-11 12:04:58 -05:00
Alan Dipert
9e959a88f1 tests 2020-03-05 18:02:26 +00:00
Alan Dipert
09abac41c5 minor reformat 2020-03-05 17:03:15 +00:00
Alan Dipert
1dbf013c1b markdown(): Improve docs; add .noWS; class result as html 2020-03-05 16:57:43 +00:00
Alan Dipert
a637d5b126 Merge remote-tracking branch 'origin/master' into inline-markdown 2020-03-04 21:25:57 +00:00
Alan Dipert
d409183751 Merge remote-tracking branch 'origin/master' into runTests-aggregate 2020-03-04 21:03:50 +00:00
Alan Dipert
e8feef1ce0 Address feedback 2020-03-04 21:03:04 +00:00
Winston Chang
01491cc696 Merge pull request #2772 from rstudio/test-nest-testModule-testServer
Small changes to testModule()/testServer() semantics
2020-03-04 14:58:30 -06:00
Alan Dipert
568a3f28cf Change test to not be locale-dependent 2020-03-04 20:48:21 +00:00
Winston Chang
02219df480 Merge pull request #2773 from rstudio/wch-module
Add moduleServer function
2020-03-04 09:24:58 -06:00
Winston Chang
e006ca51ee Add NEWS item 2020-03-04 09:23:27 -06:00
Winston Chang
86f651f3ec Add moduleServer function 2020-03-04 09:23:27 -06:00
Carson
212b33a0ce bump version 2020-03-03 18:50:41 -06:00
Carson
6b7a121161 yarn build 2020-03-03 18:50:34 -06:00
Carson Sievert
c89da718b1 Merge pull request #2777 from rstudio/fix-docs
Run tools/updateHtmltools.R
2020-03-03 18:40:27 -06:00
Carson
eef3ae8387 update news and update htmltools docs 2020-03-03 16:45:57 -06:00
Alan Dipert
0975a61725 Add test to mitigate shadow with unquote 2020-03-03 22:32:59 +00:00
Winston Chang
0c53d54347 Merge pull request #2776 from rstudio/grid-r-devel
Patches for grid 4.0
2020-03-03 16:12:39 -06:00
Carson
cbbb04cf69 yarn build 2020-03-03 15:52:25 -06:00
Carson
120baf0a6e review feedback 2020-03-03 15:34:32 -06:00
Carson
685dc7cc3a Updates for new grid in r-devel 2020-03-03 15:30:12 -06:00
Alan Dipert
2fbb2ac77b Merge remote-tracking branch 'origin/master' into test-nest-testModule-testServer 2020-03-03 19:25:49 +00:00
Alan Dipert
2832db7aba New session$env test 2020-03-03 19:25:14 +00:00
Alan Dipert
18f2471d7c Fix some roxygen errors 2020-03-03 19:08:49 +00:00
Alan Dipert
ea28f5a61b Minor changes and tests 2020-03-03 18:58:42 +00:00
Winston Chang
fe9cc6038e Merge pull request #2774 from rstudio/no-slack-notifications
Remove slack notifications
2020-03-03 12:09:39 -06:00
Barret Schloerke
5ed335c499 Remove slack notifications 2020-03-03 12:42:48 -05:00
Alan Dipert
fd04b97496 Fix global reference test inside testServer 2020-03-02 17:56:47 +00:00
Alan Dipert
4c9d281b59 Subtle change to .testModule() semantics 2020-02-28 22:49:37 +00:00
Joe Cheng
a26d66b424 Respect shiny.autoreload option being set in app.R or global.R 2020-02-25 20:11:54 -08:00
Alan Dipert
cfb683419f Remove Rd 2020-02-25 20:30:34 +00:00
Alan Dipert
97887bdf02 Add noRd to private function 2020-02-25 20:30:07 +00:00
Alan Dipert
38ea693e73 NEWS.md updates 2020-02-25 18:13:49 +00:00
Alan Dipert
582a0ea6a5 Remove redundant new test 2020-02-25 17:21:19 +00:00
Alan Dipert
71b9f0907e Merge remote-tracking branch 'origin/master' into runTests-aggregate 2020-02-25 16:39:54 +00:00
Alan Dipert
82b82b714d Fix some roxygen errors 2020-02-25 16:27:01 +00:00
Alan Dipert
6356228053 Normalize runTests() output, improve documentation of returned dataframe 2020-02-25 00:08:51 +00:00
Alan Dipert
18fd677550 Pass existing runTests() tests 2020-02-24 22:48:08 +00:00
Alan Dipert
d9698df721 More progress on runTests() format 2020-02-24 22:14:24 +00:00
Joe Cheng
63839fe045 Support shiny.autoreload even when there are errors 2020-02-22 12:22:59 -08:00
Joe Cheng
2ee06a7cbf Revert "Support shiny.autoreload even when there are errors"
This reverts commit cf2ba90b1d.
2020-02-22 12:21:58 -08:00
Joe Cheng
cf2ba90b1d Support shiny.autoreload even when there are errors 2020-02-22 12:20:12 -08:00
Alan Dipert
8124b2143b revert names in app1 tests 2020-02-21 23:57:52 +00:00
Alan Dipert
5361573051 Add working runTests test 2020-02-21 23:35:19 +00:00
Alan Dipert
1d377c868d runTests() output 2020-02-21 22:17:34 +00:00
Alan Dipert
b0a855a326 Make improvements suggested by @schloerke 2020-02-19 20:39:28 +00:00
Alan Dipert
fa35f29596 add_result() for test run 2020-02-19 06:55:32 +00:00
Alan Dipert
f429d23b6e add_result() for test run 2020-02-19 06:54:46 +00:00
Alan Dipert
eeeb903b70 add_result() for test run 2020-02-19 06:54:11 +00:00
Alan Dipert
78f12c4a75 Type stability changes to shinytestrun object 2020-02-19 06:50:58 +00:00
Barret Schloerke
c69f34d1e2 update js files (version bump) 2020-02-18 13:47:02 -05:00
Barret Schloerke
ccfcc5d8b4 add news item 2020-02-18 13:47:02 -05:00
Barret Schloerke
210c248264 bump version 2020-02-18 13:47:02 -05:00
Barret Schloerke
e3258657d0 Invoke onSessionEnded callbacks with self reactive domain 2020-02-18 13:47:02 -05:00
Barret Schloerke
dbc518bf53 Fix broken timer tests and check htmltools docs (#2758)
* Adjust time so that it's in seconds and use expect_true to use regular R dispatch

* Execute './tools/updateHtmltoolsMan.R'

* add check for htmltools docs being up to date
2020-02-14 11:36:51 -05:00
Winston Chang
cdbdb4510e Fix NEWS item 2020-01-16 11:43:51 -06:00
Joe Cheng
e7ec5e5ba4 Merge pull request #2689 from rstudio/joe/feature/bs4-compat
bs4 compatibility
2020-01-13 11:59:15 -08:00
Carson
03d8a7f296 document with modern roxygen 2020-01-13 13:28:54 -06:00
Carson
480035c065 undo unnecessary diff; yarn build 2020-01-13 13:04:44 -06:00
Winston Chang
b32c18cf72 Merge pull request #2722 from rstudio/appveyor-cache
Bust appveyor cache every time the DESCRIPTION file updates
2020-01-08 14:27:58 -06:00
Barret Schloerke
337a6b276a Add more comments about why we are busting the appveyor cache 2020-01-08 14:57:06 -05:00
Barret Schloerke
06cf1f9477 Add comment about why we are busting the cache 2020-01-08 14:55:12 -05:00
Winston Chang
190cfd2b7a Merge pull request #2721 from rstudio/yarn-frozen-lockfile
Use a frozen lock file within CI
2020-01-08 13:21:47 -06:00
Joe Cheng
63035b4d66 No need for bg-danger, progress-bar-danger is now in bs3compat 2020-01-07 13:55:46 -08:00
Joe Cheng
6a11c8fcb1 Remove .col-form-label
I must've copied this from a bs4 example without understanding
what it's for; it's intended for horizontal form labels, which
we don't do
2020-01-07 13:55:23 -08:00
Joe Cheng
33ffb006e3 Get rid of striped progress bar style
The bs4 striped progress bar directives have changed,
but also the stripes look pretty dated at this point
2020-01-07 13:55:23 -08:00
Joe Cheng
162e7f63a9 Remove branch from htmltools remote 2020-01-07 13:54:55 -08:00
Joe Cheng
bb581eeec4 Remove btn-outline-secondary
We're handling btn-default in bs3compat
2020-01-07 13:54:55 -08:00
Joe Cheng
272c555bc5 Remove unnecessary bs4 compat shims from showcase 2020-01-07 13:54:55 -08:00
Joe Cheng
fb64caab23 Remove unnecessary bs4 classes
Since these classes were added, we've decided to handle more of this
kind of thing in the bootscss package, so bs3 markup can work without
modification in many cases.
2020-01-07 13:54:55 -08:00
Carson
6f2a74a46d requires htmltools >= 0.4.0.9001 2020-01-07 13:54:41 -08:00
Carson
ec65a74492 Need to de-active any nav tab, not just navs in a dropdown 2020-01-07 13:53:57 -08:00
Carson
ba791c42fa showcase compatibility 2020-01-07 13:53:39 -08:00
Carson
5896667c36 For some reason event.relatedTarget isn't populated when the previously active item is a dropdown item 2020-01-07 13:53:39 -08:00
Carson
003c949d38 Compatibility for checkboxes will happen via bs4 shims 2020-01-07 13:53:21 -08:00
Carson
d31394254c progress-bar-striped needs to appear on the actual progress bar (not it's container) 2020-01-07 13:53:21 -08:00
Carson
1a497e246c progress-bar-danger class has been replaced by bg-danger 2020-01-07 13:53:06 -08:00
Carson
d24276aa54 btn-outline-secondary is visually closer to btn-default (compared to btn-secondary) 2020-01-07 13:52:49 -08:00
Carson
6ed21a3e6b dateRangeInput() should use input-group-sm, not input-sm or form-control-sm
The former is supported in both bs3 and bs4 and ensures consistent small sizing of the input groups
2020-01-07 13:52:49 -08:00
Carson
8066f9ce96 remove debugger; more detailed comment 2020-01-07 13:52:49 -08:00
Carson
a0276ec1ce wip bs4 compat work 2020-01-07 13:52:33 -08:00
Joe Cheng
2ab925a24c wip2 2020-01-07 13:52:33 -08:00
Joe Cheng
78fbad7d8d wip1 2020-01-07 13:52:13 -08:00
Alan Dipert
6652ae3042 markdown(): improve docs, simplify call to markdown_html(), default to extensions = TRUE 2020-01-06 22:43:04 +00:00
Alan Dipert
aa12ab7d76 Add shiny::markdown() for inline Markdown 2020-01-04 00:02:30 +00:00
Winston Chang
89be4bdce9 Merge pull request #2728 from rstudio/wch-fix-timer
Timer functions always use ms
2019-12-19 13:12:35 -06:00
Winston Chang
d09a064471 Use test_path 2019-12-13 15:45:17 -06:00
Alan Dipert
2b18ca5a6c .testModule(): remove args parameter fixes #2709 (#2713)
* .testModule(): Don't ignore args parameter, fixes #2709

* .testModule(): eliminate args, rely on dynamic dots

* Expand testModule() dots support, add dynamic dots test

* More ... tests

* testModule(): document dynamic dots

* Tighten up ... docs

* document

* testModule(): sundry improvements to docs and tests
2019-12-13 15:38:45 -06:00
Winston Chang
6bc2f18bbf Timer functions always use ms, and better names. Closes #2725 2019-12-13 15:30:47 -06:00
Alan Dipert
fbb892d84e Add MockShinySession$makeScope() (#2714)
* Add MockShinySession$makeScope(), fixes #2712

* Port some relevant ShinySession$defineOutput() behavior to MockShinySession$defineOutput()

* Add nested module test

* Add test for defineOutput() type check

* minor test improvement

* testModule(): improve inner module test, pass reactive to inner
2019-12-12 16:49:18 -06:00
Barret Schloerke
4efb7c20e4 add install cmd 2019-12-10 12:36:23 -05:00
Barret Schloerke
4beb1f07a6 Bust appveyor cache every time the DESCRIPTION file updates 2019-12-09 15:27:17 -05:00
Barret Schloerke
45e640e5f9 Use a frozen lock file within CI
https://yarnpkg.com/lang/en/docs/cli/install/#toc-yarn-install-frozen-lockfile
> Don’t generate a yarn.lock lockfile and fail if an update is needed.
2019-12-09 15:07:12 -05:00
Barret Schloerke
e84beffee3 Merge pull request #2717 from akgold/label-file-observer
Add label to file reload observer
2019-12-06 14:42:08 -05:00
Winston Chang
e07c7483a7 Merge pull request #2719 from rstudio/wch-fix-odd-chars
Use as.raw instead of charToRaw
2019-12-04 12:31:57 -06:00
Winston Chang
34ec7bf5eb Use as.raw instead of charToRaw
When the package is built, the string with odd characters is marked with the
encoding of the build system. When the build system uses the C locale and the
running system uses a UTF-8 locale (like en_US.UTF-8), this results in a warning
when this function is first accessed. Using as.raw() lets us avoid using a
string altogether.
2019-12-04 10:47:21 -06:00
Barret Schloerke
01b20a4829 display auto reload base directory for reactlog label 2019-12-03 15:16:18 -05:00
Winston Chang
45ea898da4 Rebuild docs with roxygen2 7.0.2 2019-12-03 12:28:06 -06:00
Alex Gold
fd34c5070f Add label to file reload observer 2019-12-02 10:03:11 -05:00
Winston Chang
6c409d96c1 Bump node version on Travis 2019-11-22 14:09:58 -06:00
Winston Chang
0cbe4bb3d4 Rebuild docs with roxygen2 7.0.1 2019-11-22 13:07:44 -06:00
Winston Chang
d04a990235 Merge pull request #2707 from rstudio/wch-outputinfo-null
getCurrentOutputInfo(): return NULL if not in an output
2019-11-22 12:38:05 -06:00
Winston Chang
4747c87632 Rebuild shiny.js 2019-11-21 16:31:51 -06:00
Winston Chang
f57452c7bf Update docs 2019-11-21 16:30:38 -06:00
Winston Chang
9a8e2eb675 getCurrentOutputInfo(): return NULL if not in an output 2019-11-21 16:16:52 -06:00
Winston Chang
8ef7f3cbe2 Merge pull request #2701 from rstudio/wch-update-roxygen
Update roxygen2 to 7.0.0
2019-11-13 15:01:29 -06:00
Winston Chang
de30a65f01 Update documentation of Progress and MockShinySesssion 2019-11-13 15:01:01 -06:00
Winston Chang
0bcf613195 Update to roxygen2 7.0.0 2019-11-13 12:10:57 -06:00
Winston Chang
89fd9004d0 Merge pull request #2585 from rstudio/jeff/feature/test
Add a test runner
2019-11-13 11:53:00 -06:00
trestletech
b2be108db1 Add a message to clarify what app is being tested, support setting progress on mock session. 2019-11-13 11:43:50 -06:00
trestletech
6102c44b70 Attempt to pin roxygen2 2019-11-07 13:26:15 -06:00
trestletech
327cdc8e41 Don't use GH deps for appveyor
see 89feba870d.
2019-11-07 12:51:03 -06:00
trestletech
0bc3613989 PR feedback 2019-11-06 15:58:30 -06:00
Jeff Allen
30cea871f9 Expand testServer/Module docs (#2694)
* Merge and expand testmodule/server docs

* Alos->also
2019-11-06 20:29:44 +00:00
trestletech
5f332fe4db Set working dir in testServer so the app runs in the proper dir. 2019-11-01 16:52:43 -05:00
trestletech
7ee7f2716b Load shiny and inherit from global env. Non-error are no NA and errors are passed through. 2019-11-01 16:40:45 -05:00
trestletech
5e8c39cb1e Add entry in pkgdown 2019-11-01 11:26:23 -05:00
trestletech
ee355200b3 Rename testApp -> runTests 2019-11-01 11:25:47 -05:00
trestletech
986fbe2254 Merge remote-tracking branch 'origin/master' into jeff/feature/test 2019-11-01 11:23:24 -05:00
Jeff Allen
32f93a2be1 Integration Testing Docs (#2691)
* Update roxygen and regenerate.

Mostly just whitespace changes and  `code` -> `verb`.

* R6 documentation for MockShinySession

* Install roxygen from GH

* % are now auto-escaped

(We still need to go find the rest)

* Fixed the ramining \% in roxygen

Found looking for ^#'.*\\% in all R files, so I believe this is all of them.

* Regenerate docs

* Decreate indent in roxygen so paragraphs don't get interpreted as code blocks.

https://github.com/r-lib/roxygen2/issues/948#issuecomment-546386172

* Namespace

* Add MockShinySession reference to pkgdown.

* Clean up test warnings

* Export session
2019-11-01 02:33:58 +00:00
Winston Chang
ab79065c13 Merge pull request #2690 from rstudio/wch-date-color
Datepicker: make disabled months and years lighter gray
2019-10-31 12:16:18 -05:00
Winston Chang
77171b7894 Make cursor indicate when dates are not selectable 2019-10-31 12:09:18 -05:00
Winston Chang
cce8ddb84f Update NEWS 2019-10-30 16:05:55 -05:00
Winston Chang
648b7e5911 Datepicker: make disabled months and years lighter gray 2019-10-30 16:01:29 -05:00
Jeff Allen
67a66fdc93 Merge pull request #2682 from rstudio/jeff/int-test
Introduce integration testing framework
2019-10-30 18:36:44 +00:00
trestletech
5fbaa26d05 Remove vignette. 2019-10-30 11:29:58 -04:00
trestletech
1f4a3c4fd2 Regenerate docs 2019-10-28 23:14:25 -04:00
trestletech
959dc7ffd4 PR feedback 2019-10-28 22:57:30 -04:00
trestletech
0e34221cac How do I still get paid to do this? 2019-10-25 16:54:10 -05:00
trestletech
0cad13b3a3 Placeholder docs for MockShinySession
(More to come in subsequent PR)
2019-10-25 16:47:10 -05:00
trestletech
0776f71ca3 Export session 2019-10-25 16:27:45 -05:00
trestletech
5a74e369ce Implement missing test. 2019-10-25 16:23:16 -05:00
trestletech
799c5ac662 Clean up test warnings 2019-10-25 16:20:33 -05:00
Jeff Allen
1080cf0ef4 Merge pull request #2686 from rstudio/jeff/autoload
Message when autoloading R/ files
2019-10-25 20:16:42 +00:00
trestletech
867d49e3fb Pin to the beginning of the file path. 2019-10-25 15:02:39 -05:00
trestletech
c7be406099 Change URL 2019-10-25 14:21:32 -05:00
trestletech
37257e77ce Disable autoloading with a R/_disable_autoload.R file. 2019-10-25 14:14:46 -05:00
trestletech
270d9ff0fc Add message about loading R/ 2019-10-25 14:02:50 -05:00
trestletech
34b48598d9 Merge remote-tracking branch 'origin/master' into jeff/int-test 2019-10-25 11:23:15 -05:00
trestletech
5105ecb148 Cleaning up the vignette 2019-10-24 14:46:54 -05:00
trestletech
f47b151458 Test improvements for Windows and make CHECK pass. 2019-10-24 11:50:07 -05:00
Jeff Allen
d3f15a58fc Merge pull request #2675 from rstudio/jeff/mock-session
Introduce a MockShinySession object
2019-10-24 15:21:30 +00:00
trestletech
42f6adb7fa Handle Joe's feedback. 2019-10-24 10:20:54 -05:00
trestletech
263f8a8e7d Introduce integration testing functionality 2019-10-24 10:07:23 -05:00
trestletech
3a42d30cfd Simplify run_now() 2019-10-24 09:53:37 -05:00
trestletech
9275217a5a Refine which methods merit warnings 2019-10-22 15:43:26 -05:00
trestletech
1fed19ad68 Export flushReact method 2019-10-22 09:59:20 -05:00
trestletech
6a8a78abd1 Bring in promise helpers and test for getOutput auto-flushing 2019-10-22 09:47:09 -05:00
trestletech
de69f51084 Rename parameter, destroy old outputs 2019-10-22 09:43:37 -05:00
Winston Chang
c81a3f39fd Update NEWS 2019-10-21 16:57:01 -05:00
Winston Chang
6fcb925e34 Merge pull request #2652 from ahmohamed/master
Fix debounce() behavior when r() throws an error
2019-10-21 16:54:59 -05:00
Winston Chang
8823b7280a Merge branch 'master' into hadley-text-doc 2019-10-21 16:45:53 -05:00
Winston Chang
ebadad97a8 Merge pull request #2612 from hadley/file-type
Improve inputFile() accept documentation
2019-10-21 16:43:01 -05:00
Winston Chang
a095c39626 Merge pull request #2616 from hadley/bookmarking-docs
Tweak shinyApp docs about bookmarking
2019-10-21 16:42:07 -05:00
Winston Chang
fb9bcb44c3 Merge branch 'insert-remove-ui' of https://github.com/hadley/shiny into hadley-insert-remove-ui 2019-10-21 16:40:06 -05:00
trestletech
38f593450a PR feedback 2019-10-21 15:35:05 -05:00
trestletech
6d44f2c5cb Align default parameter values with real session 2019-10-21 15:32:37 -05:00
trestletech
d1786a64c4 Try to fix failing Windows test
Perhaps Sys.time isn't high enough resolution there?
2019-10-18 15:33:07 -05:00
trestletech
616ae99c0b Include equality in scheduling comparisons
In real life, the odds that a Sys.time() call is going to hit this equality branch is pretty small as the clock is so precise. However, for testing it's nice to be able to say "this should fire in 10ms, now elapse 10ms" and then confirm that it fired. Without this, you have to pad your delays in order to see the event trigger.
2019-10-18 15:22:03 -05:00
trestletech
4d2ff80788 Introduce MockShinySession 2019-10-18 15:20:44 -05:00
Jeff Allen
005295fd4c Merge pull request #2665 from rstudio/jeff/session-timers
Best-effort task scheduling through the session
2019-10-18 20:12:22 +00:00
trestletech
d6b46f8243 Bring back the good parts of a003 2019-10-18 13:58:42 -05:00
trestletech
bac35e8f1b Revert "PR feedback. Broke tests because of dependency on session, though, so might revert."
This reverts commit a003c4da85.
2019-10-18 13:50:30 -05:00
trestletech
a003c4da85 PR feedback. Broke tests because of dependency on session, though, so might revert. 2019-10-17 14:01:58 -05:00
trestletech
0ae8e4fe8a Consolidate to two Timer classes and simplify conditionals 2019-10-16 14:49:01 -05:00
trestletech
d3667dfc77 Attempt to get the current time from the session, if available. 2019-10-15 15:32:59 -05:00
trestletech
54c5467dc6 Unrelated: fix autoload tests. 2019-10-15 15:02:16 -05:00
trestletech
d01f0300a5 Add mock timer class 2019-10-15 14:59:36 -05:00
trestletech
bff207008f Best-effort task scheduling through the session
Currently a no-op change, as the session just passes through to the global scheduleTask implementation. But this allows us to mock the method for testing.
2019-10-15 14:24:10 -05:00
trestletech
ed739f95ff Revert "Best-effort task scheduling through the session"
This reverts commit bb4de1336c.
2019-10-15 14:22:31 -05:00
trestletech
bb4de1336c Best-effort task scheduling through the session
Currently a no-op change, as the session just passes through to the global scheduleTask implementation. But this allows us to mock the method for testing.
2019-10-15 14:21:44 -05:00
Winston Chang
f7205558d2 Make shiny.autoload.r default to TRUE (#2659)
* Make shiny.autoload.r default to TRUE

* Update comments
2019-10-15 12:24:39 -05:00
Winston Chang
1318544ecf Update NEWS 2019-10-11 14:58:17 -05:00
Winston Chang
a81c161434 Merge pull request #2658 from rstudio/fix-data-table
Preserve matrix dimensions in dataTablesJSON
2019-10-11 14:56:21 -05:00
Winston Chang
73acdc755f Merge pull request #2650 from rstudio/wch-travis-r-versions
Run Travis checks on more R versions
2019-10-10 10:18:21 -05:00
Winston Chang
dd84ea8fda Merge branch 'master' into wch-travis-r-versions 2019-10-10 10:17:33 -05:00
Winston Chang
a2a4e40821 Bump version to 1.4.0.9000 2019-10-10 10:06:12 -05:00
Winston Chang
509f54d68c Merge tag 'v1.4.0'
shiny 1.4.0 on CRAN
2019-10-10 10:04:03 -05:00
Winston Chang
27ce460ea4 Preserve matrix dimensions in dataTablesJSON. Fixes #2653 2019-10-08 16:04:03 -05:00
Alan Dipert
116794ad77 Use pkgdown for reference page generation (#2651)
* Add _pkgdown.yml, remove inst/staticdocs/index.r

* Update pkgdown.yml

* Fix pkgdown (nee staticdocs) test so that it fails as it should

* Fix pkgdown test by adding shinyServer and shinyUI to list of intentionally unindexed functions

* Remove old staticdocs test

* Fix "Boilerplate" section of reference docs

* Fix CMD CHECK

* Fix typo

* Use file-based test in get_exported()

* Skip pkgdown check on CRAN

* Fix typo in pkgdown test
2019-10-07 15:18:26 -05:00
Winston Chang
89feba870d Don't use dependency release candidates in Travis 2019-10-07 14:51:36 -05:00
Winston Chang
2a980601c0 Use absolute URL for CONTRIBUTING.md 2019-10-07 12:26:37 -05:00
Winston Chang
e1fd8ae910 Fix CONTRIBUTING.md link 2019-10-07 12:24:54 -05:00
Joe Cheng
9cb415008c Update link 2019-10-04 16:16:32 -07:00
Ahmed Mohamed
26ba9bf94a Fix debounce() behavior when r() throws an error 2019-10-04 11:58:22 +10:00
Winston Chang
fb091ca195 Restructure NEWS 2019-10-02 15:26:14 -05:00
Winston Chang
99a7dca3ce Relax test so it passes on R 3.3 and below 2019-09-30 16:28:38 -05:00
Winston Chang
a1a03d94be Run Travis on more R versions 2019-09-30 16:05:31 -05:00
trestletech
85a2d41a72 Merge remote-tracking branch 'origin/master' into jeff/feature/test 2019-09-30 09:55:11 -05:00
Jeff Allen
89bd7e9011 Merge pull request #2647 from rstudio/jeff/cla
Update contributing instructions for cla-assistant.
2019-09-30 14:48:38 +00:00
trestletech
ececdf42a7 Update contributing instructions for cla-assistant. 2019-09-30 09:46:57 -05:00
Jeff Allen
2cf03de8b8 Don't notify slack on success 2019-09-27 18:07:08 +00:00
Winston Chang
c8daa1730b Merge pull request #2643 from rstudio/wch-fix-stack-tests
Disable stack tests on CRAN
2019-09-26 16:59:58 -05:00
Winston Chang
d195b595dd Disable call stack tests on CRAN 2019-09-26 16:23:52 -05:00
Barret Schloerke
ff3f7adff2 Merge pull request #2637 from rstudio/rc-barret-utils-packageVersion
Namespace packageVersion
2019-09-24 18:13:24 -04:00
Barret Schloerke
37781a9df7 namespace packageVersion 2019-09-24 17:36:45 -04:00
Joe Cheng
ca1c60e00e Merge pull request #2632 from rstudio/carson/jquery-legacy
Opt-in to jQuery 1.12.1
2019-09-20 17:52:37 -07:00
Carson
649f382291 Library updates -> Potentially breaking changes 2019-09-20 15:43:38 -05:00
Carson
103a35c81b review feedback 2019-09-20 15:43:38 -05:00
Carson
5af341bfdb document 2019-09-20 15:43:38 -05:00
Carson
7c7110cd83 Do nothing if the package isn't installed or meets the version requirement 2019-09-20 15:43:38 -05:00
Carson
c4ea489bff news feedback 2019-09-20 15:43:38 -05:00
Carson
60b3b6ff03 jquery legacy is 1.12.4, not 1.12.1 2019-09-20 15:43:38 -05:00
Carson
1510dca065 update news 2019-09-20 15:43:38 -05:00
Carson
2c49375928 Provide an option, shiny.jquery.version, to opt-in into jQuery 1.12.1 2019-09-20 15:43:38 -05:00
Carson
f9fc22c48b Emit an upgrade message if an old version htmlwidgets is installed 2019-09-20 15:43:38 -05:00
Alan Dipert
8d14e7ab04 Merge pull request #2625 from rstudio/fix-selectize-update
Fix updateSelectizeInput(), fixes #2624
2019-09-20 12:35:47 -07:00
Alan Dipert
8f2a28a1f2 Fix #2624 by aligning select* input handling of groups with that of updateSelect* 2019-09-19 20:16:36 +00:00
Carson Sievert
e8fb1faec0 Merge pull request #2623 from rstudio/carson/rc-ci
Fix travis build for 1.4.0
2019-09-18 13:51:46 -05:00
Carson
0e4874c412 have appveyor run github versions as well 2019-09-18 13:36:22 -05:00
Carson
933630af28 Update stack call test expectation in light of https://github.com/rstudio/promises/commit/9ebad6#diff-1220ed154f06164c0a2d6cc053c1f3c1R134 2019-09-18 13:28:32 -05:00
Carson
ff87098102 Temporarily install rc branches to get Travis passing 2019-09-18 12:58:23 -05:00
Winston Chang
6513a86bbd Merge pull request #2621 from rstudio/carson/bugfix/avoid-offsetX
Use pageX/pageY instead of offsetX/offsetY
2019-09-18 12:42:58 -05:00
Carson
97e296c5d5 Use pageX/pageY instead of offsetX/offsetY to determine if a second click is too far away before triggering a double-click event. Closes #2620 2019-09-17 17:49:20 -05:00
Winston Chang
9f87adf4e8 Merge pull request #2619 from rstudio/wch/eslint-rules
Better checking for implicit globals in JS
2019-09-17 15:18:05 -05:00
Joe Cheng
6470b3f08c Fix 062-submitbutton-demo
1) In srcjs/input_rate.js line 284, the global variable `name` was
   being written to.
2) In a couple of other places in that file, the global variable
   `name` was being read instead of `nameType`--the result of an
   incomplete refactor.

Also added an eslint rule to prevent this and other globals from
being read implicitly.
2019-09-17 12:55:47 -07:00
Joe Cheng
d1ba84525e Update version number inserted by Grunt 2019-09-17 12:41:02 -07:00
Winston Chang
05ad66c464 Better checking for implicit globals 2019-09-17 14:09:11 -05:00
Winston Chang
c41d38bf61 Document insertUI() and removeUI() together
Since they share so many arguments. I also updated the style of the roxygen comments.
2019-09-17 07:55:53 -05:00
Hadley Wickham
b155e8480b Update docs 2019-09-16 12:30:50 -05:00
Hadley Wickham
e94f687573 Tweak shinyApp docs about bookmarking 2019-09-16 08:00:14 -05:00
Hadley Wickham
5883082d01 Improve inputFile() accept documentation
* accept should be a vector of "unique file type identifiers" not a vector of mime types (https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#Unique_file_type_specifiers)

* I updated the example to use req() and to validate the uploaded extension; this is good practice since not all browsers will enforce `accept`
2019-09-15 09:07:16 -05:00
Hadley Wickham
75b53ffda1 Combine documentation for textOutput() and verbatimTextOutput()
And generally polish docs
2019-09-14 09:10:59 -05:00
Joe Cheng
a8057b96f3 Update version dependencies 2019-09-13 13:45:45 -07:00
Joe Cheng
a89e809498 Bump version to 1.4.0 2019-09-13 13:01:25 -07:00
Winston Chang
02f7a4fdc9 Rebuild documentation 2019-09-12 18:40:35 -05:00
Carson Sievert
7c7c22a597 Document default values of shiny's options (#2597)
* Document default values of shiny's options, closes #2558

* A more general description of shiny.port's default
2019-09-12 18:31:07 -05:00
Winston Chang
860fa525a2 Merge pull request #2605 from hadley/notification-id
Clarify use of id argument
2019-09-12 18:20:17 -05:00
Carson Sievert
9f0e38a28a Merge pull request #2601 from rstudio/layoutFamily
Layout Rd family
2019-09-12 13:09:00 -07:00
Jeff Allen
f834b7befb Define what all input functions yield for server (#2600)
* adding section to roxygen docs for server value of input funcs

* add more server values to roxygen docs

* add more server values

* update more server values in documentation

* Address PR feedback

I reflowed the comments to have a max width of 80 on some files, so there were a flurry of line changes, but the only substantive changes were around Joe's comments.

* Update R/input-slider.R

Co-Authored-By: Hadley Wickham <h.wickham@gmail.com>

* Apply suggestions from code review

Co-Authored-By: Carson Sievert <cpsievert1@gmail.com>

* PR feedback, regenerate docs.

* PR Feedback

* Eliminate extra newline

* passwordInput()'s server value

* varSelectInput()'s server value

* document
2019-09-12 20:02:44 +00:00
Winston Chang
7f3a45fb5b Merge pull request #2560 from rstudio/barret-reactlog-keybindings
Use ctrl/cmd + shift + f3 to mark reactlog and Return a 501 error code if reactlog disabled
2019-09-12 10:29:57 -05:00
Barret Schloerke
b0953e810b merge master 2019-09-12 10:26:38 -04:00
Hadley Wickham
52a86012e5 Update R/notifications.R
Co-Authored-By: Carson Sievert <cpsievert1@gmail.com>
2019-09-12 09:09:09 -05:00
Hadley Wickham
2a06fe6baf Clarify use of id argument 2019-09-12 08:28:27 -05:00
Carson
6e688d2175 add fillPage() to the family as well 2019-09-11 16:30:25 -05:00
Carson
b610fd1f56 Hadley's feedback 2019-09-11 16:29:48 -05:00
Carson
a4730096f4 code review 2019-09-11 15:23:41 -05:00
leslie-huang
6a02439944 add @ family to all layout functions 2019-09-11 15:15:38 -05:00
Carson Sievert
b889b0d2b0 Merge pull request #2582 from rstudio/barret_showcase_hidden_wide
Fix showcase bug where hidden by default on wide window
2019-09-11 10:59:18 -07:00
Carson
ba5733e4a4 add news item 2019-09-11 12:34:20 -05:00
Carson Sievert
2e0221ecfd Merge pull request #2592 from rstudio/set-min-max
Exit early if date parsing fails
2019-09-09 13:55:08 -07:00
Carson
aeded79544 yarn build 2019-09-09 15:43:41 -05:00
Carson
c0a7958e77 update news 2019-09-09 15:18:41 -05:00
Carson
431b194ec2 Exit early if date parsing fails in _setMin() and _setMax(), closes #2591 2019-09-09 13:48:18 -05:00
Joe Cheng
29d24d7e08 Merge pull request #2586 from rstudio/resourcePathChangesOption
Suppress resource path changes by default
2019-09-06 13:20:35 -07:00
Winston Chang
3b04c642ae Bump httpuv version dependency 2019-09-06 11:47:58 -05:00
Winston Chang
609fc5b0c0 Fix typo 2019-09-06 11:46:58 -05:00
Winston Chang
2a8c79b577 Merge pull request #2588 from rstudio/wch-slider-phantom
Add try-catch to ion.rangeSlider
2019-09-06 10:52:25 -05:00
Winston Chang
043316e40f Clarify comments 2019-09-06 10:52:08 -05:00
Joe Cheng
c9d8b987d4 Merge pull request #2522 from rstudio/wch-fix-reactivepoll-leak
Fix reactivePoll leak
2019-09-05 16:44:57 -07:00
Joe Cheng
33c5a5c665 Fix unit test 2019-09-05 16:12:07 -07:00
Winston Chang
29c90ba163 Code review fixes 2019-09-05 16:12:07 -07:00
Winston Chang
8c19450b10 Use safer method to remove observer 2019-09-05 16:11:47 -07:00
Winston Chang
89c97458c4 Update NEWS 2019-09-05 16:11:47 -07:00
Winston Chang
02be516902 Use safer finalizer for reactivePoll 2019-09-05 16:11:47 -07:00
Winston Chang
47ada300ea Fix reactivePoll leak 2019-09-05 16:11:19 -07:00
Carson
6f9c621774 Always suppress for now 2019-09-05 17:22:56 -05:00
trestletech
324d9195c3 Merge remote-tracking branch 'origin/wch-slider-phantom' into jeff/feature/test 2019-09-05 16:51:49 -05:00
Winston Chang
0310fe3b68 Automate patches for ion.rangeSlider 2019-09-05 16:00:56 -05:00
Winston Chang
7144a6e4b7 In ion.rangeSlider, wrap removeProp() in try-catch. Closes #2587 2019-09-05 15:53:37 -05:00
Carson
1c8071a96f Add shiny.resourcePathChanges option to get more information about resource path changes for a given prefix.
Closes #2584
2019-09-05 13:44:21 -05:00
trestletech
4ad115e024 Load the helpers before the tests -- into an ancestor environment of the tests'. 2019-09-05 09:46:34 -05:00
trestletech
f11d754cfe Add a filter to test 2019-09-05 09:45:06 -05:00
trestletech
65019ce96f Add namespace rewire option.
Return the right structure from shinytest tests and add unit tests.
2019-09-05 09:44:56 -05:00
trestletech
90e8fb2a57 Adding a test runner 2019-09-05 09:44:40 -05:00
Carson Sievert
ff5377da9e Merge pull request #2583 from rstudio/carson_resource_warning
Fix spacing in warning for resource paths conflicting with www/ subdirs
2019-09-04 11:27:09 -07:00
Carson
7aee84eb05 Fix spacing in warning for resource paths conflicting with www/ subdirs 2019-09-04 11:52:31 -05:00
Barret Schloerke
c0a7a6d0d6 don't hide the current element, instead make sure new element is hidden before fading in 2019-09-04 12:44:08 -04:00
Barret Schloerke
29c48471f2 hide the prior element, not the new element 2019-09-04 12:24:49 -04:00
Barret Schloerke
229e56464b if no code tab exists, do not attempt to highlight it 2019-09-04 12:24:20 -04:00
Joe Cheng
769c32fd38 Merge pull request #2580 from hadley/shinyApp-docs
shinyApp() documentation improvements.
2019-09-04 08:12:17 -07:00
Joe Cheng
d05b89cfb3 Merge pull request #2581 from hadley/shinyApp-args
Clarify required argumented to shinyApp()
2019-09-04 08:08:44 -07:00
Hadley Wickham
f1f18a2334 Clarify required argumented to shinyApp()
This does technically change the interface as `shinyApp(server = function(input, output) ...))` would have previously worked, but it didn't generate a useful app.

Fixes #2462
2019-09-04 09:57:19 -05:00
Hadley Wickham
afc556f801 More details about server argument
Fixes #2508
2019-09-04 09:46:57 -05:00
Hadley Wickham
7f240839fc Document shiny.appobj in own file
Fixes #2458
2019-09-04 09:44:48 -05:00
Joe Cheng
8d0a6274cb Merge pull request #2579 from rstudio/wch-fix-sleep
Remove Sys.sleep in runApp()
2019-09-03 14:11:29 -07:00
Winston Chang
91cab10ff8 Remove Sys.sleep in runApp() 2019-09-03 15:09:51 -05:00
Joe Cheng
5828ea7426 Merge pull request #2577 from hadley/print-methods
Implement two missing print methods
2019-09-03 08:14:51 -07:00
Joe Cheng
80ba147168 Merge pull request #2566 from rstudio/fix-statichandler-backslash
Disallow backslash in staticHandler paths
2019-09-03 07:50:35 -07:00
Joe Cheng
f85479ba11 Merge pull request #2570 from rstudio/joe/misc/update-node-deps
Upgrade yarn dependencies
2019-09-03 07:49:51 -07:00
Joe Cheng
a23c5f151f Merge pull request #2569 from hadley/pageWithSidebar
Soft-deprecate pageWithSidebar() and headerPanel()
2019-09-03 07:49:29 -07:00
Joe Cheng
cab3601474 Merge pull request #2568 from hadley/doc-combine
Document all sidebar UI components together
2019-09-03 07:48:44 -07:00
Joe Cheng
cf330fcd58 Merge pull request #2575 from hadley/options-docs
Combine shinyOptions and shiny-options
2019-09-03 07:47:32 -07:00
Hadley Wickham
eb0162dccf Add basic print method for shiny.render.function
So at least the user isn't exposed to a bunch on internals
2019-09-03 09:17:02 -05:00
Hadley Wickham
a415aed7e6 Implement print.reactivevalues 2019-09-03 09:13:43 -05:00
Hadley Wickham
9f6014dc0b Remove from index 2019-09-02 09:14:20 -05:00
Hadley Wickham
21b0d38b57 Minor formatting tweaks 2019-09-02 09:14:15 -05:00
Hadley Wickham
1ec7f22b5f Alphabetise options 2019-09-02 09:03:46 -05:00
Hadley Wickham
346c5e4a4c Merge shinyOptions and shiny-options
Including an alias so that ?"shiny-options" will continue to work.

Fixes #2544
2019-09-02 08:59:58 -05:00
Joe Cheng
c9a0f0a713 Merge pull request #2567 from hadley/reactive-plot-size-docs
Clarify the three inputs to width/height
2019-08-29 16:24:46 -07:00
Joe Cheng
8bbc38dc8a Upgrade yarn dependencies
This prevents GitHub from complaining about a security vulnerability
in es-lint.
2019-08-29 12:27:29 -07:00
Hadley Wickham
96494a22f9 Soft-deprecate pageWithSidebar() and headerPanel()
Fixes #2452
2019-08-29 08:27:36 -05:00
Hadley Wickham
0813789e2a Cross-link tabPanel() to navbarPage() 2019-08-29 08:15:19 -05:00
Hadley Wickham
98ca820ab1 Document sidebarPanel() and mainPanel() with sidebarLayout() 2019-08-29 08:09:22 -05:00
Hadley Wickham
81ca9d9f29 Co-locate all sidebarLayout() functions 2019-08-29 08:00:40 -05:00
Hadley Wickham
16fe0019f9 Clarify the three inputs to width/height 2019-08-29 07:30:09 -05:00
Barret Schloerke
5fa650ab75 Merge pull request #2559 from rstudio/barret-trim-showcase-info
Reduce the information sent to shiny showcase
2019-08-28 17:27:16 -04:00
Winston Chang
564c2a0f16 Disallow backslash in staicHandler paths 2019-08-28 15:42:09 -05:00
Barret Schloerke
1685e1c310 Merge branch 'master' into barret-reactlog-keybindings
* master: (22 commits)
  Fix upper-case test
  autload
  - update NEWS - only source global in server.R mode - only use intermediary environment if opted-in to autoloading.
  Only use loadSupport if opted-in to autload.r
  Fix default param
  Make loading helpers opt-in.
  Clarify docs
  Update to new signature in test.
  Move global.R sourcing into an exported load function
  Only load top-level R files in R/
  Require capitalized R/ dir.
  Correct mistake around app.R in global
  Add news
  Fix options test
  Test ui/server/app/global sourcing.
  Revert "DI the source function for testing."
  DI the source function for testing.
  Load helpers into isolated environment
  Fix expectations.
  Add dynamically-generated case-sensitive test.
  ...
2019-08-28 12:26:39 -04:00
Barret Schloerke
332f5a1266 add js for opening broken reactlog routes 2019-08-28 12:24:17 -04:00
Jeff Allen
99ac85f06a Merge pull request #2547 from rstudio/jeff/feature/helpers
Automatically load 'helpers' in R/ directory at runtime
2019-08-28 16:19:07 +00:00
trestletech
fc30ad0935 Fix upper-case test 2019-08-28 11:05:04 -05:00
trestletech
aadf2eb609 Merge remote-tracking branch 'origin/master' into jeff/feature/helpers 2019-08-28 10:29:32 -05:00
trestletech
68f778e423 autload 2019-08-28 10:26:31 -05:00
trestletech
0066cff652 - update NEWS
- only source global in server.R mode
- only use intermediary environment if opted-in to autoloading.
2019-08-28 10:20:42 -05:00
trestletech
f872a0c80a Only use loadSupport if opted-in to autload.r 2019-08-28 10:15:11 -05:00
Barret Schloerke
68d67a8194 Update NEWS.md 2019-08-27 17:51:10 -04:00
Barret Schloerke
756ac1514c Use ctrl/cmd + shift + f3 to mark reactlog; return a 501 error code for reactlog paths when reactlog is disabled
Open a new webpage even if only marking a time.
2019-08-27 17:50:46 -04:00
Barret Schloerke
d9478142b1 Merge pull request #2561 from rstudio/barret-fix-master
Fix master docs
2019-08-27 17:38:27 -04:00
Winston Chang
5eced59961 Rebuild JS files 2019-08-27 16:31:29 -05:00
Winston Chang
3e1862cd51 Merge pull request #2526 from rstudio/setDateBounds
Set min/max date after date value when they land on the same day
2019-08-27 16:30:49 -05:00
Barret Schloerke
7271609850 ignore any node_modules-like named folder 2019-08-27 17:24:25 -04:00
Barret Schloerke
f24337bb3b add messages in htmltools script to notify about version number 2019-08-27 17:14:51 -04:00
trestletech
6167247ea2 Fix default param 2019-08-27 15:59:27 -05:00
Barret Schloerke
0332e52501 remove unneeded method roxygen tag 2019-08-27 16:50:33 -04:00
trestletech
0c23f78ab7 Make loading helpers opt-in. 2019-08-27 15:29:58 -05:00
Barret Schloerke
7624449644 add import htmltools statement 2019-08-27 16:17:20 -04:00
Barret Schloerke
97309e8c4c execute tools/updateHtmltoolsMan.R 2019-08-27 14:44:39 -04:00
Barret Schloerke
a1e78214db Create updateHtmltoolsMan.R 2019-08-27 14:34:33 -04:00
Barret Schloerke
1a57b3296b use htmltools remote 2019-08-27 14:32:25 -04:00
trestletech
7c10fc3514 Merge remote-tracking branch 'origin/master' into jeff/feature/helpers 2019-08-27 12:54:06 -05:00
Jeff Allen
494ef42aa8 Clarify docs 2019-08-27 17:46:17 +00:00
Carson
8a54d216c6 better news description 2019-08-27 10:47:10 -05:00
Carson
896a20d76d set start/end date after setting date if they land on the same day, closes #2335 2019-08-27 10:30:38 -05:00
Barret Schloerke
a26510b02f copy in latest man files from htmltools
* fix staticdocs test
* remove hasTagAttributes and getTagAttributes from man file
2019-08-26 15:30:27 -04:00
Barret Schloerke
1465f1d237 add roxygen tag to enforce s3 method for checking 2019-08-26 15:27:36 -04:00
Joe Cheng
21b18d107a Merge pull request #2166 from rstudio/unexport-knit-print
Un-export knit_print methods from htmltools
2019-08-26 14:29:16 -04:00
Joe Cheng
cc2173c587 Merge pull request #2555 from rstudio/wch-fix-invalidatelater-leak
Fix invalidateLater memory leak
2019-08-26 13:51:34 -04:00
Winston Chang
71fe821ae9 Update NEWS 2019-08-26 11:28:45 -05:00
Winston Chang
3ffab69ad6 Register shiny's knit_print methods on load 2019-08-26 11:28:19 -05:00
Winston Chang
58a662bd35 Merge branch 'master' into unexport-knit-print 2019-08-26 11:04:40 -05:00
Barret Schloerke
eb55c256c7 only send requried information across wire to browser for showcase mode 2019-08-26 10:52:27 -04:00
Winston Chang
b07e553b9e Merge pull request #2557 from rstudio/barret-upgrade-bootstrap-jqui
Upgrade Bootstrap (v3.4.1) and jQuery (v3.4.1)
2019-08-23 12:19:16 -05:00
Winston Chang
2d61709de3 Update reactiveValuesToList documentation 2019-08-23 11:48:29 -05:00
Barret Schloerke
1352e1d92d move news item to library updates and state 'resolved' 2019-08-23 12:47:40 -04:00
Barret Schloerke
b595c3b902 update htmldeps versions for jquery and bootstrap 2019-08-23 12:47:20 -04:00
Barret Schloerke
76efb01c4c add news item about upgrading bootstrap and jquery versions 2019-08-23 11:06:09 -04:00
Winston Chang
0078945b79 Fix link 2019-08-23 10:00:55 -05:00
Barret Schloerke
70d8ef0b8e update license info for bootstrap and jquery 2019-08-23 11:00:06 -04:00
Barret Schloerke
9a1f7cba68 change jquery v1.12.4 -> v3.4.1 2019-08-23 10:37:21 -04:00
Barret Schloerke
39e14acffe change bootstrap v3.3.7 -> v3.4.1 2019-08-23 10:36:16 -04:00
Alan Dipert
a6149390a0 Fix selectInput/selectizeInput handling character(1) options (#2540)
* selectInput/selectizeInput: Fix handling of character(1) choices

* Re-document

* Add .github to .Rbuildignore

* Expand comment, don't import stats

* Add test for 013-selectize regression

* Expand comment

* Split listify into series of passes

* Thouroughly overhaul and comment choicesWithNames()

* No recursion

* Comment new "flat" choice processing machinery

* Remove unneccesary test of choice tree with depth > 2

* Test for choices idiomatically

* Tweak comment for asCharacter

* Comment odd test, add a new test for single-item list

* Handle empty non-lists correctly, add test

* Add test ensuring empty lists come back named

* Add comment/assertion stipulating processGroupedChoices() takes only lists
2019-08-22 21:23:38 -05:00
Carson Sievert
33cdc75810 Throw an informative warning if a subdirectory of www clashes with another static path (#2434)
* Throw an informative warning if a subdirectory of www clashes with another static path, fixes #2433

* check all pairwise combinations of resource mappings

* Check for www subdir conflicts at startApp() time

* fix warning message

* review feedback; update news
2019-08-22 16:58:41 -05:00
Winston Chang
13f229089d Merge pull request #2459 from rstudio/resources
Introduce removeResourcePath()
2019-08-22 16:13:13 -05:00
Winston Chang
2dbb0fca85 Merge branch 'master' into resources 2019-08-22 16:12:58 -05:00
Winston Chang
c7a8a4e30f Update NEWS 2019-08-22 16:05:08 -05:00
Winston Chang
dc6f1a0c10 Fixes for R CMD check 2019-08-22 15:21:04 -05:00
Winston Chang
178872d651 Update fastmap version dependency 2019-08-20 13:23:55 -05:00
Barret Schloerke
e3c15493a2 Merge pull request #2545 from rstudio/barret-bug-dynamic-tab
Fix selected dynamic tab in deployed environments
2019-08-19 14:35:31 -04:00
Barret Schloerke
3f22e5da2d add news item 2019-08-19 14:24:42 -04:00
Winston Chang
39ee4513c6 Fix invalidateLater memory leak. Closes #2267 2019-08-19 12:21:12 -05:00
Barret Schloerke
598898f0a1 use boostrap url stripper regex to remove url before looking for relative tag location 2019-08-15 11:29:50 -04:00
trestletech
052e783638 Update to new signature in test. 2019-08-14 14:35:19 -05:00
trestletech
d2deda238a Move global.R sourcing into an exported load function 2019-08-14 14:25:05 -05:00
trestletech
7317a8304f Only load top-level R files in R/
Ignores nested directories to better follow R package conventions. We want to align well so that this structure is portable to golem.
2019-08-12 15:03:50 -05:00
trestletech
5ea9d70fb4 Require capitalized R/ dir. 2019-08-12 14:59:16 -05:00
Jeff Allen
a73e0998bc Correct mistake around app.R in global 2019-08-09 16:22:03 +00:00
trestletech
51befe3e27 Add news
and other minor changes from self-review
2019-08-08 15:55:08 -05:00
trestletech
37569a291b Fix options test 2019-08-08 14:48:19 -05:00
trestletech
7fe973145d Test ui/server/app/global sourcing. 2019-08-08 11:44:01 -05:00
trestletech
da3fc276fd Revert "DI the source function for testing."
This reverts commit c2dfea18c4.
2019-08-08 09:35:07 -05:00
trestletech
4c0af8b1c0 Revert "Break master 😈"
This reverts commit f65f7b2f1b.
2019-08-07 15:42:38 -05:00
trestletech
f65f7b2f1b Break master 😈
This reverts commit 545b6c1247.
2019-08-07 15:29:50 -05:00
trestletech
33c86ed6a7 Encrypt with --org
https://github.com/travis-ci/travis-ci/issues/7837
2019-08-07 14:55:44 -05:00
trestletech
545b6c1247 Revert "Break master 😈"
This reverts commit 1b0e37f371.
2019-08-07 14:09:05 -05:00
trestletech
1b0e37f371 Break master 😈 2019-08-07 14:06:55 -05:00
trestletech
97e00721e9 Add Travis Slack notifications on fail 2019-08-07 13:46:19 -05:00
Barret Schloerke
3c43301edb remove print statement 2019-08-07 12:45:20 -04:00
Barret Schloerke
51cbb67a96 use new RegExp 2019-08-07 12:21:38 -04:00
Barret Schloerke
2e2bd80416 remove leading url when removing relative url 2019-08-07 11:06:03 -04:00
Barret Schloerke
86389ff7a3 add print to debug appendTab 2019-08-07 10:44:59 -04:00
trestletech
c2dfea18c4 DI the source function for testing. 2019-08-06 14:08:25 -05:00
trestletech
4be6bbc681 Load helpers into isolated environment
And scaffold out the tests.
2019-08-06 10:49:38 -05:00
trestletech
cfc0ff9cc7 Fix expectations. 2019-08-06 09:10:18 -05:00
trestletech
b4c6ba6962 Add dynamically-generated case-sensitive test. 2019-08-06 09:05:02 -05:00
trestletech
dc3ed2f79b Support case-agnostic r/ dir loading 2019-08-05 17:33:07 -05:00
trestletech
5d95c7a9cb Load helpers in R/ on app startup
No support yet for case-sensitive file systems when loading the dir.
2019-08-05 17:25:14 -05:00
Alan Dipert
6821ca6238 Merge pull request #2543 from rstudio/buildignore-github
Add .github to .Rbuildignore
2019-08-05 14:32:20 -07:00
Alan Dipert
167dc0a259 Add .github to .Rbuildignore 2019-08-05 20:45:27 +00:00
Winston Chang
fa9fa68693 Re-document 2019-08-05 15:22:12 -05:00
Winston Chang
353615da89 Remove fastmap from Remotes because it is on CRAN 2019-07-29 11:01:01 -05:00
Winston Chang
51de558675 Rebuild JS objects 2019-07-26 10:41:21 -05:00
Winston Chang
174fc1dda1 Update JS build dependencies 2019-07-26 10:41:07 -05:00
Carson Sievert
7caeb60c47 add some historical context in the comment 2019-07-15 16:53:51 -05:00
Carson Sievert
e3aba1b5ff Introduce removeResourcePath() & throw message if the local path of a resource path has changed 2019-07-15 16:53:51 -05:00
Alan Dipert
1a8b36f06d selectInput: improve factor handling (#2524)
* selectInput: handle factor choices, fixes #2515

* Handle complex vectors

* Improve tests

* New item

* Update selectInput() docs to mention factors

* Un-S3-ify listify

* Bracketify the if/else

* Moar Brackets

* Fix travis: we hope

* Use existing asNamedVector function

* Better implementation of asNamedVector

* Clarify comments
2019-07-15 14:51:13 -05:00
Winston Chang
250303790c Bump version to 1.3.2.9001 2019-07-09 13:56:39 -05:00
Winston Chang
e20544659a Merge pull request #2523 from rstudio/joe/feature/readable-outputs
Support reading of Shiny outputs
2019-07-09 12:19:54 -05:00
Joe Cheng
ad7692ed34 output$xxx should return the actual func passed in
...not the frankenstein one we create to clean up the stack trace
2019-07-06 13:20:44 -07:00
Joe Cheng
f9144a4be3 Make output reading compatible with modules 2019-07-05 19:22:41 -07:00
Winston Chang
0fc3b90efb tham -> than 2019-07-03 20:52:15 -05:00
Winston Chang
25ccc8a77a Merge pull request #2484 from rstudio/weakref
Use weakrefs for reactive value to reactive expression dependencies
2019-07-03 20:49:33 -05:00
Winston Chang
da18390f3e Import and re-export fastmap::key_missing (#2517)
* Import and re-export fastmap::key_missing

* Fix for staticdocs index
2019-07-03 15:45:42 -05:00
Winston Chang
b392bf8298 Update rlang dependency info 2019-07-03 15:37:16 -05:00
Joe Cheng
73c42ebeaf Merge pull request #2516 from rstudio/fix-shinyapp-doc
Remove outdated information for shinyApp()
2019-07-03 10:41:28 -07:00
Winston Chang
eb45f7fcba Remove outdated information for shinyApp() 2019-06-28 22:31:29 -05:00
Jeff Allen
5fdca29448 Clarify interaction between width/height and CSS/templates (#2504)
* Clarify interaction between width/height and CSS/templates

* Reword given that height is less likely to be specified in CSS.
2019-06-25 10:56:57 -05:00
Jeff Allen
048c4006e4 en dashes -> em dashes (#2513) 2019-06-25 10:46:52 -05:00
Jeff Allen
6d10a2dafb Merge pull request #2510 from rstudio/jeff-md
Convert docs to MD
2019-06-25 13:53:07 +00:00
trestletech
d6c421f8de Fix more hyperlinks 2019-06-20 12:03:56 -05:00
trestletech
ac4adcc62c Fix shinyOptions hyperlinking 2019-06-20 11:51:45 -05:00
trestletech
bc8465d284 Commit generated MD with new links, not manually reviewed. 2019-06-19 15:50:47 -05:00
trestletech
7fc497eeb8 Auto-generated link conversation, not manually reviewed. 2019-06-19 15:46:13 -05:00
trestletech
633817e3d5 Manually escape another % that wasn't getting rendered properly. 2019-06-19 15:43:16 -05:00
trestletech
09dee9670a Manually escape one % sign that wasn't getting escaped? 2019-06-19 15:42:24 -05:00
trestletech
631debbec4 Restore one \code{} block that contains inner backticks 2019-06-19 15:38:47 -05:00
trestletech
4e57bc2161 Fix syntax error with double-backticks. 2019-06-19 15:32:01 -05:00
trestletech
a111e36867 Accept harmless RD changes. 2019-06-19 15:30:55 -05:00
trestletech
152bd5841c Accept whitespace-only RD changes. 2019-06-19 15:29:54 -05:00
trestletech
ecefdcd951 Convert R to MD
Used roxygen2md::roxygen2md(scope="simple")

Not manually reviewed.
2019-06-19 15:28:03 -05:00
trestletech
a976cfa98d Remove escaping for % in preparation for MD conversion
Obtained by running `sed -i "" -E "s/^(.*)\\\%(.*)$/\1%\2/g" *` in the R
directory on a Mac.
2019-06-19 15:13:25 -05:00
trestletech
df70d7708d Result of running roxygen2md(scope = "none")
Enables markdown. Only observed one non-whitespace difference on a line
that had used backticks previously which were previously not being
parsed as a code block.

-explicitly using the `title` parameter of the top-level page function.
+explicitly using the \code{title} parameter of the top-level page function.
2019-06-19 14:47:04 -05:00
Jeff Allen
c558d95e3b Merge pull request #2507 from rstudio/jeff-ci-docs
Test for Roxygen doc & JS changes in Travis
2019-06-19 19:24:11 +00:00
trestletech
3bd4825d4b Write errors to stderr. 2019-06-19 11:34:59 -05:00
trestletech
67cdcedd4e Better bash 2019-06-19 11:04:39 -05:00
trestletech
384116a76f Specify node version 2019-06-19 10:22:55 -05:00
trestletech
12e91ae643 Script to check for JS. 2019-06-19 10:09:21 -05:00
trestletech
7c56d277da Try matrix build for Roxygen check. 2019-06-18 20:20:25 -05:00
trestletech
579a4592b8 Test for Roxygen doc changes in Travis
I'd prefer to do the doc check prior to the package check so that we can
fail fast in light of trivial errors, but I worry about the side-effects
of installing devtools and roxygen2 on our tests, so I'm punting those
tasks until after our CMD check.

It may be possible to parallelize this work adjacent to our package
check (and only do it on one version of R rather than all three), but I
haven't explored that yet.

Failures in the `after_script`s don't fail the build, surprisingly. The
`|| travis_terminate 1` accomplishes that.  `travis_terminate` taken
from
https://github.com/travis-ci/travis-ci/issues/1574#issuecomment-164094347

`git clean` incantations found in
https://issues.jenkins-ci.org/browse/JENKINS-31924
2019-06-18 16:48:22 -05:00
Jeff Allen
9dad5e6362 Define optgroup when using (#2502) 2019-06-18 16:06:29 -05:00
Jeff Allen
f51b5421f2 Add sep argument to renderText (#2497)
* Add sep argument to renderText

Closes #2469

* Add link to PR

* Regenerate docs
2019-06-14 16:26:28 -05:00
Winston Chang
387907ea32 Upgrade JS build dependencies 2019-06-14 16:18:53 -05:00
trestletech
b5ca1d48e0 Add link to renderCachedPlot.
Closes #2476
2019-06-14 14:22:49 -05:00
trestletech
396f170738 Bundle deprecated reactive functions into a single file. 2019-06-14 14:20:31 -05:00
Jeff Allen
5514039d42 M0ar README words
Give a bit more detail about validating install, and avoid calling things easy.
2019-06-14 14:18:44 -05:00
Winston Chang
c90c4f3673 Suppress stack traces in tests 2019-06-14 10:59:45 -05:00
Winston Chang
41758858cf Fix react logging for reactiveValues 2019-06-14 10:58:50 -05:00
Joe Cheng
3ff507e6b8 Merge pull request #2493 from rstudio/jeff-internal-docs
Mark deprecated functions as internal
2019-06-13 14:34:03 -07:00
trestletech
5199371025 Mark deprecated functions as internal.
This prevents them from being listed in the documentation index. Closes #2482.
2019-06-13 15:47:20 -05:00
Winston Chang
26ad773f77 Switch from fastmap to rlang for weakref functions 2019-06-13 14:52:14 -05:00
Winston Chang
9e133e0ecc More memory leak tests 2019-06-11 20:21:16 -05:00
Winston Chang
c4e7099229 Reactive expressions keep reference to context 2019-06-11 19:19:52 -05:00
Winston Chang
56062628f2 Use Dependents in ReactiveValues 2019-06-11 19:19:31 -05:00
Winston Chang
48a3a1dabb Use weak references for dependents of reactive values 2019-06-10 20:43:28 -05:00
Winston Chang
ca3c2b3e26 Use weak references for reactive contexts 2019-06-06 13:35:56 -05:00
Winston Chang
d35c5c8320 Merge pull request #2479 from rstudio/wch-consistent-reactive-order
Ensure that observers fire in consistent order
2019-06-06 13:22:05 -05:00
Winston Chang
749a582296 Update NEWS 2019-06-04 16:12:12 -05:00
Winston Chang
6310406430 Add tests for observer order 2019-06-04 16:07:04 -05:00
Winston Chang
d26d339f97 Ensure that dependents are sorted 2019-06-04 14:02:36 -05:00
Winston Chang
17afce6fa1 Merge pull request #2429 from rstudio/wch-fastmap
Use fastmap as backing store for Map class
2019-05-31 15:39:34 -05:00
Joe Cheng
d3aa601798 Make Shiny outputs (optionally) readable 2019-05-31 09:25:27 -07:00
Winston Chang
8f24d667d6 Unquote key 2019-05-30 15:12:15 -05:00
Winston Chang
5cd4588ef2 Use grep(value=TRUE) 2019-05-30 14:38:05 -05:00
Winston Chang
b0a1821d95 Rebuild shiny.js 2019-05-30 14:32:52 -05:00
Winston Chang
6b835f70e6 Merge pull request #2460 from rstudio/wch-disable-plot-drag
Disable dragging of plots with any interactions enabled
2019-05-30 14:32:00 -05:00
Winston Chang
308bc76ac6 Disable dragging of plots with any interactions. Closes #1393, #2223 2019-05-29 15:16:11 -05:00
Winston Chang
fd843509a1 Fix NEWS formatting 2019-05-29 11:59:13 -05:00
Winston Chang
7691cfdadb Merge pull request #2446 from nteetor/master
New target for `shiny:inputchanged` event
2019-05-29 11:57:55 -05:00
nteetor
1aa9368e54 Update inputchanged news item with pr number, move to improvements 2019-05-23 20:11:44 -04:00
nteetor
180e852fee Trigger shiny:inputchanged event on related input element (#2442) 2019-05-22 20:01:33 -04:00
Alan Dipert
547edd7e32 Fix feature request template 2019-05-21 11:14:02 -07:00
Winston Chang
0b46c63c31 Fix testthat version number 2019-05-16 16:43:01 -05:00
Carson Sievert
9b69ce1988 yarn build 2019-05-14 16:44:33 -05:00
Carson Sievert
57cc44f662 Coordmap info should retain discrete limits (#2410)
* ggplot2 input brushes should retain discrete range mapping, and be imposed in brushedPoints(), closes #1433

* simplify logic and reduce required storage

* get nearPoints() working as well, cleanup

* only remember scale range if ggplot is facet with a free discrete axis

* Use the scale limits (before the range) since the former is specified, that's what is actually shown on the plot

also, introduce within_brush() helper to consistently handle missing values produced by asNumber()

* also use scale limits in older versions of ggplot2

* DRY

* discrete_mapping -> discrete_limits; better comments

* update test expectation

* a couple unit tests

* update comment to reflect new coordmap data structure

* use unlink() not rm()

* add some tests for specifying scale limits and labels

* Use get_limits() if available

* update news

* better name and comment for new asNumber() argument
2019-05-14 16:34:00 -05:00
Carson Sievert
4eaa9c7ea9 Don't match text inputs with a trailing '-selectized' in their id, fixes #2396 (#2418)
* Don't match text inputs with a trailing '-selectized' in their id, fixes #2396

* update news

* parentheses
2019-05-14 16:26:32 -05:00
Winston Chang
0b6cdcc826 fastmap moved to r-lib 2019-05-14 11:46:57 -05:00
Winston Chang
7bc0a0ca39 Fix tests that assumed names in a specific order 2019-05-14 10:41:06 -05:00
Winston Chang
1ef2074a10 Fastmap objects can now be saved and loaded 2019-05-14 10:36:37 -05:00
Winston Chang
0747b2a72a fastmap: exists() was renamed to has() 2019-05-14 10:35:50 -05:00
Alan Dipert
64b3095f2c Removed redundant section of issue template 2019-05-10 10:07:30 -07:00
Winston Chang
ab82af122f Merge pull request #2436 from rstudio/alan/issue-templates
Add issue templates
2019-05-10 12:05:35 -05:00
Alan Dipert
54fccf2e7c Incorporate feedback from @wch 2019-05-10 10:01:03 -07:00
Alan Dipert
05e953db3a Improve bug report template 2019-05-10 08:28:05 -07:00
Alan Dipert
f726835850 Add issue templates 2019-05-09 23:04:19 -07:00
Winston Chang
38d2809131 Convert MemoryCache to use fastmap 2019-05-09 10:20:33 -05:00
Winston Chang
d7718991a6 Import fastmap::fastmap 2019-05-09 10:20:33 -05:00
Winston Chang
32c2bff6eb Convert ReactiveValues$.metadata to use Map 2019-05-09 10:20:33 -05:00
Winston Chang
555ede03ed Convert ReactiveValues$.values to use Map 2019-05-08 20:33:52 -05:00
Winston Chang
2a6f218700 Convert ReactiveValues$.dependents to use Map 2019-05-08 20:33:52 -05:00
Winston Chang
b087c19b52 Use fastmap as backing store for Map class 2019-05-08 20:33:52 -05:00
Carson Sievert
6fed1c60ac update news (should've been done in #2404) 2019-05-08 16:36:46 -05:00
Carson Sievert
b10f2a5291 yarn build 2019-05-08 16:30:59 -05:00
Winston Chang
a4a49a354e Merge pull request #2404 from rstudio/inputRateName
Fix issue with input rate policies
2019-05-08 16:24:02 -05:00
Carson Sievert
ead23528ca doSetInput calls setInput (duh) so should have name and type 2019-05-08 16:19:21 -05:00
Carson Sievert
b8644949cc camelCase for consistency; clarify comment 2019-05-08 16:19:13 -05:00
Carson Sievert
b88e3a64f2 comment on the difference between name_type and name 2019-05-08 16:19:07 -05:00
Carson Sievert
2871b423fd rename name arg to name_type where relevant in input decorators...
this will help to highlight when you should call a method with just the input name instead of both the name and the type
2019-05-08 16:19:02 -05:00
Carson Sievert
562fafbc39 pass inputName to immediateCall() and normalCall() 2019-05-08 16:18:55 -05:00
Carson Sievert
191e0874f8 type is only relevant for public methods setInput() and setRatePolicy()
change the name of these arguments to reflect this (name_type)
2019-05-08 16:18:47 -05:00
Carson Sievert
fa5ff7bfa5 Consistently ignore input type in all InputRateDecorator methods 2019-05-08 16:18:39 -05:00
Carson Sievert
82e80ccdeb InputRateDecorator's setInput method needs to strip of the input's ttype before looking up the input's rate policy, closes #2387 2019-05-08 16:18:19 -05:00
Carson Sievert
ff84cf5a18 update news (#2428) 2019-05-08 16:08:20 -05:00
Winston Chang
44843a7768 Merge pull request #2406 from rstudio/null-label
Input label updating
2019-05-08 15:52:09 -05:00
Carson Sievert
68eeb338da Have input labels always include 'control-label' class 2019-05-08 15:15:09 -05:00
Carson Sievert
ea54c17902 merge with master 2019-05-08 15:10:22 -05:00
Barret Schloerke
d5ad7eed40 Merge pull request #2424 from rstudio/joe/bugfix/reactive-value-not-changing
Fix rstudio/reactlog#36: Changes to reactive values not displaying accurately
2019-05-08 12:01:08 -04:00
Joe Cheng
c2430cd3f4 Update NEWS 2019-05-07 09:33:59 -07:00
Joe Cheng
8a0731493f Fix rstudio/reactlog#36: Changes to reactive values not displaying accurately 2019-05-07 09:30:59 -07:00
Carson Sievert
07e2b80b5d merge with master; fix NEWS conflicts 2019-05-03 17:21:06 -05:00
Carson Sievert
1311e1fca2 have class come before the for attribute 2019-05-03 17:16:17 -05:00
Winston Chang
e6c2133520 Merge pull request #2416 from rstudio/updateSliderInput
getSliderType() should be able to handle NULL min/max/value, fixes #2250
2019-05-03 16:54:57 -05:00
Carson Sievert
3d6f734ff2 update comment 2019-05-03 15:58:45 -05:00
Carson Sievert
e0eaa58779 update news 2019-05-03 15:57:55 -05:00
Carson Sievert
ced6622b25 Have getSliderType() return '' early if min, max, and value are NULL 2019-05-03 15:54:48 -05:00
Carson Sievert
2d2cf96f5e missed input_binding_slider.js 2019-05-03 15:48:47 -05:00
Carson Sievert
370f1b51ee Inputs now always supply a <label> tag with a special CSS class for hiding NULL labels
This helps to simplify the updating logic on the client
2019-05-03 15:38:57 -05:00
Winston Chang
67d3a504ae Merge pull request #2403 from rstudio/dateFormat
Consistent approach to coercing and formatting date strings
2019-05-03 10:58:06 -05:00
Carson Sievert
34ee48ef93 update news 2019-05-02 10:46:08 -05:00
Carson Sievert
c61a585e79 getSliderType() should be able to handle NULL min/max/value, fixes #2250 2019-05-01 19:41:26 -05:00
Carson Sievert
09388c9f07 Apply label updating logic all relevant input labels 2019-05-01 18:55:36 -05:00
Carson Sievert
b1bc78dad3 fix news link 2019-05-01 11:19:40 -05:00
Carson Sievert
a5a0f23c3a Use jQuery's text() method for proper escaping when inserting data.label string 2019-04-30 17:33:26 -05:00
Carson Sievert
4c50c064d3 make return value of dateYMD() slightly more clear 2019-04-30 17:08:13 -05:00
Carson Sievert
a63f271300 update news 2019-04-30 17:00:34 -05:00
Carson Sievert
08b22ff550 update NEWS 2019-04-30 17:00:34 -05:00
Carson Sievert
b04133bf65 Include argName with warning when length > 1 2019-04-30 17:00:34 -05:00
Carson Sievert
3602358d2c fix typo in warning message 2019-04-30 17:00:34 -05:00
Carson Sievert
67b0416eba Throw informative warning if date coercion fails and original input 2019-04-30 17:00:34 -05:00
Carson Sievert
f8d69ecb1f Consistent approach to coercing and formatting date strings, closes #2402 2019-04-30 17:00:34 -05:00
Carson Sievert
5e8bc204c1 make sure to remove label tag from DOM if label is updated to NULL 2019-04-26 19:08:15 -05:00
Carson Sievert
938332d646 Have textInput()'s receiveMessage method insert a label tag if one is needed, closes #868 2019-04-26 16:56:53 -05:00
Winston Chang
386078d441 Merge tag 'v1.3.2' 2019-04-23 14:07:37 -05:00
Winston Chang
4d778faaf4 Bump version to 1.3.2 2019-04-18 11:51:16 -05:00
Winston Chang
3055cf5602 Update NEWS 2019-04-18 11:49:09 -05:00
Joe Cheng
36373ba28b Merge pull request #2386 from rstudio/joe/bugfix/subapp-routing
Fix #2385: R Markdown documents containing subapps not rendering properly
2019-04-18 08:49:56 -07:00
Joe Cheng
1415b57181 Add sys.www.root to createAppHandlers, so that subapps can access /shared/* 2019-04-16 18:40:29 -07:00
Joe Cheng
65d4a4e906 Add comments 2019-04-16 18:12:09 -07:00
Joe Cheng
0abe221227 Use v1.3.1.9000 2019-04-14 17:21:26 -07:00
Joe Cheng
1b8d822226 Fix #2385: R Markdown documents containing subapps not rendering properly 2019-04-14 17:19:17 -07:00
Winston Chang
bc8fbd60d7 Bump version to 1.3.1.9000 2019-04-12 11:13:32 -05:00
Winston Chang
4c332eac9a Merge tag 'v1.3.1'
Shiny 1.3.1 on CRAN
2019-04-12 11:12:59 -05:00
Joe Cheng
f5392d77dc Merge pull request #2382 from rstudio/fix-index-html
Fix serving of www/index.html
2019-04-11 11:43:44 -07:00
Winston Chang
1e88990a0b Fix serving of www/index.html. Closes #2380 2019-04-11 11:57:48 -05:00
Joe Cheng
de4c7567d0 Manually bump the version numbers in shiny.js and shiny.min.js
Normally this would be where we grunt, but for this hotfix we
need to avoid the changes that went in at the end of 1.3.0 that
were accidentally left out of the built JS.
2019-04-10 11:42:42 -07:00
Joe Cheng
aff33dd023 Bump version to 1.3.1 2019-04-10 11:35:05 -07:00
Barret Schloerke
a287ebe324 Minimize str usage in rlog$valueStr (#2377)
* return early if loggin is disabled

* do not allow str to recurse

* add news item for #2377

* change "  " to " "

* Not a "world-ending performance issue"
2019-04-10 11:27:29 -07:00
Winston Chang
583a8d1001 Merge pull request #2353 from rstudio/fix-verbatim-text-wrap
Don't wrap text in verbatimTextOuput in Safari
2019-04-08 16:20:18 -05:00
Winston Chang
36a808add0 Update NEWS 2019-04-08 13:22:57 -05:00
Winston Chang
f651d4a274 Don't wrap text in verbatimTextOuput in Safari. Closes #2233 2019-04-08 13:20:20 -05:00
Winston Chang
f6e8e645f2 Bump version to 1.3.0.9000 2019-04-08 13:19:57 -05:00
Winston Chang
b4d2f88b74 Merge tag 'v1.3.0'
Shiny v1.3.0 on CRAN
2019-04-08 12:01:05 -05:00
Winston Chang
c524a736bd Re-document 2019-03-29 17:25:14 -05:00
Winston Chang
cdf3bf18f0 Fix broken URL 2019-03-29 16:55:41 -05:00
Winston Chang
b21bdacb4f Remove reactlog from Remotes 2019-03-27 13:42:25 -05:00
Winston Chang
92019b5ba3 Merge pull request #2361 from rstudio/fix-svg-foreignobject
Fix #2348, #2329, #1817: bugs triggered by networkD3 sankey plot
2019-03-27 13:40:15 -05:00
Alan Dipert
908d635063 Fix #2349, #2329, #1817: bugs triggered by networkD3 sankey plot
* All of these were caused by the presence of multiple body tags on the
page, which happened because networkD3's sankey plot generates SVGs
containing body tags via SVG's foreignObject tag
* In various places, the 'body' jQuery selector string is used under the
assumption there is only one 'body' tag on the page. The presence of
multiple 'body' tags breaks reliant code in strange ways.
* The fix was to use document.body or 'body:first' instead of 'body'.
2019-03-27 11:36:19 -07:00
Alan Dipert
20329feb7f Improve bootstrap-datepicker update tools, add docs 2019-03-26 20:33:42 -07:00
Alan Dipert
4cd92a1cd9 Add 'Fix datepicker DST bug' as patch
- Original commit: 0683b79
2019-03-26 20:33:32 -07:00
Alan Dipert
8ca3397c5d Improve bootstrap-datepicker update script 2019-03-26 20:33:20 -07:00
Alan Dipert
05cd79481e Re-import bootstrap-datepicker 1.6.4 2019-03-26 17:34:47 -07:00
Winston Chang
c0f1905785 Remove httpuv and reactlog from remotes 2019-03-26 15:18:00 -05:00
Alan Dipert
9afc06028d Restore intuitive bookmarking behavior (#2360)
* Adding flushPending() to ShinySession's flushOutput() restores intuitive bookmarking behavior

* Check that restoreContext is present

* Update NEWS
2019-03-26 15:08:34 -05:00
Barret Schloerke
7b6cc50238 Merge branch 'master' into rc-v1.3.0
* master:
  fix shortString is NA or NULL logic
  add coverage for situation where label might be na or NULL
  increase default length of label to 250chars from 100chars
  make sure labels are short for reactlog
2019-03-01 15:45:19 -05:00
Barret Schloerke
722b1d0258 Merge pull request #2345 from rstudio/short_reactlog_labels
Shorter reactlog labels
2019-03-01 14:43:59 -06:00
Barret Schloerke
93d3b78ac1 fix shortString is NA or NULL logic 2019-03-01 15:22:40 -05:00
Barret Schloerke
69e82f6e0e add coverage for situation where label might be na or NULL 2019-03-01 14:57:05 -05:00
Barret Schloerke
1f83a6db7b increase default length of label to 250chars from 100chars 2019-03-01 14:34:21 -05:00
Barret Schloerke
8f37951e14 make sure labels are short for reactlog 2019-03-01 14:30:23 -05:00
Joe Cheng
e1f4d43926 Merge pull request #2342 from rstudio/reactlog-cran
Reactlog github location removed
2019-02-27 10:31:08 -08:00
Joe Cheng
eb6139276f Merge pull request #2343 from rstudio/fix-resource-path
addResourcePath: create staticPath object immediately. Fixes #2339
2019-02-27 10:27:09 -08:00
Winston Chang
f18c426151 addResourcePath: create staticPath object immediately. Fixes #2339 2019-02-27 11:12:55 -06:00
Barret Schloerke
e46debb6d1 remove github location for reactlog and clean up flow of check_suggested 2019-02-27 09:19:46 -05:00
Barret Schloerke
d8b8739cb8 use httpuv rc-v1.5.0 branch 2019-02-26 16:57:28 -05:00
Barret Schloerke
9fd8eefa59 Merge branch 'master' into rc-v1.3.0
* master:
  Make sure the is.na() check in %AND% looks for length-1 input
2019-02-26 16:21:24 -05:00
Barret Schloerke
fd2af06a53 run grunt 2019-02-26 16:21:01 -05:00
Barret Schloerke
48f945ba7f use reactlog rc-1.0.0 branch 2019-02-26 16:19:24 -05:00
Barret Schloerke
6d59f88a76 bump news and description versions to 1.3.0 2019-02-26 16:19:07 -05:00
Joe Cheng
8b94d4626d Merge pull request #2338 from rstudio/fix-and
Make sure the is.na() check in %AND% looks for length-1 input
2019-02-26 13:11:39 -08:00
Winston Chang
d7d8e78e42 Make sure the is.na() check in %AND% looks for length-1 input
This is to avoid errors with R CMD check on R-devel like this:
https://travis-ci.org/rstudio/shiny/jobs/498880293
2019-02-26 14:32:41 -06:00
Joe Cheng
9755f86f53 Merge pull request #2327 from rstudio/staticpath-exclude
Exclude "session" from static path serving
2019-02-26 12:17:30 -08:00
Winston Chang
599a3ee82f Simplify session placement 2019-02-26 13:02:23 -06:00
Winston Chang
c790346490 Merge pull request #2284 from chasemc/patch-1
Fix typo
2019-02-21 14:04:40 -06:00
Joe Cheng
68cf3a9111 Merge pull request #2311 from rstudio/bookmark-dot
Bookmarking: restore inputs that have a leading dot
2019-02-21 11:56:40 -08:00
Barret Schloerke
59221dfcf2 bump dev version of reactlog. remove reactlog::reactlog_add_shiny_resource_paths() 2019-02-15 15:52:05 -06:00
Winston Chang
020413a206 Always exclude /session from static paths 2019-02-15 15:08:26 -06:00
Winston Chang
a343e9ebdf Use excludeStaticPath() function 2019-02-14 21:15:20 -06:00
Winston Chang
c304efee36 Exclude "session" from static path serving. Fixes #2325 2019-02-12 20:28:47 -06:00
Winston Chang
95173f676d Merge pull request #2319 from rstudio/joe/misc/constant-time-check
Add constant time check for shared secret
2019-02-11 15:22:54 -06:00
Joe Cheng
87d1db1f2b Fix test 2019-02-11 10:02:40 -08:00
Barret Schloerke
d445f384c7 Merge pull request #2315 from rstudio/reactlogShow
Add methods: reactlog, reactlogShow, and reactlogReset. Deprecate showReactLog
2019-02-07 15:05:05 -06:00
Joe Cheng
59dd4b0721 Code review feedback
- Rename sharedSecret variables to checkSharedSecret
- Don't perform the digest::digest(). This just means the timing could
  give away the length of the secret, but that's OK, there's enough
  entropy in the secret even if you know its length.
2019-02-05 14:33:04 -08:00
Joe Cheng
d73c91d4a7 Add unit tests for shared secret check 2019-02-04 14:19:02 -08:00
Joe Cheng
665a66522e Add constant time check for shared secret 2019-02-04 13:19:47 -08:00
Barret Schloerke
ba1efa65fa update man file name to reactlog from showReactLog in inst/staticdocs/index.r 2019-02-01 16:29:03 -05:00
Barret Schloerke
64a74692b9 document time for reactlogShow 2019-02-01 16:05:33 -05:00
Barret Schloerke
46cd285dd0 update docs by removing showReactLog/reactlogShow (to reactlog) as much as possible 2019-01-30 16:01:22 -05:00
Barret Schloerke
bcac115c3d Add methods: reactlog, reactlogShow, and reactlogReset. Depricate showReactLog
Update links to help file to not use `showReactLog`, but `reactlogShow`
Use updated reactlog pkg function api of reactlog_*. This may fail right now, but rerun travis when the reactlog code is merged into master.
2019-01-30 12:20:22 -05:00
Winston Chang
77ddb2c8c2 Bookmarking: restore inputs that have a leading dot. Fixes #2308 2019-01-23 12:05:24 -06:00
Barret Schloerke
8ae31eb998 Merge pull request #2107 from schloerke/barret/reactlog
Upgraded reactlog logging and support for shinyreactlog rendering
2019-01-11 13:19:14 -05:00
Barret Schloerke
7551a6ae1d add stats:: to setNames function calls
helps pass R CMD check
2019-01-11 13:04:39 -05:00
Barret Schloerke
93be659b1b merge Remotes 2019-01-11 12:45:59 -05:00
Barret Schloerke
3327878fc2 merged from master 2019-01-11 12:33:31 -05:00
Winston Chang
0b25c7f3c1 Merge pull request #2280 from rstudio/static-file
Use httpuv static file serving
2019-01-11 10:56:52 -06:00
Barret Schloerke
b606ba4dd7 added news item for reactlog 2019-01-11 09:43:25 -05:00
Chase Clark
0269bc810c Fix typo
"...use the JavaScript library selectize.js (https://github.com/selectize/selectize.js) ~~ to~~ instead of the basic select..."
2018-12-17 12:59:57 -06:00
Barret Schloerke
f2775f2c1d update rLog$msg output tests 2018-12-14 16:18:20 -05:00
Barret Schloerke
f06274aec6 fixed bad argument placement 2018-12-14 16:01:25 -05:00
Barret Schloerke
dfa686a3e0 always display the first n chars in a rLog$valueChange or rLog$define
capture the value in a try statement of capture.output of str
2018-12-14 15:51:31 -05:00
Barret Schloerke
fe679b5de5 add reactId to rLog$invalidateLater 2018-12-14 15:49:45 -05:00
Barret Schloerke
aa1eb0410c add force option to retrieving reactive info 2018-12-14 14:10:34 -05:00
Barret Schloerke
1b06bab7ee add define observer to rLog 2018-12-14 12:05:37 -05:00
Barret Schloerke
0f13056aa2 fix rLog$reset to work as an installed package. added a dummy context reactId (different from noReactId) 2018-12-14 12:05:22 -05:00
Barret Schloerke
beecf60db7 use rLog$reset() instead of initializeReactlog() due to changing global binding error 2018-12-13 17:04:12 -05:00
Barret Schloerke
160a2013bc fix broken test 2018-12-13 16:52:44 -05:00
Barret Schloerke
b8c636e87e move the actual setting of the reactiveValues key higher in set command for accurate logging 2018-12-13 16:52:35 -05:00
Barret Schloerke
add40e5926 when calling rlog$define, set a value 2018-12-13 16:51:32 -05:00
Barret Schloerke
960e7f3b24 fix .globals binding issue 2018-12-13 16:50:13 -05:00
Barret Schloerke
3e749f36e8 turn off logging of value in console 2018-12-13 16:50:03 -05:00
Barret Schloerke
8198d99309 add rlog$invalidateLater(runningCtxId, millis, domain) 2018-12-13 14:49:27 -05:00
Barret Schloerke
81de1c8ed4 remove setLabel from ReactiveValues 2018-12-13 14:42:25 -05:00
Barret Schloerke
3eb55e9d9b update reactiveValues set comments 2018-12-13 14:34:58 -05:00
Barret Schloerke
6b6ac86aea async start stop rLog should use domain = self 2018-12-13 14:33:29 -05:00
Barret Schloerke
1b45e70cbb use rLog$noReactId constant 2018-12-13 14:32:40 -05:00
Barret Schloerke
929f7ec235 document 2018-12-13 13:26:49 -05:00
Barret Schloerke
cf28d7e470 init testing for msg logging 2018-12-13 13:26:42 -05:00
Barret Schloerke
b0a00108f3 log, action, then perform invalidate action 2018-12-13 13:26:26 -05:00
Barret Schloerke
01151fc7f8 dummy context should be created every time. allow for id to be passed in 2018-12-13 13:26:12 -05:00
Barret Schloerke
bf8dbc38c7 add a noReactId label and init rLog method 2018-12-13 13:25:53 -05:00
Barret Schloerke
ae0d4d9353 add a default reactId for contexts for clearer msg logs and rLogs 2018-12-13 10:48:32 -05:00
Barret Schloerke
43ec4ae238 add helper functions for msg logger. 2018-12-13 10:48:02 -05:00
Barret Schloerke
c568a8cabe when updating a value for reactVal or a reactValues key, the context should not be recorded 2018-12-13 10:46:12 -05:00
Barret Schloerke
423bdd8b6b read reactlog version from description file 2018-12-12 11:27:17 -05:00
Barret Schloerke
1e19ff65e6 fix bad comma usage 2018-12-12 11:04:36 -05:00
Barret Schloerke
a9cf632f53 markTime -> userMark; queueEmpty -> idle 2018-12-12 10:58:28 -05:00
Barret Schloerke
fddf94a341 this check is already covered 2018-12-11 17:23:22 -05:00
Barret Schloerke
203168d261 dec/increment with integers 2018-12-11 17:23:13 -05:00
Barret Schloerke
0e3c3536f8 no need to store messages 2018-12-11 17:22:59 -05:00
Barret Schloerke
45b2b7e24f use curly brackets for all function defs 2018-12-11 17:22:33 -05:00
Barret Schloerke
88f177b065 use class brackets for R6 def 2018-12-11 17:22:09 -05:00
Barret Schloerke
ea7a8dd3ad consistent naming 2018-12-11 17:14:30 -05:00
Barret Schloerke
dda8f92494 remove writeReactLog 2018-12-11 17:13:09 -05:00
Barret Schloerke
26211802cd spelling and comments 2018-12-11 17:12:59 -05:00
Barret Schloerke
b4bef0d32c use reactlog::reactlog_add_shiny_resource_paths 2018-12-11 17:12:38 -05:00
Winston Chang
a8bf203067 Grunt 2018-12-10 14:34:27 -06:00
Winston Chang
624dd2e99d Bump version to 1.2.0.9001 2018-12-10 14:19:48 -06:00
Barret Schloerke
26a136a6e8 check_suggested now takes a github location and a source install script 2018-12-04 14:38:14 -05:00
Winston Chang
2d57ffa546 Update NEWS 2018-12-03 12:13:54 -06:00
Winston Chang
428b81a6d9 Use httpuv master branch 2018-12-03 12:10:04 -06:00
Barret Schloerke
f24c12fdfb shinyreactlog -> reactlog 2018-11-30 16:02:00 -05:00
Barret Schloerke
9a345d191b merge in master 2018-11-27 10:33:11 -05:00
Winston Chang
fec706d134 Add headers for static serving 2018-11-20 12:25:46 -06:00
Winston Chang
c338448997 Use shiny-shared-secret validation for static files 2018-11-20 12:25:46 -06:00
Winston Chang
956c1cb1a7 Use setStaticPath instead of setStaticPaths 2018-11-20 12:25:46 -06:00
Winston Chang
8831b4da9e Use static serving for app's own assets 2018-11-20 12:25:46 -06:00
Winston Chang
f8bd60dcd7 Use httpuv static serving 2018-11-20 12:25:46 -06:00
Winston Chang
6a373b585c Merge pull request #2248 from rstudio/fix-selectize-label
Make updateSelectizeInput() work with labels again
2018-11-15 17:04:16 -06:00
Winston Chang
54480e2510 Merge branch 'master' into fix-selectize-label 2018-11-15 17:03:58 -06:00
Joe Cheng
83f73603db Merge pull request #2257 from colearendt/fix-htmltools-dep
fix dependency version since htmltools 0.3.6 is used
2018-11-15 14:39:37 -08:00
Joe Cheng
2b10f192ba Merge pull request #2261 from rstudio/joe/bugfix/async-rendercachedplot
Fix #2247: Async cached plots raise "Error in !: invalid argument type" error
2018-11-15 14:39:07 -08:00
Winston Chang
775d5289cb Grunt 2018-11-15 15:23:35 -06:00
Winston Chang
e6c66352a7 Update NEWS 2018-11-15 15:23:35 -06:00
Winston Chang
77afd73ee1 Use new selectize suffix. Fixes #2245 2018-11-15 15:23:35 -06:00
Winston Chang
5ac96a40aa Remove QuitChildProcessesOnExit: Default option 2018-11-15 15:10:54 -06:00
Winston Chang
2fea0e2598 Don't byte-compile when doing local install in RStudio 2018-11-15 15:08:49 -06:00
Joe Cheng
2b64949cbe Fix #2247: Async cached plots raise "Error in !: invalid argument type" error 2018-11-14 16:45:40 -08:00
Cole Arendt
918d57f25e fix dependency version since htmltools 0.3.6 is used 2018-11-11 15:04:44 -05:00
Joe Cheng
5e2b40d3a9 Bump version for development 2018-11-02 13:11:04 -07:00
Joe Cheng
979ef4bd43 Merge remote-tracking branch 'origin/v1.2-rc' 2018-11-02 13:10:48 -07:00
Winston Chang
914baf594b Merge pull request #2241 from rstudio/joe/bugfix/icon-examples
Remove icon examples
2018-11-01 20:41:58 -05:00
Joe Cheng
02b0802886 Add note about FontAwesome path change 2018-11-01 15:08:59 -07:00
Joe Cheng
0725239397 Remove icon examples
These cause browser windows to pop up during R CMD check, which is
against CRAN policy. @wch will merge a PR that has other examples
once we release v1.2.
2018-11-01 14:56:15 -07:00
Joe Cheng
d72e8a06a7 Fix error in global reactiveTimer
When reactiveTimer is created without a default reactive domain
(i.e. outside of a session, i.e. global) there's no session to
call cycleStartAction on. Instead, invalidation should proceed
right away.

Fixes #2228
2018-10-29 11:43:03 -05:00
Joe Cheng
cf79fec720 Merge pull request #2226 from rstudio/joe/bugfix/cycle-queue-stall-2
Fix input event queue stall
2018-10-25 15:19:23 -07:00
Joe Cheng
31dda45d1c Update NEWS 2018-10-25 12:13:37 -07:00
Joe Cheng
9836b72661 Fix #2225: Input event queue can stall in apps that use async 2018-10-25 12:12:21 -07:00
Winston Chang
6ede0194c6 Update license information in README 2018-10-25 12:15:57 -05:00
Winston Chang
5ec38581ca Add support for Font-Awesome 5 brands (#2221)
* Add support for Font-Awesome 5 brands

* Fix glyphicon support
2018-10-24 16:13:36 -05:00
Winston Chang
2629e59ace Re-document 2018-10-18 22:52:43 -05:00
Alan Dipert
f3eb770e20 Add to fontawesome news entry (#2214)
* Add FontAwesome upgrade information to NEWS.md

* Update NEWS.md

* Update NEWS.md
2018-10-18 11:57:29 -05:00
Winston Chang
0683b79fac Fix datepicker DST bug (#2212)
* Fix datepicker DST bug. Closes #2204

This fix is borrowed from:
13885397de (diff-dd513a8bab7ad1033c8784c4a1b9ce15)

* Update NEWS.md
2018-10-17 15:01:39 -05:00
Alan Dipert
fcd09e2bae Simplify DnD for fileInputs, fix #2142 (Firefox 57+)
- Simplified dragHover "plugin" by counting children instead of storing them.
  Counting children fixes Firefox 57+ bug (to be found or filed) that causes
  text object of input element to produce drag events
- Removed multimethod since it's no longer used anywhere
- Firefox 57+ appears not to trigger a change event when the `files` field is modified,
  which prevented uploads from occuring. This commit triggers a change event manually
  and doesn't impact the functioning of other browsers.
2018-10-08 21:24:18 -07:00
Joe Cheng
b25cb0f2d5 Merge pull request #2200 from rstudio/joe/bugfix/brush-webkit
Fix brushes not being properly cleared
2018-09-27 14:23:27 -07:00
Barret Schloerke
0704aec01b Follow js event namespacing conventions and only possibly init brush once (#2202)
* underscore the shiny_image_interaction namespace

* namespace dragstart

* use `one` instead of `on`

* compile
2018-09-27 16:24:53 -04:00
Barret Schloerke
d38b939c63 use naturalHeight and naturalWidth for default dim values. Followup comments from winston (#2201) 2018-09-27 16:16:11 -04:00
Joe Cheng
112466de1e Fix brushes not being properly cleared
Actually three separate issues addressed. Fixes #2197.

- brush.importOldBrush() was not being called anymore, due to it being
  registered as a load handler after the image was already loaded (this
  was a very recent regression, less than 24 hours old).
- Each time the brush changes, the plot is redrawn twice. This was
  because importing the old brush introduced floating point errors that
  led to a slightly different new brush being created.
- Sometimes the image's load event wasn't firing at all. This is due to
  behavior in WebKit where assigning an image's src to its existing
  value is a no-op.
2018-09-26 22:57:16 -07:00
Barret Schloerke
1d0edd2ad0 Initialize brush dims for renderImage objects (#2198)
* wait for image to be loaded in browser before initializing handlers

reverts similar behavior in 3354a47e8a

* default the height and width to the image clientHeight and clientWidth

* use raw image clientWidth and clientHeight instead of container clientWidth and clientHeight

prevents being able to brush on non image areas
2018-09-26 13:29:42 -04:00
Joe Cheng
37736119be Merge pull request #2195 from rstudio/joe/bugfix/selectize-choices-data-frame
Fix custom selectize rendering
2018-09-25 14:23:29 -07:00
Joe Cheng
c5df150acb Improve robustness of optgroup construction
Instead of providing alternate defaults for optgroupField,
optgroupLabelField, and optgroupValueField, respect the
selectize instance's settings for those fields.
2018-09-25 14:13:39 -07:00
Joe Cheng
49a346334b Fix custom selectize rendering
Fixes #2192. Two problems here:

1. It's not documented but apparently we supported data frames for
   choices in updateSelectInput/updateSelectizeInput (it doesn't
   appear to work correctly for selectInput/selectizeInput though).
   This was used in 023-optgroup-server as well as by the user who
   reported #2172.
2. The example in 023-optgroup-server was also counting on the
   default value of optgroupLabelField, which (starting post-Shiny
   v1.1) was being set to a new default of "group". That now won't
   happen unless optgroupField is also blank. I'm less confident
   about the ramifications of this change. The selectize docs with
   the relevant bits are here:
  https://github.com/selectize/selectize.js/blob/master/docs/usage.md#data_searching
2018-09-25 13:23:35 -07:00
Joe Cheng
e7c4656e8f Fix selectize bug where value is set merely on query results (#2193)
This bug is new since v1.1. When results are returned from selectize's
server-side endpoint, iff no results have been selected before, then
the control should be set to either its specified initial value (the
one specified in selectInput/selectizeInput) or, if none was provided
AND the selectize control is multiple=FALSE, then select the first
entry automatically.

That's the desired behavior; the bug was that last part, "select the
first entry automatically", was happening whether results had already
been selected before or not. This was causing merely typing in the
control to cause the value to be changed.

Fixes #2191
2018-09-25 12:21:16 -07:00
Joe Cheng
85bed0582a Rebuild JS (to update version number) 2018-09-19 09:51:36 -07:00
Joe Cheng
b9e6f867c6 Bump version 2018-09-19 09:47:41 -07:00
Joe Cheng
a5b80168bd Refactor v1.2 news 2018-09-19 09:47:35 -07:00
Alan Dipert
3cea5fb2d0 Upgrade FontAwesome to 5.3.1 (#2186)
* Upgrade FontAwesome to 5.3.1

- Upgrades FontAwesome to a new major (breaking) version, but
  is backwards compatible because we include the v4-shims CSS that maps
  old names to new.
- This is a step toward full V5 adoption that doesn't require us to
  come up with a plan for deprecating V4 icon names.
- Details: https://fontawesome.com/how-to-use/on-the-web/setup/upgrading-from-version-4
- Related to #2156 and #1966

* Improvements to icon

- Clarify in docs that fontawesome V5 icons accessible with V4-style names
- Make icons browseable: icon('address-book') will now open the Viewer
  pane of RStudio IDE so that icons can be experimented with more easily.

* Update LICENSE with CC for FontAwesome .svgs

* Update NEWS
2018-09-18 13:30:14 -07:00
Joe Cheng
c89d782048 Merge pull request #2187 from rstudio/joe/bugfix/selectize-nonempty
Fix spurious duplicate values being sent by selectInput
2018-09-18 13:27:55 -07:00
Barret Schloerke
1fd4179e07 News item for #2180 (#2189)
* news item for #2180

* fix news item
2018-09-18 14:58:57 -04:00
Joe Cheng
3b62400298 Code review feedback--use an arrow function instead of aliasing this 2018-09-18 10:52:50 -07:00
Joe Cheng
ba0fe938a1 Merge pull request #2188 from rstudio/jcheng5-patch-1
Remove unneeded Remotes
2018-09-18 10:33:47 -07:00
Joe Cheng
d4560171a8 Remove unneeded Remotes 2018-09-18 09:59:40 -07:00
Barret Schloerke
9963ba6cf5 merge master 2018-09-18 12:26:57 -04:00
Barret Schloerke
f5a23826c8 add domain to reactlog for context exit (#2180)
* add domain to reactlog for context exit

* use if statement vs %OR% when using envs

* Simplify graphExitContext domain argument
2018-09-18 12:23:01 -04:00
Barret Schloerke
21ff005c1a remove display param from MessageLogger 2018-09-18 10:59:31 -04:00
Barret Schloerke
206b9135f1 if reactlog console option is set, display, or display is display is true 2018-09-18 10:24:48 -04:00
Barret Schloerke
5449de1a67 use shinyreactlog pkg directly 2018-09-18 10:24:17 -04:00
Barret Schloerke
47c61756e6 log create context with srcref and srcfile 2018-09-18 10:24:01 -04:00
Joe Cheng
ef63679ff0 Update NEWS 2018-09-17 16:13:32 -07:00
Joe Cheng
ef7e1c385a Fix spurious duplicate values being sent by selectInput 2018-09-17 16:12:15 -07:00
Barret Schloerke
3a0a6cdbbb Add css and image locations to plot click and brush events (#2183) 2018-09-17 15:25:34 -04:00
Joe Cheng
340df3e956 Merge pull request #2174 from AliciaSchep/master
Add informative errors when xvar or yvar not in data for brushedPoints
2018-09-17 11:33:16 -07:00
AliciaSchep
eeb264da8e add var name to error msg 2018-09-17 09:45:40 -07:00
AliciaSchep
00f08b8ec6 revert two previous commits 2018-09-17 09:41:04 -07:00
AliciaSchep
67ae2a39ba update documentation to reflect new options for xvar and yvar 2018-09-16 23:07:08 -07:00
AliciaSchep
72dda25835 evaluate xvar and yvar for nearPoints and brushedPoints 2018-09-16 22:45:53 -07:00
Alan Dipert
8c9ce1994a Merge pull request #2028 from rstudio/joe/misc/selectize-upgrade
Upgrade Selectize to 0.12.4
2018-09-14 14:42:28 -07:00
Alan Dipert
606b05fdaf Merge remote-tracking branch 'origin' into joe/misc/selectize-upgrade 2018-09-14 14:40:54 -07:00
Alan Dipert
420ba9549f Merge pull request #2047 from rstudio/joe/bugfix/post-message
Fix #2033: Rstudio Viewer window not closed on shiny::stopApp()
2018-09-14 14:26:58 -07:00
Alan Dipert
51fbb5cfac Update NEWS 2018-09-14 14:25:43 -07:00
Alan Dipert
ca2c2b60f2 Grunt 2018-09-14 14:25:09 -07:00
Alan Dipert
d6064636d4 Merge pull request #2182 from rstudio/joe/misc/fontawesome-4-note
Add note that Font Awesome support is for 4.7.0
2018-09-14 13:52:30 -07:00
Joe Cheng
9646c9b0a0 Add note that Font Awesome support is for 4.7.0 2018-09-12 08:57:53 -07:00
Barret Schloerke
f28900f8ca merged master 2018-09-10 12:50:42 -04:00
Barret Schloerke
e0c15c42d7 do not depend on null reactid values 2018-09-05 10:40:45 -04:00
AliciaSchep
7177618c25 add informative errors when xvar or yvar not in data for nearPoints and brushedPoints 2018-09-04 20:51:51 -07:00
Winston Chang
3bdd4af75c Merge pull request #2168 from rstudio/create-scope-dir
Check for existence of bookmark scope directory before creating
2018-08-24 13:43:15 -05:00
Winston Chang
98d4b5e487 Check for existence of bookmark scope directory before creating 2018-08-24 12:43:45 -05:00
Joe Cheng
8b5639bfdb Tweaks to NEWS 2018-08-24 10:41:08 -07:00
Joe Cheng
1c70b8b1bf Merge pull request #2147 from nathancday/master
Fixes #174, allowing specific days of the week to be disabled.
2018-08-24 10:39:12 -07:00
Joe Cheng
b5a7e03879 Merge branch 'master' into master 2018-08-24 10:38:44 -07:00
Winston Chang
a6dade846e Un-export knit_print methods from htmltools 2018-08-23 15:51:53 -05:00
Winston Chang
32913f9d95 Merge pull request #2160 from rstudio/digest-xxhash
Use xxhash64 instead of sha256 for hash algorithm
2018-08-17 11:59:47 -05:00
Winston Chang
cbabf9a2a3 Use xxhash64 instead of sha256 for hash algorithm 2018-08-16 15:54:54 -05:00
Winston Chang
03e92c3336 Update NEWS 2018-08-10 21:18:05 -05:00
Winston Chang
997c39fdc0 Merge pull request #2125 from rstudio/plot-interact-scaled
Fix plot interaction for scaled plots
2018-08-10 21:13:16 -05:00
Winston Chang
bba2d1ee18 Grunt 2018-08-10 19:42:11 -05:00
Winston Chang
a60301810f Update coordmap tests 2018-08-10 19:42:11 -05:00
Winston Chang
6b261f76b1 Bump version and update NEWS 2018-08-07 15:25:31 -05:00
Winston Chang
3db5f21d90 Update data structure comment 2018-08-07 15:11:43 -05:00
Winston Chang
121bfcb984 Import old brush after image has loaded 2018-08-07 15:11:43 -05:00
Winston Chang
265de66946 Make sure not to have multiple reset event handlers 2018-08-07 14:51:23 -05:00
Winston Chang
79c5c9f95e Add isnan() function for IE 2018-08-07 14:51:23 -05:00
Winston Chang
3354a47e8a Add width/height to coordmap instead of using naturalWidth/Height
This eliminates the need to use an on load callback.
2018-08-07 14:51:23 -05:00
Winston Chang
a1e1416d7a More consistent use of img to css conversion functions 2018-08-07 10:48:42 -05:00
Winston Chang
24b7a9907f renderCachedPlot: add note about interactive plots to help page 2018-08-07 10:48:42 -05:00
Nate
214abd0cd4 moved new dateInput arguments to last and added formatting conditional if datesdisabled is Date object 2018-08-07 10:16:48 -04:00
Joe Cheng
0bb53e8ca5 Inputs in renderUI/uiOutput don't work with bookmarks (#2139)
* hasCurrentRestoreContext returns FALSE from server side

Fixes #2138.

* Add NEWS item for renderUI bookmarking fix
2018-08-06 15:04:16 -07:00
Winston Chang
ec12caaeba Include x and y pixelratio in coordinfo 2018-08-06 12:51:08 -05:00
Winston Chang
5bbf2aa57a Use canonical CSS property name
Firefox doesn't support shorthand properties like "border-left", but instead
requires "border-left-width".
2018-08-06 12:51:08 -05:00
Winston Chang
84ad9997da Reposition div when resized (without new image) 2018-08-06 12:51:08 -05:00
Winston Chang
9f6ce87443 Remove redundant isEquivalent function 2018-08-06 12:51:08 -05:00
Winston Chang
1ff6c382bf Remove unnecessary ggplot2 workaround 2018-08-06 12:51:07 -05:00
Winston Chang
c366c10ae1 Initialize coordmap only after image loads 2018-08-06 12:51:07 -05:00
Winston Chang
950df1e25c Add support for scaled images and brushing 2018-08-06 12:51:07 -05:00
Winston Chang
909bfa8c14 Allow plot interaction to handle scaled images 2018-08-06 12:51:07 -05:00
Winston Chang
598b48d078 DiskCache: use mtime instead of atime, check for time resolution (#2146)
* DiskCache: check for atime support while running

* Use mtime instead of atime

* Remove mtime resolution checks
2018-08-06 10:50:05 -07:00
Nate
4c7b7f236a added datesdisabled parameter to dateInput() allows disabling of specific yyyy-mm-dd format strings 2018-08-04 19:04:40 -04:00
Nate
896c5b41cb Fixes #174, allowing specific days of the week to be disabled. 2018-08-04 15:47:13 -04:00
Winston Chang
205c35d5e5 Re-document with roxygen2 6.1.0 2018-08-03 17:50:47 -05:00
Winston Chang
bf0dd7d725 Merge pull request #1997 from rstudio/plot-cache
Add renderCachedPlot()
2018-08-03 13:30:13 -05:00
Winston Chang
ba2b811172 Fix argument name in documentation 2018-07-31 15:06:59 -05:00
Winston Chang
be347c3ed4 Don't cache plotResult 2018-07-31 12:07:21 -05:00
Joe Cheng
c01abdb6a9 Merge branch 'master' into plot-cache 2018-07-26 15:52:11 -07:00
Winston Chang
95a5a965a5 Documentation fixes 2018-07-20 16:12:21 -05:00
Winston Chang
fc2849a8ff Remove env and quoted arguments 2018-07-20 16:10:15 -05:00
Winston Chang
fcc900f3e0 Simplify resize logic 2018-07-20 14:48:57 -05:00
Winston Chang
9d0bcd5637 Add shiny-scalable class 2018-07-20 14:44:21 -05:00
Winston Chang
6ebbad5273 Safer file removal order 2018-07-19 23:20:51 -05:00
Winston Chang
930459899a Small logic cleanup 2018-07-19 23:20:40 -05:00
Winston Chang
fe730e2d76 Make session cache public, so that user can set it 2018-07-19 21:57:32 -05:00
Winston Chang
e58b2e9a47 Fix app- and session-level cache initialization 2018-07-19 21:57:07 -05:00
Winston Chang
719dbab0c2 DiskCache: make destroy_on_finalize default to FALSE 2018-07-19 14:35:59 -05:00
Winston Chang
86ea023e2e Update caches from code review feedback 2018-07-19 14:33:53 -05:00
Winston Chang
bc0fb3f44c Restructure drawReactive/renderFunc code 2018-07-18 14:52:39 -05:00
Winston Chang
6d37f6b4dd Set max-width and max-height to 100% for cached plots 2018-07-12 10:55:26 -05:00
Winston Chang
958ab85297 Add exec_missing parameter 2018-07-12 10:55:26 -05:00
Barret Schloerke
facef1d23c do not set shiny.reactlog option by default 2018-07-09 22:23:28 -04:00
Barret Schloerke
cdb446375c turn all active isLogging bindings into functions 2018-07-09 22:22:49 -04:00
Barret Schloerke
6f7b2887aa fix parameters for shinyreactlog (session_token) 2018-07-06 11:58:37 -04:00
Barret Schloerke
bc8ae063dd add new option for shinyreactlog messages in the console 2018-07-06 11:58:16 -04:00
Winston Chang
a23f973433 Suppress console logging for renderCachedPlot 2018-07-02 17:04:44 -05:00
Winston Chang
c124256bad Improved logging for DiskCache and MemoryCache 2018-07-02 17:04:28 -05:00
Winston Chang
f1b035bcca Update renderCachedPlot documentation and examples 2018-07-02 15:27:51 -05:00
Joe Cheng
81cc7c591e Merge pull request #2080 from schloerke/barret-freeze-thaw
freeze/thaw reactiveValues with namespace support
2018-06-29 15:58:52 -07:00
Winston Chang
a0ca560c3b Doc entries 2018-06-29 13:24:01 -05:00
Winston Chang
d1f20a9c73 Add 'missing' parameter to get() 2018-06-29 13:23:47 -05:00
Barret Schloerke
013059c5b9 merged in master 2018-06-29 11:35:20 -04:00
Winston Chang
fe6ad235ac Add sentinel value cache miss 2018-06-28 23:58:55 -05:00
Winston Chang
67af26ffe6 When MemoryCache is used, we can cache the displayList 2018-06-26 23:11:25 -05:00
Winston Chang
0fce9de04f Change default DiskCache size 2018-06-26 22:59:32 -05:00
Winston Chang
a8b8df21d6 DiskCache: make default finalizer behavior conditional on whether a temp directory is used 2018-06-26 22:57:35 -05:00
Winston Chang
ab2e304f02 DiskCache: Add info about sharing across processes 2018-06-26 22:56:59 -05:00
Winston Chang
574f2c53d4 DiskCache: Make destroy() work robustly with multiple processes 2018-06-26 22:26:27 -05:00
Winston Chang
bc85d812d2 DiskCache: Avoid errors from a race condition 2018-06-26 16:38:43 -05:00
Winston Chang
364990a29f Fix .rds directory search pattern 2018-06-26 16:37:58 -05:00
Winston Chang
9ac9e36873 DiskCache: Check if cache has been destroyed by someone else 2018-06-26 15:48:08 -05:00
Winston Chang
6745e09688 Add support for promisey cache key 2018-06-25 21:13:55 -05:00
Winston Chang
e758927c84 DiskCache: Add warning when caching reference objects 2018-06-25 15:53:47 -05:00
Winston Chang
90fbf7d50f Add comment about pruning 2018-06-25 15:34:43 -05:00
Winston Chang
75f1ee0082 Prune after setting value 2018-06-25 15:30:30 -05:00
Winston Chang
750aaf451a NEWS edits 2018-06-25 14:11:42 -05:00
Winston Chang
b44bfe9109 Grunt 2018-06-25 14:10:22 -05:00
Winston Chang
aa392f8563 Merge pull request #2102 from tmastny/selectize-remote
Resolves #1933: Serve-side selectize extended to all inputs
2018-06-25 14:07:56 -05:00
Winston Chang
ac7228f6c4 Merge branch 'master' into selectize-remote 2018-06-25 14:07:20 -05:00
Winston Chang
dcb12addaa Merge pull request #2108 from tmastny/par-oma
Resolves #1935: Fix coordinate outputs when modifying outer margins
2018-06-25 14:05:39 -05:00
Winston Chang
ad398b5f8a Merge branch 'master' into par-oma 2018-06-25 14:05:30 -05:00
Timothy Mastny
803cb4806e add new item 2018-06-25 14:04:31 -05:00
Timothy Mastny
1a468bbb61 add news items 2018-06-25 14:02:18 -05:00
Winston Chang
c332c051f3 Merge pull request #2099 from tmastny/slider-type
Fix #2019: `updateSliderInput` changes formatting
2018-06-25 14:00:18 -05:00
Timothy Mastny
db48befcb7 removed TODO comments 2018-06-25 13:51:24 -05:00
Winston Chang
b02edb05ac DiskCache: Use temp file when setting value 2018-06-25 11:56:01 -05:00
Winston Chang
d7009fd1c8 DiskCache: Don't call exists() before reading file 2018-06-25 11:55:29 -05:00
Winston Chang
ce3755676c Fix files that were split 2018-06-25 10:45:12 -05:00
Winston Chang
db3c1b728d Merge branches 'plot-cache-split-1' and 'plot-cache-split-2' into plot-cache 2018-06-25 10:42:52 -05:00
Winston Chang
1761de4740 Rename cache.R cache-context.R 2018-06-25 10:42:49 -05:00
Winston Chang
09d496925b Rename cache.R cache-memory.R 2018-06-25 10:41:49 -05:00
Winston Chang
3af5327f1c Rename cache.R cache-disk.R 2018-06-25 10:41:04 -05:00
Winston Chang
06cb14d7ec Rename $has method to $exists 2018-06-22 23:27:49 -05:00
Winston Chang
7be1a9d7fa Add memoryCache and make it the default 2018-06-22 23:08:39 -05:00
Winston Chang
95243fb35c DiskCache: Add LRU eviction policy 2018-06-22 22:44:27 -05:00
Winston Chang
26438a3979 DiskCache cleanup 2018-06-22 19:32:29 -05:00
Winston Chang
28db097a71 Use promise domain for currentOutputName 2018-06-22 19:31:20 -05:00
Winston Chang
76fdd8ae04 Make renderCachedPlot work with async 2018-06-22 16:47:55 -05:00
Barret Schloerke
003dc39d76 add shinyreactlog as remote 2018-06-22 10:49:57 -04:00
Timothy Mastny
3a73bfb142 changed output coordinate system to "ndc" to account for margin changes 2018-06-21 17:48:16 -05:00
Timothy Mastny
a24bdabf08 Updates to Winston's feedback: removed for ... of iteration that is not supported in IE. 2018-06-21 16:17:42 -05:00
Winston Chang
8815f293a2 Update R version check information 2018-06-21 15:55:35 -05:00
Barret Schloerke
0b04c28011 move renderReactLog calculation above addResourcePath 2018-06-21 16:54:23 -04:00
Winston Chang
9af2775539 Fix absolutePath to correctly handle absolute paths 2018-06-21 15:48:54 -05:00
Winston Chang
ae5deae6e9 Use output name in cache key 2018-06-21 14:55:30 -05:00
Winston Chang
61c2126498 Add diskCache function, and app- and session-level caches 2018-06-21 14:44:09 -05:00
Timothy Mastny
881fe0cfce explicitly set number to null instead of implicitly for better documentation 2018-06-21 14:30:15 -05:00
Timothy Mastny
a999bf389c update NEWS.md 2018-06-21 14:30:15 -05:00
Timothy Mastny
ff3b97b630 refactored data type checking for consistency 2018-06-21 14:30:15 -05:00
Timothy Mastny
639b520d39 updateInputSlider can now change from date to date-time formatting. fixes #2019 2018-06-21 14:30:15 -05:00
Barret Schloerke
31854ad9e8 add reactlog resource path when calling for reactlog 2018-06-21 15:24:17 -04:00
Barret Schloerke
4304e92f0d use self$ for all fn calls within rLog to avoid any conflicts 2018-06-21 15:23:33 -04:00
Barret Schloerke
44736cefbf allow for null context id in dependents 2018-06-21 15:22:46 -04:00
Barret Schloerke
a807449f28 remove old temp files 2018-06-21 15:22:16 -04:00
Timothy Mastny
19dc29ea17 changes as per Winston's feedback; additional comments, and edge cases, and removed unnecessary JS. 2018-06-21 12:47:14 -05:00
Barret Schloerke
ae9d38b59c remove old .graph methods and use shinyreactlog pkg for rendering 2018-06-21 10:31:12 -04:00
Timothy Mastny
97bebae8d7 fixed default selection for multiple-select 2018-06-20 15:41:35 -05:00
Timothy Mastny
cf534ce6da remove "thiz"s and replace with explicit "selectize" 2018-06-20 15:41:35 -05:00
Timothy Mastny
f25f691a55 fix selectize for default selected value NULL 2018-06-20 15:41:35 -05:00
Timothy Mastny
cbebf8be7b improve performance of R input processing 2018-06-20 15:41:35 -05:00
Timothy Mastny
165ce26b2f Fixes #1933. Fixed JSON encoding of input data, and added more optgroup controls on JS-side 2018-06-20 15:41:35 -05:00
Barret Schloerke
05e50c1b98 use original yarn lock file 2018-06-20 15:54:07 -04:00
Barret Schloerke
e11004da7b remove _ignore folder 2018-06-20 15:51:17 -04:00
Barret Schloerke
97ee7b5d96 clean up tools readme to use yarn over global grunt-cli install 2018-06-20 15:47:16 -04:00
Barret Schloerke
6c6e2573aa remove a LOT of files in favor of github.com/schloerke/shinyreactlog
still need hooks to shinyreactlog pkg
2018-06-20 15:34:22 -04:00
Barret Schloerke
8992827f21 merged master 2018-06-20 14:11:22 -04:00
Winston Chang
572c863bff Merge pull request #2106 from schloerke/js_patch
compile with grunt to get version in js code (v1.1.0.9000)
2018-06-20 12:47:43 -05:00
Barret Schloerke
d3c85d67b8 gruntfile should run 'default' task to make sure everything is built like normal 2018-06-20 13:31:10 -04:00
Barret Schloerke
ff3434f77e add a R test to make sure shiny.js {{ VERSION }} was replaced 2018-06-20 12:53:07 -04:00
Barret Schloerke
762528c044 add a grunt test to make sure {{ VERSION }} was replaced 2018-06-20 12:52:46 -04:00
Barret Schloerke
1891af0d4a compile with grunt 2018-06-20 11:39:12 -04:00
Winston Chang
583ad036f7 Streamline renderCachedPlot API 2018-06-19 16:00:49 -05:00
Barret Schloerke
893b9c1b38 merged master -> barret/reactlog 2018-06-19 09:24:39 -04:00
Winston Chang
ac92bf98d4 WIP 2018-06-18 16:25:36 -05:00
Winston Chang
fd90ff7ff7 Use DiskCache class 2018-06-18 16:25:36 -05:00
Winston Chang
d06dbbe5db Change cacheResetEventExpr to cacheResetExpr 2018-06-18 16:25:36 -05:00
Winston Chang
bffc4995d7 Rename normalizePath2 to absolutePath 2018-06-18 16:25:36 -05:00
Winston Chang
4b8b406bed Add sizeGrowthRatio function 2018-06-18 16:25:36 -05:00
Winston Chang
5641153272 renderCachedPlot: pass ... args 2018-06-18 16:25:36 -05:00
Winston Chang
08c6c7781f Rename cacheClearExpr to cacheResetEventExpr 2018-06-18 16:25:36 -05:00
Winston Chang
ad2ad391a7 Isolate user code 2018-06-18 16:25:36 -05:00
Winston Chang
caac88be0d Don't re-run user code when only dimensions change 2018-06-18 16:25:36 -05:00
Winston Chang
10660aa373 Rename cacheInvalidationExpr to cacheClearExpr 2018-06-18 16:25:36 -05:00
Winston Chang
cfaf97aee4 Add entries to staticdocs 2018-06-18 16:25:36 -05:00
Winston Chang
55f14576f0 Remove createCachedPlot function 2018-06-18 16:25:36 -05:00
Winston Chang
4dca94ac99 Code reorganization 2018-06-18 16:25:36 -05:00
Winston Chang
14779d3d27 Only invalidate plot when fitted dimensions change 2018-06-18 16:25:36 -05:00
Winston Chang
66d1e710b5 Allow renderCachedPlot to take a directory for scope 2018-06-18 16:25:36 -05:00
Winston Chang
12ae3c17e9 Allow onStop to take a NULL session 2018-06-18 16:25:35 -05:00
Winston Chang
36e4da0709 Add app/session scoping for renderCachedPlot 2018-06-18 16:25:35 -05:00
Winston Chang
91631cb081 Note bug fix in R 2018-06-18 16:25:35 -05:00
Winston Chang
224f082e1f Implement cache invalidation 2018-06-18 16:25:35 -05:00
Winston Chang
76b239a6ea Convert renderCachedPlot to take expr and cacheKeyExpr 2018-06-18 16:25:35 -05:00
Winston Chang
cb476b510d Initial implementation of renderCachedPlot 2018-06-18 16:25:35 -05:00
Winston Chang
334f233968 Move plot caching code into separate file 2018-06-18 16:25:35 -05:00
Winston Chang
e1f21250b9 Rename plotCache to createCachedPlot 2018-06-18 16:25:35 -05:00
Winston Chang
8d087e4f20 Get output info and auto-size plot cache images 2018-06-18 16:25:35 -05:00
Winston Chang
9e35e8c947 Allow user code to pass width/height/pixelratio 2018-06-18 16:25:35 -05:00
Winston Chang
f98faef024 Document cache scoping and minor code cleanup 2018-06-18 16:25:35 -05:00
Winston Chang
0f9346ead5 Add different scoping levels for plotCache 2018-06-18 16:25:35 -05:00
Winston Chang
fc8118c694 First implementation of plotCache 2018-06-18 16:25:35 -05:00
Barret Schloerke
6f8166ca0f add todo 2018-06-14 16:06:12 -05:00
Joe Cheng
026b7278c1 Merge pull request #2091 from schloerke/barret-varSelectInput
Variable Select Input
2018-06-14 09:39:09 -05:00
Barret Schloerke
375a7e7e5c respect existing class values and add tests 2018-06-11 10:31:49 -05:00
Barret Schloerke
64db035d77 simplify colors
no active green or grey. input invalidate should be grey
2018-06-08 15:38:03 -04:00
Barret Schloerke
cb051e4254 less case "STRING" and more case OBJ.VALUE 2018-06-08 15:20:51 -04:00
Barret Schloerke
20e9c2901d reduced hoverStatusOnNodeIds arg requirements and internals 2018-06-08 15:17:33 -04:00
Barret Schloerke
ce4b391495 add more flow classes and remove $FlowExpectError 2018-06-08 15:16:43 -04:00
Barret Schloerke
7d932f5b18 fix searching on nodes 2018-06-08 11:43:37 -04:00
Barret Schloerke
56c8c08e08 move mapValues to a util file 2018-06-08 11:42:37 -04:00
Barret Schloerke
13ef25c0b5 bump flow threshold to 95 percent 2018-06-08 11:41:10 -04:00
Barret Schloerke
7a1aecb1a4 varSelectInput doc tweaks 2018-06-08 10:59:45 -04:00
Barret Schloerke
b3690e8680 add bullets in details for output return value (update corresponding example) 2018-06-08 10:51:37 -04:00
Barret Schloerke
97d490cfb4 remove rogue staticdocs fn 2018-06-07 16:52:35 -04:00
Barret Schloerke
2081dda6fc merged master -> varSelectInput 2018-06-07 16:46:31 -04:00
Barret Schloerke
ea912fc50c staticdocs for varSelectInput 2018-06-07 16:43:20 -04:00
Barret Schloerke
b655fdf68f added news for varSelectInput 2018-06-07 16:43:05 -04:00
Barret Schloerke
4749f46a4f add shiny.symbol and shiny.symbolList tests 2018-06-07 16:10:47 -04:00
Barret Schloerke
f95bb9c82d compile and document 2018-06-07 16:10:24 -04:00
Barret Schloerke
6529529cdb add new input 'varSelectInput()' and input binding 'shiny.symbol' and 'shiny.symbolList' 2018-06-07 16:10:01 -04:00
Tim Mastny
3a2a3f21d4 Improve optgroup documentation per #1864 (#2084)
* improves optgroup documentation per #1864

* change PR number in NEWS.md

* change addresses to addressed
2018-06-07 12:09:45 -05:00
Tim Mastny
631bc1c481 Addresses #2042: lighten dates outside of range for datepicker (#2087)
* dehighlight dates outside of range for datepicker

* override color in shiny.css instead of package css

* refactored css styling to use specific references instead of !important
2018-06-07 11:57:27 -05:00
Barret Schloerke
6abfa5bf80 default log with marks 2018-06-06 16:14:54 -04:00
Barret Schloerke
20ae8e4f8b fix eslint and prettier clashes 2018-06-06 16:14:51 -04:00
Barret Schloerke
f595c5d504 first pass at a user time mark 2018-06-06 16:14:47 -04:00
Barret Schloerke
972779253c update enter exit to not be off by one 2018-06-06 16:14:42 -04:00
Barret Schloerke
9179a241e9 first pass at reactlog mark 2018-06-06 16:14:31 -04:00
Barret Schloerke
85e7e89ad9 fix babel options bug in grunt config 2018-06-06 16:14:26 -04:00
Barret Schloerke
9f5bc00c89 add simpler lint then watch script 2018-05-31 14:00:55 -04:00
Barret Schloerke
0ab842e3c5 add cranwhales log 2018-05-31 14:00:32 -04:00
Barret Schloerke
3a0a3e49dc use log states from dictionary, rather than copies 2018-05-31 13:58:45 -04:00
Barret Schloerke
438b1c043e set app data as log 2018-05-31 13:57:56 -04:00
Barret Schloerke
6d13b65e7c export rlog object not as default 2018-05-31 13:57:27 -04:00
Barret Schloerke
423d41ee0e fix console bug 2018-05-31 13:55:59 -04:00
Barret Schloerke
1b61d9bc51 first pass at freeze/thaw in rlog 2018-05-31 13:55:32 -04:00
Barret Schloerke
bf0c3d42db copy all rlog files to the temp directory 2018-05-31 13:53:58 -04:00
Barret Schloerke
5394a68314 attempt to load rlog_data as a trycatch to work with showReactLog() 2018-05-31 13:53:46 -04:00
Barret Schloerke
597af36759 added news item 2018-05-31 10:31:35 -04:00
Barret Schloerke
691062f687 white space 2018-05-31 10:30:19 -04:00
Barret Schloerke
6651c4ea48 when freezing a reactivevalues key, use the name space similar to $.reactivevalues 2018-05-31 10:23:30 -04:00
Barret Schloerke
116559e5a0 use utils namespace 2018-05-31 10:21:55 -04:00
Barret Schloerke
7818e8ed64 white space 2018-05-31 10:21:42 -04:00
Barret Schloerke
b0063399bb fix freeze/thaw rlog'ing 2018-05-30 14:14:57 -04:00
Barret Schloerke
724c6b7656 Merge branch 'master' into barret/reactlog
* master:
  runApp: add support for IPv6 addresses
  Bump version to *.9000. Back to work!
  Bump version to 1.1.0
  Bump httpuv version and add NEWS note
  Fix #2061: Tests failing on Windows due to rounding errors
  Take dependency on later >=0.7.2
2018-05-29 18:26:24 -04:00
Barret Schloerke
0530cbcd0f make sure log works with an empty log 2018-05-29 18:22:26 -04:00
Barret Schloerke
6e2bba1513 up the flow type percentage 2018-05-29 18:16:40 -04:00
Barret Schloerke
89ac5d7c42 ignore yarn error 2018-05-29 18:16:08 -04:00
Barret Schloerke
dd68722b66 first pass at cyto flow types 2018-05-29 12:01:36 -04:00
Barret Schloerke
933d5db2ab flow more files 2018-05-29 09:59:19 -04:00
Barret Schloerke
0386ed6409 add index file for updateGraph to gather all exports for easy import 2018-05-29 09:34:06 -04:00
Barret Schloerke
d3c14bf416 first pass at flowtype 2018-05-29 09:33:02 -04:00
Barret Schloerke
2a224ce9fb add babel plugin transform class properties within yarn 2018-05-29 09:32:53 -04:00
Barret Schloerke
78322525b7 add flow, flow scripts and update grunt-babel 2018-05-29 09:25:39 -04:00
Barret Schloerke
5b7c9c205e remove rlog grunt tasks in favor of config files 2018-05-29 09:24:44 -04:00
Barret Schloerke
07ac70a460 add lodash flow types 2018-05-29 09:23:30 -04:00
Barret Schloerke
3629f806a2 add jquery flow types 2018-05-29 09:23:21 -04:00
Barret Schloerke
72fc43c738 add a flow config
only for rlog src
make all lints warnings
any suppress comment starts with "\\ $Flow"
and if strict (currently none) do recommended strict things
2018-05-29 09:23:06 -04:00
Winston Chang
2880391620 runApp: add support for IPv6 addresses 2018-05-25 16:19:51 -04:00
Barret Schloerke
df38f0be3f clean up lint config 2018-05-23 17:02:26 -04:00
Barret Schloerke
808684c2a8 remove unused dep and script 2018-05-23 17:00:57 -04:00
Barret Schloerke
69ed3a7751 working graph with es6 modules 2018-05-23 16:40:24 -04:00
Barret Schloerke
68556caa9a first pass at distributed files. graph loads, not all perfect 2018-05-23 12:02:59 -04:00
Barret Schloerke
bb8ea8053b prettier and build script updates 2018-05-22 11:44:49 -04:00
Barret Schloerke
6f01e6edf1 first pass at sep classes 2018-05-22 10:38:10 -04:00
Barret Schloerke
66a74d16ff lints 2018-05-22 10:01:07 -04:00
Barret Schloerke
0e525f5aeb add Console module 2018-05-22 09:59:52 -04:00
Joe Cheng
f742605a1b Bump version to *.9000. Back to work! 2018-05-17 17:20:17 -07:00
Barret Schloerke
86007c466d copy in react_graph into index.js to start pruning into multiple files 2018-05-17 16:56:21 -04:00
Barret Schloerke
7b39b79183 added prettier config for rlog 2018-05-17 16:42:02 -04:00
Barret Schloerke
7f453aa6f6 add local rlog .eslintrc.js 2018-05-17 16:38:59 -04:00
Barret Schloerke
f36052ffeb add test files 2018-05-17 16:38:34 -04:00
Barret Schloerke
d35db11f43 add gitignore in rlog 2018-05-17 16:19:20 -04:00
Barret Schloerke
173e5d3f97 prettier and lints 2018-05-17 16:18:05 -04:00
Barret Schloerke
bcebf737c3 move node_modules and grunt file to root dir 2018-05-17 16:13:13 -04:00
Winston Chang
2afff67e89 Bump version to 1.1.0 2018-05-16 15:18:59 -07:00
Winston Chang
fe7bd53250 Bump httpuv version and add NEWS note 2018-05-16 15:18:59 -07:00
Joe Cheng
6df3509869 Merge pull request #2062 from rstudio/joe/bugfix/windows-rounding
Fix #2061: Tests failing on Windows due to rounding errors
2018-05-16 15:17:04 -07:00
Joe Cheng
062dc771aa Fix #2061: Tests failing on Windows due to rounding errors 2018-05-16 14:44:34 -07:00
Barret Schloerke
5280b72b85 add different log files for rlog to check 2018-05-15 12:21:29 -04:00
Barret Schloerke
a4dfe7138e search regex implemented to update filtered data on getGraph.atStep(k) 2018-05-14 16:01:04 -04:00
Barret Schloerke
b9960bad1a next, prev, next cycle, prev cycle implemented within new search 2018-05-14 15:34:35 -04:00
Barret Schloerke
e1d7805396 massive sweep on how filtering and hovering is done. Commiting. regex filter is unfinished 2018-05-11 14:59:50 -04:00
Barret Schloerke
ce6f993f0e add filter by name 2018-05-10 10:54:14 -04:00
Barret Schloerke
aa1d94e6c9 first pass double click filter 2018-05-09 10:42:45 -04:00
Barret Schloerke
00a6092836 remove TODO 2018-05-09 10:41:45 -04:00
Barret Schloerke
f6372faa23 for future... make animation a setting 2018-05-04 11:10:01 -04:00
Barret Schloerke
1a5e266d26 Drastically improve performance by not re-rendering the layout on a layout that isn't changing 2018-05-04 11:02:33 -04:00
Barret Schloerke
2e4a107201 fix hover and sticky hover to be stable throughout transitions
all items use `hoverKey`. edges are supplying their ghostKey so that all edges share the same hoverKey.  if A --> B then all edges from A to B will behave the same way.
2018-05-04 11:01:31 -04:00
Joe Cheng
d4688db31c Update NEWS 2018-05-03 14:08:52 -07:00
Joe Cheng
c49a289619 Fix #2033: Rstudio Viewer window not closed on shiny::stopApp() 2018-05-03 14:06:34 -07:00
Barret Schloerke
2559496ded first pass at hover highlight. need to move to graph data object and not cyto object 2018-05-03 13:27:20 -04:00
Barret Schloerke
d3aa82fc5d clean up graph addEntry wrapper 2018-05-03 13:26:53 -04:00
Barret Schloerke
704605918d update layout options 2018-05-03 13:26:35 -04:00
Barret Schloerke
7e8116888b add alt shift arrows navigation and prev / next step calculations 2018-05-03 13:25:25 -04:00
Barret Schloerke
e0f4bbd20d skip adding entries if the reactId is rNoCtx 2018-05-02 15:12:21 -04:00
Barret Schloerke
5ae2d5a24b Allow for isolate calls to have no context and input name changes to have no context 2018-05-02 15:11:58 -04:00
Barret Schloerke
8648737a7a fix missing period bug 2018-05-02 15:11:19 -04:00
Barret Schloerke
6e090d5112 active enter and value change now pulse and use ActiveStateStatus helper 2018-05-02 11:25:08 -04:00
Barret Schloerke
2207e561f2 fix progress bar tick leaking right bug 2018-05-02 11:24:33 -04:00
Barret Schloerke
b9cd5b572b first pass at ActiveStateStatus class with invalidate 2018-05-02 11:04:30 -04:00
Barret Schloerke
344c6f3ee7 use graph style and do not animate graph style 2018-05-02 11:03:52 -04:00
Barret Schloerke
f6f2c0ed56 first pass at cacheing graphs. wait for now 2018-05-02 11:01:01 -04:00
Barret Schloerke
ec7a66a966 make edges shades of grey 2018-05-02 11:00:34 -04:00
Barret Schloerke
23ca428a01 add cycle markers in the timeline 2018-05-02 10:58:47 -04:00
Barret Schloerke
eb9f251e34 add nav buttons 2018-05-02 10:58:15 -04:00
Joe Cheng
9c3a0c86ca Take dependency on later >=0.7.2 2018-05-01 20:37:25 -05:00
Barret Schloerke
394d875eb4 valuechange addressed when an isolateInvalidateEnd is called
invalidate end also sets color to a 'done' grey
2018-05-01 14:12:02 -04:00
Barret Schloerke
4cc6403867 do not double log observable set invalidation 2018-05-01 14:09:09 -04:00
Barret Schloerke
9d5fa773f3 add classes and colors for different states of a graph
* reactive key value change until invalidate end has finished
* latest enter is darker green than others
* mousedown added to timeline click
* mousedown and mouse movement added to timeline
2018-05-01 10:08:37 -04:00
Barret Schloerke
075ca49a1f log that invalidation has occured when an input value changes a key 2018-05-01 10:06:13 -04:00
Barret Schloerke
9564f1d871 invalidate rlog namesDeps on value change 2018-05-01 10:05:36 -04:00
Barret Schloerke
cf546a47b6 on rlog object definition, do not trigger a value change 2018-05-01 10:05:23 -04:00
Barret Schloerke
d3a4f35170 merge master --> reactlog 2018-04-30 11:25:03 -04:00
Barret Schloerke
f450aea449 allow for skipping to next cycle by holding altKey and arrow L/R 2018-04-30 11:21:15 -04:00
Barret Schloerke
aed308b259 styles added to animation in cyto nodes 2018-04-30 11:20:45 -04:00
Barret Schloerke
714dffc943 set up ghost edge and use classes in cyto graph 2018-04-30 11:04:13 -04:00
Barret Schloerke
f8a173efbd first pass at cytoscape.js graph 2018-04-30 10:06:59 -04:00
Barret Schloerke
70e7822dd1 be clear in action name provided in log and give dependsOnRemove a ctxId 2018-04-30 10:06:40 -04:00
Winston Chang
01b24e984c Merge pull request #2038 from rstudio/joe/bugfix/cycle-start-bugs
Fix #2037: With enableBookmarking="url", clientData is not available …
2018-04-25 13:34:34 -05:00
Joe Cheng
9dd4302fe9 Fix #2037: With enableBookmarking="url", clientData is not available when observers are first run
Also fixed reactiveTimer firing even while async tasks are active
2018-04-25 10:54:00 -07:00
Winston Chang
c2f03aa833 Merge pull request #2036 from rstudio/joe/misc/renderui-experimental
Remove "experimental feature" tag from renderUI
2018-04-24 12:42:04 -05:00
Barbara Borges Ribeiro
2260459422 brought observeEvent/eventReactive documentation up to date 2018-04-24 17:44:54 +01:00
Barret Schloerke
452631550a single quotes to double quotes 2018-04-24 11:34:12 -04:00
Barret Schloerke
a14266b452 add freeze and thaw to logger 2018-04-24 11:34:00 -04:00
Winston Chang
e838cc3fe9 Re-document 2018-04-24 10:24:52 -05:00
Winston Chang
74457b95e9 NEWS edits 2018-04-24 10:17:03 -05:00
Barret Schloerke
ceb19c7573 use an rLog object to do all logging 2018-04-24 10:49:16 -04:00
Joe Cheng
d5754515a6 Remove "experimental feature" tag from renderUI 2018-04-23 17:05:08 -07:00
Joe Cheng
4ed13c04f5 Merge pull request #2032 from rstudio/fix-flushed-callbacks
Set default reactive domain when executing flushedCallbacks. Fixes #1975
2018-04-21 10:02:10 -07:00
Winston Chang
5a5294cc44 Set default reactive domain when executing flushedCallbacks. Fixes #1975 2018-04-21 11:46:50 -05:00
Joe Cheng
3a5d48ae7c Remove outdated Remotes
Live code review by @wch
2018-04-19 14:59:10 -07:00
Joe Cheng
6b605804d2 Upgrade Selectize to 0.12.4 2018-04-19 14:19:12 -07:00
Joe Cheng
ffe883ab72 Merge pull request #2022 from rstudio/joe/bugfix/timer-leak
Fix #2021: Memory leak with reactiveTimer and invalidateLater
2018-04-19 14:16:35 -07:00
Joe Cheng
31c4e0fdfe Add test to demonstrate vectorized unscheduling 2018-04-19 12:52:30 -07:00
Joe Cheng
66f970e0bd Merge pull request #2026 from rstudio/fix-ggplot2
Fix plot coordmap for devel version of ggplot2. Closes #2016
2018-04-19 12:46:38 -07:00
Winston Chang
07b223dcb0 Fix plot coordmap for devel version of ggplot2. Closes #2016 2018-04-19 11:40:26 -05:00
Joe Cheng
f1e27b6ffb Fix #1922: Warning: partial match of 'y' to 'yintercept' 2018-04-19 10:00:24 -05:00
Joe Cheng
389463aea5 Merge branch 'joe/feature/undedupe-inputs' 2018-04-18 19:33:37 -07:00
Joe Cheng
b11ab9a31c Update NEWS 2018-04-18 12:53:31 -07:00
Joe Cheng
5fe85b07b7 Merge remote-tracking branch 'andrewsali/master' 2018-04-18 12:52:40 -07:00
Joe Cheng
3c7b1e7d21 Update NEWS 2018-04-18 12:32:16 -07:00
Joe Cheng
c556cf1e69 Fix #2021: Memory leak with reactiveTimer and invalidateLater 2018-04-18 12:30:14 -07:00
Joe Cheng
722e5fb5f7 Modify internal JS to use Shiny.setInputValue, {priority: "event"} 2018-04-18 12:05:18 -07:00
Joe Cheng
e90cc591b7 Update NEWS 2018-04-18 11:57:55 -07:00
Barret Schloerke
7336d327b3 first pass at adding domain to all rlog functions 2018-04-18 11:49:11 -04:00
Joe Cheng
c555725201 Change {immediate: ...} to {priority: "deferred|immediate|event"}
This was the product of a long discussion between @wch, @alandipert, @bborgesr
and myself. The conflation of immediate (no throttle/debounce) and non-dedupe
in a single "immediate" flag was deemed unacceptable, because UI controls often
want immediacy but also dedupe. Introducing a second "dedupe" flag would work
but {immediate: false, dedupe: false} doesn't make much sense, and dedupe not
only implies that InputNoResendDecorator should behave differently but also
InputBatchSender (i.e. no deduplication AND no coalescing).

We decided to remove the "immediate" boolean option and replace it with a
string option that would have three possibilities at this time. The only con
to this approach is if anyone is calling onInputChange with immediate:true
today, and I can't imagine anyone is. The immediate flag only has any effect
if the input id that's being set has been put in debounce/throttle mode, and
I don't even think that is documented today, and I'm not even sure it's
possible to do it from custom JS (that's not part of a custom input binding).
2018-04-17 16:39:05 -07:00
Barret Schloerke
c9c5225a6a add rlogAsyncStart and rlogAsyncStop 2018-04-17 10:58:20 -04:00
Barret Schloerke
e1060bf537 isolate calls should be handled differently than regular rlog calls 2018-04-17 10:10:01 -04:00
Barret Schloerke
392e42a55d clean up when reactivevalues are defined and updated in rlog 2018-04-17 10:09:34 -04:00
Barret Schloerke
b974e41148 add test app for rlog 2018-04-17 10:09:00 -04:00
Barret Schloerke
aa3e2a0b64 ctxId's are now upgraded to start with 'ctx' in logging 2018-04-17 09:47:26 -04:00
Barret Schloerke
3df89dd9a3 local logging done with ". " for spacing 2018-04-17 09:46:54 -04:00
Joe Cheng
cef1f3c7ee withReactiveDomain now acts as a promise domain
Without this change, async handlers won't return any
value for getDefaultReactiveDomain().

    library(shiny)
    library(promises)

    ui <- fluidPage(
      p("This app tests if async handlers have reactive domains. You'll get a yes/no answer below."),
      h3(
        "Does it work?",
        textOutput("answer", inline = TRUE)
      )
    )

    server <- function(input, output, session) {
      output$answer <- renderText({
        promise_resolve(TRUE) %...>% {
          if (!is.null(getDefaultReactiveDomain()))
            "Yes!"
          else
            "No :("
        }
      })
    }

    shinyApp(ui, server)
2018-04-16 20:51:46 -05:00
Joe Cheng
e5d1fa1ea4 Fix #2008: Allow eventReactive and observeEvent eventExprs to be async (#2014)
* Fix #2008: Allow eventReactive and observeEvent eventExprs to be async

This makes it possible to monitor e.g. async reactives.

In the process of fixing this, also discovered that observers don't
filter out shiny.silent.error (i.e. req(FALSE)) when they come back
from async operations. For example, this will kill the current
Shiny session instead of being ignored:

  observe({
    promise_resolve(TRUE) %...>%
      {req(FALSE)}
  })

This issue is also fixed in this commit.

* Enable deep stack trace by default, now that it's fast
2018-04-16 20:50:28 -05:00
Joe Cheng
3ccf2937b4 Fix #928: allow inputs to trigger reactive flow even if the value of input hasn't changed
We already had an `immediate` input option, which was used to override client side rate
limiting mechanisms (debounce/throttle). This commit extends the semantics of that option
to also mean that duplicate values should not be ignored on the client side.

Previous to this commit, circumventing the client side dedupe logic was not enough. The
server side ReactiveValues object was also subject to deduping. With this commit, the
low-level ReactiveValues class's constructor now has a `dedupe` option, which defaults
to TRUE; the ReactiveValues used for a session's input has it turned to FALSE. I figure
if I had to work this hard to get the client to stop sending duplicates, and the input
values are only expected to ever be updated by the client, then there's really no reason
for server side deduping to be performed for this particular ReactiveValues object.

It would make sense as a future feature to also make deduping optional for user-created
reactiveValues and reactiveVal objects.
2018-04-16 18:37:47 -07:00
Joe Cheng
b7b696630f Fix #2003: Long stack traces are truncated 2018-04-16 17:16:12 -05:00
Joe Cheng
84aba546bc Fix #2000: Implicit calls to xxxOutput not working inside modules (#2010)
* Fix #2000: Implicit calls to xxxOutput not working inside modules

* Add comment, update NEWS

* Credits in NEWS
2018-04-16 16:57:13 -05:00
Barret Schloerke
6ef751422a first pass at reformatting rlog 2018-04-16 13:37:50 -04:00
Barret Schloerke
05d49ee45e use MessageLogger for node information cache 2018-04-16 09:47:58 -04:00
Barret Schloerke
3e4783c454 remove dot syntax 2018-04-16 09:33:09 -04:00
Barret Schloerke
ce93201843 make the rlog messages a r6 object 2018-04-16 09:28:54 -04:00
Barret Schloerke
f9fc3a46b5 change all nodeId to reactId 2018-04-16 09:17:04 -04:00
Barret Schloerke
0467d6666a merge master -> barret/reactlog 2018-04-13 11:26:34 -04:00
Barret Schloerke
1f26b076a3 first pass gantt chart... brings up future thoughts
could add a gantt chart at bottom of react-graph for the current execution session. Would be interesting to have a full gantt of the current execution 'cycle' with a bar indicating where we are in time to give context to the current graph layout. the gantt coult reset at each 'cycle' as the context is reset as well
2018-04-13 11:22:23 -04:00
Barret Schloerke
7944f21925 break apart the large react-graph.html file 2018-04-13 10:20:08 -04:00
Barret Schloerke
e91eda8eca add npm scripts to build, clean, and watch the js 2018-04-13 10:19:10 -04:00
Barret Schloerke
d8ac84a5da add rLogValueChange (no start/end, just change) 2018-04-13 10:18:11 -04:00
Barret Schloerke
3098a02b72 first pass at making rlog. need javascript to recognize new log format 2018-04-13 10:07:03 -04:00
Winston Chang
741236df56 Merge pull request #2011 from rstudio/joe/feature/output-null
Fix #1989: Allow outputs to be removed by assigning NULL to them
2018-04-12 16:29:48 -05:00
Winston Chang
e3584f0a61 Merge pull request #2013 from rstudio/joe/bugfix/render-plot-args
renderPlot's ... args were being dropped
2018-04-12 16:27:46 -05:00
Joe Cheng
432482c5a7 renderPlot's ... args were being dropped 2018-04-12 11:57:32 -07:00
Joe Cheng
323ad46bba Implement #1989: Allow outputs to be removed by assigning NULL to them 2018-04-11 18:40:32 -07:00
Alan Dipert
ace0fe1802 Merge pull request #2005 from rstudio/alan/bugfix/dndfix
Fix dragging and dropping in the presence of jQuery 3.0
2018-04-11 11:53:42 -07:00
Alan Dipert
36f244fece Merge branch 'master' into alan/bugfix/dndfix 2018-04-11 11:52:23 -07:00
Joe Cheng
99e5ef99ec Move some bullets around 2018-04-10 10:08:15 -07:00
Alan Dipert
d6d3ed5bbc NEWS 2018-04-10 08:40:40 -07:00
Alan Dipert
49d09ecf30 Grunt 2018-04-10 08:30:46 -07:00
Alan Dipert
c529a03096 DnD: Fix in the presence of jQuery 3.0 (removed .size()) 2018-04-10 08:29:03 -07:00
Andras Sali
101d9aa0fa Move trigger after value change 2018-04-07 16:51:03 +02:00
Andras Sali
b4864e1180 Trigger shiny:value even if same data is received. Fixes #1978 2018-04-07 16:46:34 +02:00
Winston Chang
cba7304ab9 Merge pull request #1996 from rstudio/fix-selectize
fix selectize capitalization (regression introduced by #1861)
2018-04-05 11:58:20 -05:00
Barbara Borges Ribeiro
2d058b0519 move attribute setting to after choices is reassigned (this was getting lost after the changes in #1861). 2018-04-04 19:55:15 +01:00
Barbara Borges Ribeiro
eed9231884 fix selectize capitalization (regression introduced by #1861) 2018-04-04 14:00:44 +01:00
Joe Cheng
5c84eaf2a5 Merge pull request #1990 from rstudio/joe/feature/better-stacks
Better stack traces
2018-03-27 19:31:51 -07:00
Joe Cheng
2ef7226be0 Use seq_along instead of 1:length(x)
It behaves when length(x) == 0
2018-03-27 18:30:24 -07:00
Joe Cheng
e5d1c61cdf Merge branch 'master' into joe/feature/better-stacks 2018-03-27 18:04:05 -07:00
Joe Cheng
e635055ab8 Update NEWS 2018-03-27 18:02:41 -07:00
Joe Cheng
d8d4e3b262 Don't error when entire stack trace is stripped/pruned 2018-03-27 16:35:45 -07:00
Joe Cheng
8f29543479 Use qualified name for utils::tail (R CMD check NOTE) 2018-03-27 16:19:28 -07:00
Joe Cheng
c11a8ea24b Fix tests 2018-03-27 15:35:29 -07:00
Joe Cheng
86646d7faa Make srcref offsetting optional 2018-03-27 15:35:06 -07:00
Joe Cheng
6e44915e08 Merge pull request #1984 from rstudio/joe/feature/faster-deep-stacks
Lazily format stack traces
2018-03-27 10:31:00 -07:00
Joe Cheng
f8b99cf4e9 Add deprecation docs 2018-03-26 11:38:12 -07:00
Joe Cheng
0e7d6ff192 Refactoring and deprecation in conditions.R
- Refactor printError so a working printStackTrace falls out
- Deprecate extractStackTrace and formatStackTrace, see if anyone uses them
2018-03-26 11:35:50 -07:00
Barbara Borges Ribeiro
66501dac97 Add new autoclose = TRUE param to dateInput() and dateRangeInput (#1987)
* Add new `autoclose = TRUE` param to both dateInput() and dateRangeInput()

* added NEWS item
2018-03-23 09:40:19 -07:00
Joe Cheng
195907b2ec printError implements lobstr::cst analysis and deep-stack-aware frame suppression 2018-03-22 12:22:46 -07:00
Joe Cheng
be11b44864 First steps to improved stack traces
- Adds functions we will need for tracking ..stacktraceon/off..
  across deep stacks
- Adds functions we will need for pruning according to lobstr::cst
  logic

These functions are not yet integrated, that will occur in a
separate commit.
2018-03-20 16:45:47 -07:00
Joe Cheng
bc7cd21c13 Update NEWS.md 2018-03-20 16:39:52 -07:00
Carson Sievert
0555cbdd28 relay offsetWidth/offsetHeight of htmlwidgets to clientData (#1981)
Addresses #1980
2018-03-20 16:37:43 -07:00
Joe Cheng
97498451bb Lazily format stack traces
With deep stack traces enabled, whenever then() is called, we need
to grab the current stack, just in case a downstream callback throws
an error and we need to form a deep stack trace.

Previously, we were calling formatStackTrace at the time that we
grab the current stack (i.e. no error has happened yet) because I
wasn't sure whether holding a reference to sys.calls() for a long
time was a good idea from a garbage collection perspective; would it
prevent the stack frame environments from being collected? But the
answer is no, sys.calls() is just calls, which can be confirmed with
.Internal(inspect(sys.calls()).

By deferring the formatStackTrace call to when we actually need to
print the stack trace, we save ourselves a ton of work--it turns out
it's quite expensive to format the stack traces, much more expensive
than sys.calls() alone.
2018-03-20 12:35:17 -07:00
Joe Cheng
2e0d9b5475 Bump httpuv dependency version 2018-03-18 19:07:43 -07:00
Barbara Borges Ribeiro
62395f3103 Improve error handling when addResourcePath() fails (especially for runtime: shiny_prerendered documents) (#1968)
* A copy of yihui's PR for rmarkdown (https://github.com/rstudio/rmarkdown/pull/1171/) to avoid to error "Error in normalizePath: path[1]="": No such file or directory" when running any tutorial

* first try

* limited the scope of the `tryCatch` wrapper to the one important line that needed it; added news item
2018-03-16 15:36:12 -07:00
Winston Chang
6b31cd6aee Merge pull request #1965 from rstudio/joe/bugfix/plot-dim-error
Fix #1964: renderPlot cache breaks when width/height throw
2018-03-01 11:12:56 -06:00
Joe Cheng
e67a8ba369 Fix #1964: renderPlot cache breaks when width/height throw
Fixed by moving the isolate(getDims()) call into the (effectively)
try/catch that does a non-isolated getDims() if an error occurs
2018-02-28 15:40:55 -08:00
Joe Cheng
133d301925 Merge pull request #1961 from rstudio/fix-date-sliders-bookmarking
Fix URL-encoded bookmarking with date/date-time sliders
2018-02-28 14:26:50 -08:00
Joe Cheng
17c40a5d1d Merge pull request #1960 from rstudio/slider-formatting
Don't show commas after decimal mark in sliderInput
2018-02-28 13:01:20 -08:00
Winston Chang
042211e5f6 Grunt 2018-02-28 14:34:09 -06:00
Winston Chang
d12830d700 sliderInput: don't show commas after decimal 2018-02-28 14:33:42 -06:00
Winston Chang
b411c70280 Fix URL-encoded bookmarking with date/date-time sliders 2018-02-27 20:42:11 -06:00
Winston Chang
2bc22cc7d5 Merge pull request #1955 from rstudio/update-slider
Update ion.rangeSlider to 2.2.0
2018-02-27 13:21:09 -06:00
Joe Cheng
b4c189c89b Merge pull request #1956 from rstudio/fix-slider-rounding
Avoid rounding errors in sliderInput
2018-02-27 10:55:11 -08:00
Winston Chang
fe3f351a2d Avoid rounding errors from pretty(). Fixes #1006 2018-02-27 10:50:36 -06:00
Winston Chang
076be9cba7 Remove unused keyboard_step parameter
keyboard_step was removed in ion.rangeSlider 2.2.0.
2018-02-26 15:57:30 -06:00
Winston Chang
f28dcd85fb Update to ion.rangeSlider 2.2.0 2018-02-26 15:57:30 -06:00
Joe Cheng
8e0f17c9d7 Merge pull request #1954 from rstudio/fix-bookmark-restore
Look for restore context associated with session
2018-02-26 09:25:33 -08:00
Winston Chang
d73817a0db Look for restore context associated with session. Fixes #1948 2018-02-26 10:55:38 -06:00
Joe Cheng
11874db825 Remove background-thread branch from httpuv remote 2018-02-16 15:41:32 -08:00
Joe Cheng
5d5a43ce90 Merge pull request #1932 from rstudio/async
Async
2018-02-16 07:41:36 -08:00
Winston Chang
75e548caab For installation of Rtools on Appveyor 2018-02-16 09:15:40 -06:00
Joe Cheng
c901e7ba06 Update TODO-promises.md 2018-02-13 15:23:06 -08:00
Joe Cheng
b1dc3dfca1 Restore label to plotObj reactive 2018-02-09 11:12:46 -08:00
Joe Cheng
ce4ed20c69 Fix remaining failing tests 2018-02-09 11:12:46 -08:00
Joe Cheng
d44df7f860 Stack traces were being lost inside hybrid_chain 2018-02-09 11:12:46 -08:00
Joe Cheng
54353e0e1f Fix coordmap unit tests 2018-02-09 11:12:46 -08:00
Joe Cheng
1c042b6efb Add to .Rbuildignore 2018-02-09 11:12:46 -08:00
Joe Cheng
b8df1f29c4 Remove unused function 2018-02-09 11:12:46 -08:00
Joe Cheng
18252f5b03 Use later >= 0.7.1 2018-02-09 11:12:46 -08:00
Joe Cheng
881370f284 Remove extraneous comments 2018-02-09 11:12:46 -08:00
Joe Cheng
35d1747bc3 Don't allow invalidation from a child process 2018-02-09 11:12:46 -08:00
Joe Cheng
91ac89a54e Update TODOs 2018-02-09 11:12:46 -08:00
Joe Cheng
3c694d9bd9 More robust process identification (thanks @HenrikBengtsson) 2018-02-09 11:12:46 -08:00
Joe Cheng
6a78e9df77 Detect (probably inadvertent) attempts to inherit reactive contexts across processes
Example (we want this to fail):

library(shiny)
library(future)
plan(multicore)

r <- reactiveVal(TRUE)
isolate({
  f <- future({
    r()
  })
  value(f)
})
2018-02-09 11:12:45 -08:00
Joe Cheng
078c6eb30a Add TODO 2018-02-09 11:12:45 -08:00
Joe Cheng
d35c6002a6 Respect pixelratio (retina) when redrawing cached images 2018-02-09 11:12:45 -08:00
Joe Cheng
f23fc3beaa Plots were not respecting pixel ratio (retina) 2018-02-09 11:12:45 -08:00
Joe Cheng
5a352e5ace Update TODOs 2018-02-09 11:12:45 -08:00
Joe Cheng
27cae0065e Fix bug where req(cancelOutput=TRUE) would leave things grey
This was introduced by some changes to shinyapp.js that were necessary
before async outputs and sync outputs were held/flushed together. Now
that async/sync outputs are held/flushed together, these changes are
not necessary and removing them fixes the problem.

The test app is in shiny-examples/205-async-req. I also moved a test
app from manualtests/async/download.R to shiny-examples/204-async-download.
2018-02-09 11:12:45 -08:00
Joe Cheng
50be2993fa Add TODO 2018-02-09 11:12:45 -08:00
Joe Cheng
d9ea15e9bc Update TODOs 2018-02-09 11:12:45 -08:00
Joe Cheng
03b1d45d7e Make deep stack traces opt-in; fix imports 2018-02-09 11:12:45 -08:00
Joe Cheng
e48d6878c4 Update TODOs 2018-02-09 11:12:45 -08:00
Joe Cheng
1a3b255848 Update TODOs 2018-02-09 11:12:45 -08:00
Joe Cheng
f00aa94d7e Suspend session during async download operation 2018-02-09 11:12:45 -08:00
Joe Cheng
f7980b19f4 Update TODOs 2018-02-09 11:12:45 -08:00
Joe Cheng
6a1f9677a5 Support async downloadHandler content functions
If a downloadHandler content function returns a promise (or future)
then Shiny will wait for the promise to resolve before serving up
the file download.
2018-02-09 11:12:45 -08:00
Joe Cheng
e844bb36a5 Update TODOs 2018-02-09 11:12:45 -08:00
Joe Cheng
ae364adfc2 wip2 2018-02-09 11:12:45 -08:00
Joe Cheng
c14a382b90 wip 2018-02-09 11:12:45 -08:00
Joe Cheng
da9c2beaaf Update TODO 2018-02-09 11:12:45 -08:00
Joe Cheng
a4a56476db Update TODO 2018-02-09 11:12:45 -08:00
Joe Cheng
39d3784b9b async support for renderDataTable 2018-02-09 11:12:45 -08:00
Joe Cheng
7d29df58f1 Support same-tick execution for synchronous outputs 2018-02-09 11:12:45 -08:00
Joe Cheng
05aa413683 promises::finally() was missing namespace prefix 2018-02-09 11:12:45 -08:00
Joe Cheng
132f90f45b Support promise domain wrapSync; fix renderPrint visibility
Also introduce promise_chain and hybrid_chain, for assembling chains of
operations without involving magrittr-style operators
2018-02-09 11:12:45 -08:00
Joe Cheng
4526fd1917 Update TODO 2018-02-09 11:12:45 -08:00
Joe Cheng
2602dc15b0 Changes to flush cycle to support async
- Moved (in|de)crementBusyCount calls out of Context and into Observer
- decrementBusyCount is (effectively) deferred for async observers until
  the async operation is complete
- invalidateLater didn't force(session), almost certainly was buggy
- invalidateLater, reactiveTimer, and manageInputs all now use a new
  session$cycleStartAction, which delays their effect until observers
  (including async ones) are done executing
2018-02-09 11:12:45 -08:00
Joe Cheng
2314f63424 Fix broken .shiny__stdout mechanism 2018-02-09 11:12:45 -08:00
Joe Cheng
c2410600ee Refactor list of TODOs 2018-02-09 11:12:45 -08:00
Joe Cheng
f7e4702685 Restore writing of _n_flushReact and _x_flushReact to stdout 2018-02-09 11:12:45 -08:00
Joe Cheng
71682512c4 Refactor flush cycle 2018-02-09 11:12:45 -08:00
Joe Cheng
20b82fbf77 Cleanup R CMD check 2018-02-09 11:12:45 -08:00
Joe Cheng
631f09847d Update TODOs 2018-02-09 11:12:45 -08:00
Joe Cheng
671585f68a Update TODOs 2018-02-09 11:12:45 -08:00
Joe Cheng
5feed888bb Add promises to remotes 2018-02-09 11:12:45 -08:00
Joe Cheng
47bef0f1b0 Remove extraneous debugging code 2018-02-09 11:12:45 -08:00
Joe Cheng
c1dc662a40 "promise" package was renamed to "promises" 2018-02-09 11:12:45 -08:00
Joe Cheng
16e1721fe8 Add TODO comment 2018-02-09 11:12:45 -08:00
Joe Cheng
f406e13600 Add TODO 2018-02-09 11:12:45 -08:00
Joe Cheng
9063133a7b Fix various rendering bugs 2018-02-09 11:12:45 -08:00
Joe Cheng
3fbb436187 Add call_async temporarily; this should probably live somewhere else 2018-02-09 11:12:45 -08:00
Joe Cheng
7c845d070b Sync to changes in promise. run_now aggressively in serviceApp. 2018-02-09 11:12:45 -08:00
Joe Cheng
5e905aa73e Implement execOnResize 2018-02-09 11:12:45 -08:00
Joe Cheng
e15654f265 Minor renderPlot cleanup 2018-02-09 11:12:45 -08:00
Joe Cheng
369c067efc Update TODO 2018-02-09 11:12:45 -08:00
Joe Cheng
c037e69793 Fix ggplot brushing 2018-02-09 11:12:45 -08:00
Joe Cheng
8c935ff44e Use proper promise:: prefix 2018-02-09 11:12:45 -08:00
Joe Cheng
74bf8b0554 renderPlots works!!! Testing needed. 2018-02-09 11:12:45 -08:00
Joe Cheng
6345972efe Adapt promise domains to handle multiple arguments 2018-02-09 11:11:35 -08:00
Joe Cheng
16242e87a1 Some steps toward renderPlot working. Move to promise package instead of system2.5. 2018-02-09 11:11:34 -08:00
Joe Cheng
8155320ba5 wip 2018-02-09 11:09:28 -08:00
Winston Chang
39a7f63972 Update NEWS 2018-01-29 13:45:23 -06:00
Dmitriy Selivanov
7b72209277 fixes #1859 (#1861)
* style & formatting. fixes #1859

* prepare `choices` in `updateSelectizeInput()` as per discussion in #1861

* remove duplicated block in selectizeJSON, simply `lab` assignement logic
2018-01-29 13:41:30 -06:00
Joe Cheng
cad20a0bfe Merge pull request #1856 from rstudio/wch-do-call
Quote arguments to do.call() for nicer stack traces
2017-10-31 11:28:47 -07:00
Winston Chang
ba8d79f202 Fix version text substitution 2017-10-17 10:51:19 -05:00
Winston Chang
176fe699b9 Point to RStudio Community website instead of shiny-discuss 2017-09-27 15:54:05 -05:00
Winston Chang
213ee7be13 Quote arguments to do.call() for nicer stack traces. Closes #1851 2017-09-26 14:36:19 -05:00
Joe Cheng
48fd869c71 Merge pull request #1848 from rstudio/barbara/fix/icon
Revert back the relative position of the icon and title in tabPanel's and navbarMenu's
2017-09-12 07:34:31 -07:00
Barbara Borges Ribeiro
53e47484e2 reverted the relative positioning of the icon and the title text in navbarMenus and tabPanels back to what it was before Shiny 1.0.5 (fixes #1840) 2017-09-12 12:16:06 +01:00
Winston Chang
dc18b20e5a Don't copy httpuv::decodeURIComponent at build time 2017-09-07 21:31:32 -05:00
Barbara Borges Ribeiro
b4c5debbdf Merge pull request #1844 from rstudio/barbara/fix/reactlog
Changed script tags in reactlog from HTTP to HTTPS
2017-09-07 01:43:46 +01:00
Barbara Borges Ribeiro
771d3d52b9 Changed script tags in reactlog from HTTP to HTTPS in order to avoid mixed content blocking by most browsers (thanks @jekriske-lilly) 2017-09-07 01:34:17 +01:00
Joe Cheng
2a53ac093d Merge pull request #1830 from rstudio/wch-compare-version
Add Shiny.compareVersion() function
2017-09-05 11:37:17 -07:00
Winston Chang
4fa2af72cc Avoid port 6697. Closes #1784 2017-08-28 16:40:51 -05:00
Winston Chang
e512d3cd61 Grunt 2017-08-25 14:46:19 -05:00
Winston Chang
16b7ee3985 Add Shiny.compareVersion() function 2017-08-25 14:46:06 -05:00
Winston Chang
4f3d26c31b Add Shiny.version to Javascript (#1826)
* Add Shiny.version to Javascript

* Grunt
2017-08-23 15:52:16 -05:00
Winston Chang
587bf94d69 Merge tag 'v1.0.5'
Shiny 1.0.5 on CRAN
2017-08-23 15:27:56 -05:00
Winston Chang
635ad77e0d Bump version to 1.0.5 2017-08-23 13:11:59 -05:00
Winston Chang
33258da6c3 Bump version to 1.0.5.9000 2017-08-23 13:07:15 -05:00
Joe Cheng
c2b3c3379d Fix #1824: HEAD request on static files causes app to stop (#1825)
* Fix #1824: HEAD request on static files causes app to stop

The problem was that for HEAD requests specifically, we implement
an explicit Content-Length header (normally we let httpuv figure
out the Content-Length based on the content, but for HEAD we don't
return any content but still want to include the Content-Length).

The Content-Length header was only implemented correctly for string
values, not for raw vectors or file-by-path. This change implements
the value correctly for all currently valid httpuv content.

* Update NEWS

* Code review feedback
2017-08-23 13:01:22 -05:00
Winston Chang
e30fac02ed Add safe wrapper for fromJSON 2017-08-21 19:55:48 -05:00
Winston Chang
e74592a654 Escape a few more characters for conditionalPanel expressions 2017-08-21 14:25:20 -05:00
Joe Cheng
ebd47aa73b Merge pull request #1820 from rstudio/wch-fix-conditionalpanel
Escape newline characters in conditionalPanel expression
2017-08-18 20:49:48 -04:00
Winston Chang
e2d19cbaba Grunt 2017-08-18 17:24:06 -05:00
Winston Chang
1f864a846f Escape newline chars in conditionalPanel expr. Fixes #1818 2017-08-18 17:24:06 -05:00
Winston Chang
fc32c2c944 Clarify that choices must be strings 2017-08-18 11:48:41 -05:00
Winston Chang
279e37f1cb Bump version to 1.0.4.9000 2017-08-18 11:47:19 -05:00
Winston Chang
3f9176176e Merge tag 'v1.0.4'
Shiny 1.0.4 on CRAN
2017-08-14 12:01:26 -05:00
Winston Chang
b3201ccafd Add functions to news item 2017-08-10 14:29:06 -05:00
Winston Chang
2a01a620a9 Add NEWS summary 2017-08-10 12:03:22 -05:00
Winston Chang
6f43cf7b82 NEWS cleanup 2017-08-09 18:49:34 -05:00
Winston Chang
1c6250f9c2 Bump version to 1.0.4 2017-08-09 18:49:34 -05:00
Barbara Borges Ribeiro
650075a9ab Fix appendTab for empty tabsetPanels (#1813)
* fix appendTab for empty tabsetPanels; use spread operator to avoid having to resort to apply; upgrade grunt.

* revert back to `Math.max.apply(null, existingTabIds) + 1;` there's no browser compatibility issues there
2017-08-09 18:45:25 -05:00
Winston Chang
668ee6f24a Add references to issues 2017-08-08 11:16:57 -05:00
Alan Dipert
c456ec2c4c drag/drop-able fileInputs (#1782)
* fileInput WIP: Show dropzones when file dragged over window

- Still need to validate dataTransfer contents

* WIP: Basic functionality working

* wip

* Grunt

* WIP state machine

* WIP generalize FSM to data+multimethod

* WIP multimethod

* WIP draghover

* wip multimethod

* WIP, such refactor

* WIP: rm multimethod

* WIP

* WIP resurrect multimethod

* WIP move draghover functions into input object

* WIP colors: use more muted, bootstrap-esque glows

* Grunt

* WIP: use whenAny, more descriptive args in default test/dispatch fns

* WIP more whenAny

* Grunt

* WIP dont use for...of, requires polyfill

* Grunt

* multimethod improvements, documentation. `equal` function.

* multimethod: simplified equal, removed need for forward decl. docs.

* dox

* multimethod improvements, docs

* minor

* IE 10+ drag/drop, first cut

* Grunt

* use functions not arrows for faux instance methods

* Grunt

* fix uploadDropped call

* Grunt

* cleanup drop handler, fix entry to invalid state via doc drop handler

* Grunt

* IE workaround #293932

* Grunt

* yeeeeeeeeeeessss IE WORKSSSSS

* Cleanup; support activeClass/overClass

* everything basically works everywhere \o/

* revert ability to specify classes, hardcode in JS

* MM fixes

* minor fixes

* Grunt

* DnD: Support dragging directly over zones
- Happens when source window occludes browser window

* woo

* Note Safari bug, use draghover for zones

* merge

* Grunt

* news

* include CSS
2017-08-08 11:12:21 -05:00
Joe Cheng
3b0c390a9e Merge pull request #1794 from rstudio/barbara/tabs
Dynamic tabs
2017-08-04 11:31:50 -07:00
Barbara Borges Ribeiro
b02eb11345 do inputId <- session$ns(inputId) in user facing functions for module functionality (rather than overriding the same functions in makeScope) 2017-08-04 18:02:43 +01:00
Barbara Borges Ribeiro
ed3ba303bc Joe's feedback 2017-08-04 17:56:58 +01:00
Barbara Borges Ribeiro
ee5da1410e make hide and remove work well when we want to hide/remove a tab inside a navbarMenu (or the whole menu) and it is selected (before this commit, it wasn't navigating to the first tab like it is supposed to) 2017-08-04 15:10:08 +01:00
Barbara Borges Ribeiro
494627c6e1 make this PR work for modules 2017-08-04 15:10:08 +01:00
Barbara Borges Ribeiro
82ac112dec added select argument to showTab function 2017-08-04 15:10:08 +01:00
Barbara Borges Ribeiro
40cfff33ff for dynamic tabs, send message on session$onFlush (instead of session$onFlushed) 2017-08-04 15:10:08 +01:00
Joe Cheng
c1c5873912 Abandon nearest neighbor tab-showing logic. Just grab the first tab. 2017-08-04 15:10:08 +01:00
Joe Cheng
c090efd562 Fix bug where last tab being removed, didn't update tabset input value 2017-08-04 15:10:08 +01:00
Joe Cheng
91dbb0e77b htmlDependencies are properly loaded with dynamic tabs 2017-08-04 15:10:08 +01:00
Joe Cheng
dde7b144f0 Add select=FALSE argument to insert/append/prependTab 2017-08-04 15:10:08 +01:00
Joe Cheng
f1873a014c Make tab prepend/append just edge cases of insert 2017-08-04 15:10:08 +01:00
Joe Cheng
48b8923b67 Properly escape jQuery selector strings 2017-08-04 15:10:08 +01:00
Barbara Borges Ribeiro
6f9f3fea83 implement navigation after hiding/removing selected tab 2017-08-04 15:10:08 +01:00
Barbara Borges Ribeiro
10f3320165 more JS code refactoring; improved documentation 2017-08-04 15:10:08 +01:00
Barbara Borges Ribeiro
d57aa33b40 insertion fully implemented 2017-08-04 15:10:08 +01:00
Barbara Borges Ribeiro
0e7c78bae3 refactored code and made insertion of navbarMenus possible 2017-08-04 15:10:08 +01:00
Barbara Borges Ribeiro
e6602786ec updated docs 2017-08-04 15:10:08 +01:00
Barbara Borges Ribeiro
31bbb3894c remove extra line 2017-08-04 15:10:08 +01:00
Barbara Borges Ribeiro
8bbf576807 typo: tag -> tab (makes a big difference!) 2017-08-04 15:10:08 +01:00
Barbara Borges Ribeiro
1ecc9b9d0e Fixed documentation problems and JS code logic 2017-08-04 15:10:08 +01:00
Barbara Borges Ribeiro
3adbebc3d9 document similar things together; add prependTab and appendTab 2017-08-04 15:10:08 +01:00
Barbara Borges Ribeiro
a4c086f51b now working for navbarPage and navlistPanel 2017-08-04 15:10:08 +01:00
Barbara Borges Ribeiro
0ecdcec698 clean up JS code (1 line only) 2017-08-04 15:10:08 +01:00
Barbara Borges Ribeiro
ae7f026d46 added NEWS and fixed typo 2017-08-04 15:10:08 +01:00
Barbara Borges Ribeiro
2813e0b706 update examples 2017-08-04 15:09:00 +01:00
Barbara Borges Ribeiro
a409562d00 delete extra brackets 2017-08-04 15:09:00 +01:00
Barbara Borges Ribeiro
b6b6661ea1 implement showTab and removeTab 2017-08-04 15:09:00 +01:00
Barbara Borges Ribeiro
fb7b6f667c implement removeTab 2017-08-04 15:09:00 +01:00
Barbara Borges Ribeiro
b94efe81e4 finish insertTab 2017-08-04 15:09:00 +01:00
Barbara Borges Ribeiro
72a1b3d2a0 add functions to index.r 2017-08-04 15:09:00 +01:00
Barbara Borges Ribeiro
20bff18bd4 changes 2017-08-04 15:09:00 +01:00
Winston Chang
ba5c5ef4fb Move isRunning function to better location 2017-07-27 14:56:01 -05:00
Barbara Borges Ribeiro
aff3ac0bb3 Add onStop function (#1770)
* NEWS item

* added `onStop` arg to `shinyApp()` (and renamed our internal `onEnd` - which is what was calling `on.exit()` already - to `onStop` as well)

* added onStop() function

* add entry for documentation

* make it work for all possible app structures (interactive, saved as app.R, saved as ui.R and server.R)

* fix #1772: make sure `onStart` works in all scenarios

* update NEWS

* improved wording

* more wording

* and more wording

* don't stop execution if a `onStop` callback function results in an error

* remove "(all sessions have been disconnected)" because it's misleading

* add @seealso documentation

* shamefully forgot to Cmd Shift D

* change code place

* Code review feedback

* onStop: use session argument instead of scope
2017-07-27 14:54:55 -05:00
Winston Chang
2c350daf01 Merge pull request #1802 from rstudio/bugfix/rstudio-debugger
work around RStudio debugger issue (closes #1474)
2017-07-27 13:14:01 -05:00
Winston Chang
cb7627c736 Update NEWS and add comment 2017-07-27 13:13:31 -05:00
Kevin Ushey
f731a5cae4 work around RStudio debugger issue (closes #1474) 2017-07-27 10:37:56 -07:00
Winston Chang
07cb7c9305 Add 'setSerializer' function (#1792) 2017-07-18 17:01:06 -05:00
Winston Chang
86e9cc4896 Add preprocessor for fileInputs that strips local path (#1789)
* Add preprocessor for fileInputs that strips local path

* Update NEWS

* Rename snapshotPreprocess to snapshotPreprocessOutput

* Add snapshotPreprocessInput function

* Remove unnecessary NEWS item

* Update NEWS

* Add getSnapshotPreprocessInput

* Add staticdocs entry for snapshotPreprocessInput

* Add private methods to get snapshotPreprocess functions

* Bump version to 1.0.3.9002
2017-07-13 16:07:16 -05:00
Joe Cheng
12c9405257 Merge pull request #1790 from rstudio/wch-warn-level
Don't reduce warn level when running app
2017-07-12 22:41:21 -07:00
Winston Chang
4708b44c59 Don't reduce warn level when running app. Fixes #1680 2017-07-12 19:29:49 -05:00
Winston Chang
4cb428bb92 Add a function to test if an app is running (#1785)
Squashed commit of the following:

commit 8667bed8962069a5cab8691f981e2b7ba9d449c3
Author: Winston Chang <winston@stdout.org>
Date:   Tue Jul 11 14:36:11 2017 -0500

    Edits

commit c4e8549ca5
Author: Konrad Rudolph <konrad.rudolph@gmail.com>
Date:   Fri Jul 7 17:57:33 2017 +0100

    Describe changes

commit 7b05c2e60f
Author: Konrad Rudolph <konrad.rudolph@gmail.com>
Date:   Fri Jul 7 17:54:40 2017 +0100

    Add new function to doc index

commit eb93ebfad8
Author: Konrad Rudolph <konrad.rudolph@gmail.com>
Date:   Fri Jul 7 17:54:30 2017 +0100

    Add documentatio for new function

commit 1a6c8a4d72
Author: Konrad Rudolph <konrad.rudolph@gmail.com>
Date:   Fri Jul 7 17:53:13 2017 +0100

    Add a function to test whether the app is running
2017-07-11 14:36:59 -05:00
Mine Cetinkaya-Rundel
d7391b19bc Convert examples to single file apps (#1685)
* - Convert all example apps to single file app.R file
- Make relevant updates to Readmes to match up with app.R structure
- Add color to plots (RStudio blue)
- In 04_mpg example: Show outliers by default, as opposed to hide, since this is more routine
- In 06_tabsets and 08_html examples: Don't name random data vector "data"
- Add extensive comments to app.R files and use consistent formatting of comments across examples
- In 09_upload example: Use req() to check for NULL entry

* add news entry summarizing changes

* use true RStudio blue, #75AADB

* Conver shinyApp calls at the end to drop argument name in examples 3-11, except for the custom HTML example. Kept them in for examples 1&2 for completeness in first exporuse to function.

* Pull news items that got added before this PR was merged

* Update comment for shinyApp function -- it creates an app object, doesn't run the app
2017-07-11 14:20:01 -05:00
Joe Cheng
db9e56d1ca Merge pull request #1768 from rstudio/wch-fix-with-private-seed
Fix withPrivateSeed
2017-07-11 12:17:02 -07:00
Winston Chang
e527af10f4 New version of httpuv is on CRAN 2017-07-11 13:45:45 -05:00
Joe Cheng
74c7be0a6d Merge pull request #1786 from rstudio/joe/bugfix/fileinput-content-type
Use a more suitable content type for file uploads
2017-07-10 15:39:13 -07:00
Joe Cheng
2d40e7b51a Use a more suitable content type for file uploads
application/x-www-form-urlencoded;charset=UTF-8 is the default, which shinyapps.io
cares about for some reason and tries to parse the data as such. By setting the
content type to the more accurate application/octet-stream, no middleware should
be tempted to futz with the contents.
2017-07-10 15:33:42 -07:00
Winston Chang
ea407fb2ea Don't include xtable comment in renderTable by default 2017-06-27 15:05:31 -05:00
Winston Chang
fca5b0529a Remove reinitalizeSeed
This function is no longer needed because the minimum R vesion supported by Shiny is 3.0.2.
2017-06-27 10:30:50 -05:00
Winston Chang
65fd1dd2d8 Remove branch name for httpuv remote 2017-06-26 22:40:37 -05:00
Winston Chang
0a7ede3818 Add tests for random streams 2017-06-26 21:59:52 -05:00
Winston Chang
24e84f3866 Prevent private random stream from leaking out. Fixes #1763 2017-06-26 21:59:51 -05:00
Winston Chang
c1c8e46c09 Refactor withPrivateSeed 2017-06-26 21:59:51 -05:00
Winston Chang
8591e4f301 Add working app for conditionalPanel example 2017-06-23 10:14:32 -05:00
Alan Dipert
10db7ad89c Support modules in conditionalPanel (#1735) 2017-06-23 10:12:15 -05:00
Joe Cheng
4ca4f442b9 Required R version is 3.0.2 due to sourcetools 2017-06-22 19:42:49 -05:00
Winston Chang
6d5ecbc9c4 Fix indentation 2017-06-22 13:18:05 -05:00
Winston Chang
ea685a5686 Don't send local package path to client when using htmlwidgets (#1756)
* Don't send local package path to client when using htmlwidgets. Fixes #1755

* Add scrubFile option
2017-06-22 13:16:19 -05:00
Winston Chang
376d3b6e91 Merge pull request #1760 from rstudio/wch-snapshot-preprocess
Add snapshotPreprocess function
2017-06-22 13:01:09 -05:00
Winston Chang
df7397af1f Bump version 2017-06-21 14:27:03 -05:00
Winston Chang
9ba9345b04 Add snapshotPreprocess function 2017-06-21 14:27:03 -05:00
Barbara Borges Ribeiro
9fc5758ae0 Triggers a new shiny:outputinvalidated event (#1758)
* trigger a new `shiny:invalidated` event when an output gets invalidated, at the same time that the `recalculating` CSS class is added (fixes #1688)

* add attribution to @andrewsali

* change event name from 'shiny:invalidated' to 'shiny:outputinvalidated'

* add binding and name to the new event 'shiny:outputinvalidated'
2017-06-21 12:28:51 -05:00
Winston Chang
25298a6182 In test mode, send message to client even when no outputs change (#1747)
* In test mode, send message to client even when no outputs change

* Update NEWS.md
2017-06-20 13:50:28 -05:00
Winston Chang
246da1bff6 Grunt 2017-06-16 13:48:38 -05:00
Carl Ganz
8b5d12b958 Add placeholder parameter to updateTextInput (#1742)
* add placeholder parameter

* add js placeholder code

* roxygenize

* grunt

* fix updateCheckBoxInput not to use placeholder

* simply roxygen

* add NEWS

* revert grunt
2017-06-15 22:00:39 -05:00
Alan Dipert
3817370d4e fileInput JS: Allow uploading the same file. (#1719)
* tools README: notes about entr + grunt

* fileInput JS: Allow uploading the same file. Fixes #1508

* Grunt

* Added note to NEWS.

* tools README: add Linux section, fix formatting
2017-06-15 15:09:37 -05:00
Alan Dipert
c29846a9da fileInput: Preserve extension of files uploaded from IE9 (#1717)
* fileInput: IE addendum to #1706

- Attempt to preserve the extension of files uploaded from IE9.

* maybeMoveIEUpload: Fix if spacing
2017-06-15 13:47:21 -05:00
Winston Chang
2158f906a7 Merge pull request #1736 from rstudio/wch-fix-unbind
Fix condition for calling exports.unbindAll()
2017-06-15 13:05:16 -05:00
Winston Chang
008dd280d6 Grunt 2017-06-08 17:03:21 -07:00
Winston Chang
fb99db011c Fix condition for calling exports.unbindAll(). (Correction to #1449) 2017-06-08 17:02:56 -07:00
Joe Cheng
c0fbd9cb3c Merge pull request #1732 from rstudio/barbara/mods
Fixed #1546: make it possible to write into a module's session$userData non-hackily
2017-06-07 22:45:47 -07:00
Barbara Borges Ribeiro
fb79b18002 More descriptive NEWS item and added an explanatory comment to the code 2017-06-07 13:28:51 -07:00
Barbara Borges Ribeiro
3841f22108 Fixed #1546: make it possible (without any hacks) to write arbitrary data into a module's session$userData 2017-06-07 12:11:05 -07:00
Winston Chang
379d523ac5 Add better error messages for errors parsing and evaluating JS code (#1727)
* Add better error messages for errors parsing and evaluating JS code

* Grunt
2017-06-02 14:31:06 -05:00
Winston Chang
07ec7f8c13 Update Rproj for new version of RStudio IDE 2017-06-02 13:31:33 -05:00
Alan Dipert
d0f29cc7a2 fileInput: If possible, retain uploaded file extensions on the server. (#1706) 2017-05-26 11:16:02 -05:00
Joe Cheng
0e23a487f7 Merge pull request #1713 from rstudio/jjallaire-contributing-links
Update links in CONTRIBUTING.md
2017-05-23 14:05:43 -07:00
JJ Allaire
ac10f7c426 Update links in CONTRIBUTING.md
Update the links to contributor agreements to reflect new versions that use my current email rather than rstudio.org based one.

I've made the same change in the rstudio and rmarkdown repos, we should make it in other repos that have a contributor agreement as well.
2017-05-23 16:38:02 -04:00
Joe Cheng
852c00009e Merge pull request #1712 from rstudio/wch-fix-reactiveval
Give each ReactiveVal separate dependents
2017-05-22 11:15:35 -07:00
Winston Chang
b365798e66 Add tests for ReactiveVal independence 2017-05-22 10:35:01 -05:00
Winston Chang
66a6097a49 Give each ReactiveVal separate dependents. Fixes #1710 2017-05-22 10:34:27 -05:00
Winston Chang
0e529d3d92 Fix partial arg match. Closes #1701 2017-05-10 10:08:05 -05:00
Winston Chang
06c75dd656 Bump version to 1.0.3.9000 2017-04-28 09:45:17 -05:00
Winston Chang
69c32d4d90 Bump version to 1.0.3 2017-04-25 15:33:10 -05:00
Winston Chang
36ffebd975 Workaround for NOTE about objects in yet-unreleased version of ggplot2 2017-04-25 15:33:10 -05:00
Winston Chang
deb56539fb Better reactivePoll example. Closes #1678 2017-04-25 10:48:29 -05:00
Winston Chang
af8d099b9f Don't call body(NULL). Fixes #1676 2017-04-24 13:42:22 -05:00
Winston Chang
eed869d321 Make fileInput progress bar change color on error (#1673)
* Make fileInput progress bar change color on error. Fixes #1672

* Grunt

* Update NEWS
2017-04-21 11:33:14 -05:00
Winston Chang
f8f2acf6c3 Bump version to 1.0.2.9000 2017-04-18 16:38:14 -05:00
Winston Chang
7be9f74827 Merge tag 'v1.0.2'
Shiny 1.0.2 on CRAN
2017-04-18 16:36:44 -05:00
Barbara Borges Ribeiro
ed77982330 Merge pull request #1670 from rstudio/joe/prebuilt
pre-built => prebuilt
2017-04-18 19:58:32 +01:00
Joe Cheng
e1b47eca90 pre-built => prebuilt 2017-04-18 11:09:45 -07:00
Winston Chang
bfa0b2d2bc Bump version to 1.0.2 and update NEWS 2017-04-13 14:13:41 -05:00
Winston Chang
d67783edbd Fix typo 2017-04-13 14:11:15 -05:00
Joe Cheng
77712b6664 Use RStudio replacement for deprecated MathJax CDN (#1664)
* Use RStudio replacement for deprecated MathJax CDN

* Add link to PR
2017-04-12 14:41:21 -05:00
Winston Chang
1633e7faa6 Fix Bootstrap URL. Closes #1662 2017-04-10 10:01:42 -05:00
Joe Cheng
2dc5ee5862 Merge pull request #1661 from rstudio/joe/bugfix/showcase-code-margin
Fix #1654: Empty space below showcase code
2017-04-07 17:39:01 -07:00
Joe Cheng
bbaea23eea Fix #1654: Empty space below showcase code 2017-04-07 17:37:54 -07:00
Barbara Borges Ribeiro
d112ac7eef fix documentation (worng/misleading code example) 2017-04-05 17:58:39 -05:00
Barbara Borges Ribeiro
cf21e987f2 Add shiny:sessionInit event (#1568)
* added a shiny:sessionInit JS event that is triggered at the end of the session's initialize method

* new entry

* update NEWS

* correct version number in NEWS.md

* fix typo
2017-04-05 10:50:42 -05:00
Barbara Borges Ribeiro
dae11765bc allow the choices argument in checkboxGroupInput() to be NULL (#1652)
* allow the `choices` argument in `checkboxGroupInput()` to be `NULL` or `c()` to keep backward compatibility with Shiny < 1.0.1 (fixes #1649)

* use vapply

* added one more test; reimplemented logic for checking if choice args are null
2017-04-05 10:12:44 -05:00
Barbara Borges Ribeiro
df30a3c7f4 PR: Add CC-BY-SA-4.0 license to showcase 2017-04-03 18:24:28 +01:00
Joe Cheng
aaa4600597 Bump version number to 1.0.1.9000 2017-04-03 10:22:08 -07:00
Joe Cheng
ba1730d26b Add CC-BY-SA-4.0 license to showcase 2017-04-03 10:18:04 -07:00
Barbara Borges Ribeiro
d1b5c812f7 re-run grunt to update version number embedded in shiny.min.js 2017-03-31 16:49:11 +01:00
Barbara Borges Ribeiro
5bfe6d1c84 bump version numbers in DESCRIPTION and NEWS 2017-03-31 16:48:13 +01:00
Winston Chang
9804a794fd Merge pull request #1641 from rstudio/fix-plot-rounding
Round brush coordinates
2017-03-31 10:46:44 -05:00
Winston Chang
0344645208 Grunt 2017-03-31 10:42:44 -05:00
Winston Chang
f56ad6e787 Update NEWS 2017-03-31 10:42:43 -05:00
Winston Chang
7492db592b Round brush coordinates to 14 digits. Fixes #1634 2017-03-31 10:42:43 -05:00
Winston Chang
2e80ecf8a7 Rebuild ion.rangeSlider.min.js 2017-03-30 15:48:47 -05:00
Joe Cheng
6993551a44 Fix #1637: Outputs stay faded on MS Edge (#1640) 2017-03-30 20:25:27 +01:00
Joe Cheng
9bff15adfe Fix #1632: Showcase mode comes up almost blank in IE9 & 11 (#1633)
If the width is made very wide in showcase mode with side-by-side
arrangement, the app shrinks to almost nothing. For some reason the
zoom CSS property (which we set using jQuery.animate) is set to
"1%" instead of "1".

Numbers and percentages are equally valid here, and the issue goes
away if we use percentage.
2017-03-29 10:16:17 -05:00
Winston Chang
0c24da2358 Stop propagation of mouse events on slider (#1631)
see (https://github.com/rstudio/shiny/issues/711)
2017-03-28 20:38:46 +01:00
Barbara Borges Ribeiro
4ee4adb43d doc changes 2017-03-27 21:12:46 +01:00
Joe Cheng
e33b028348 Merge pull request #1628 from rstudio/wch-rm-object-assign
Remove babel-polyfill
2017-03-27 13:07:47 -07:00
Winston Chang
384d9c1841 Grunt 2017-03-27 15:02:16 -05:00
Winston Chang
f78fcd6b5f Remove need for babel-polyfill 2017-03-27 15:02:03 -05:00
Barbara Borges Ribeiro
711a72989b Update NEWS.md 2017-03-27 17:53:59 +01:00
Barbara Borges Ribeiro
d62a2fc1d5 Allow arbitrary UI code in the choiceNames for radio buttons and checkbox group input (#1521) 2017-03-27 16:51:44 +01:00
Barbara Borges Ribeiro
f33f712a3a fix typo 2017-03-27 10:00:47 +01:00
Joe Cheng
3315b3310b Merge pull request #1614 from rstudio/joe/feature/reactiveVal
Add reactiveVal() for single reactive value
2017-03-24 13:08:47 -07:00
Joe Cheng
c7134b16ed Add link to PR for reactiveVal feature 2017-03-24 13:08:09 -07:00
Winston Chang
f36f710661 Make sure reactiveTimer gets session at creation time. Fixes #1621 2017-03-24 13:47:25 -05:00
Joe Cheng
00ab8681c7 Merge pull request #1619 from rstudio/wch-fileinput
Make fileInput text customizable. Closes #1617
2017-03-23 17:16:32 -07:00
Winston Chang
4137bbac94 NEWS 2017-03-23 14:33:22 -05:00
Winston Chang
750b2ad599 Make fileInput text customizable. Closes #1617 2017-03-23 14:31:31 -05:00
Joe Cheng
511c833fbb More code review feedback 2017-03-23 10:29:29 -07:00
Joe Cheng
29063a0c07 Code review feedback 2017-03-23 10:24:06 -07:00
Barbara Borges Ribeiro
67909b3557 updated tools/README.md (#1616) 2017-03-23 10:07:41 -05:00
Joe Cheng
102c12d36c Add NEWS item 2017-03-22 16:12:07 -07:00
Joe Cheng
dc51651665 Add S3 generics for format/print; freezeReactiveVal
Also changed the classes of reactive expressions and reactiveVal
from "reactive" and "reactiveVal" to c("reactiveExpr", "reactive")
and c("reactiveVal", "reactive")
2017-03-22 11:29:22 -07:00
Joe Cheng
8b563d6d5f Fix regex for old versions of R 2017-03-22 10:37:16 -07:00
Joe Cheng
eb8b88027e Automatic labelling of reactiveVals 2017-03-22 09:47:08 -07:00
Joe Cheng
a5b7f307ed Add reactiveVal() for single reactive value 2017-03-21 16:38:32 -07:00
Winston Chang
45fca425aa Change NS() to return a vectorized function (#1613)
* Change NS() to return a vectorized function

* Update NEWS

* Use vectorized ns()

* Use correct separator
2017-03-21 15:57:38 -05:00
Winston Chang
a0bd9b5fd7 Redocument with Roxygen 6.0.1 2017-03-21 14:02:29 -05:00
Winston Chang
c12e24e3e3 Properly register bookmark excludes for modules. Fixes #1598 (#1599)
* Scopes: properly register bookmark excludes. Fixes #1598

* Update NEWS
2017-03-21 13:56:08 -05:00
Winston Chang
d147c5a153 Don't use data-drag-interval for non-range sliders. Fixes #1605 (#1610)
* Don't use data-drag-interval for non-range sliders. Fixes #1605

* Update NEWS
2017-03-16 15:49:46 -05:00
Winston Chang
7a833456d9 Use consistent value caching format 2017-03-10 12:03:24 -06:00
Winston Chang
306f33dfc4 Fix value access 2017-03-09 16:16:16 -06:00
Winston Chang
a2745a4060 Grunt 2017-03-03 15:28:47 -06:00
Winston Chang
46b68c7b2a Bump version to 1.0.0.9001 2017-03-03 15:28:47 -06:00
Winston Chang
4264760113 Add binding and el fields to shiny:inputchanged event (#1596)
* Remove unused 'immediate' arguments

* Add opts argument to setInput methods

* Extract input values without opts

* Consistent interface for setting initial values

* Update NEWS

* Add binding and el when fileInputBinding triggers shiny:inputchanged

* Revert "Consistent interface for setting initial values"

This reverts commit 12c0b6e72a.

* Move InputDeferDecorater function

The new placement properly reflects the decorator stack

* Fix indentation

* bindInputs: make sure value is set immediately

* Only use opts where necessary in input decorators

* Properly send initial values

* Move initial value of .clientdata_allowDataUriScheme to better place

* Fix indentation

* Add InputValidateDecorator

* Better variable name

* Add function for default input options

* Simplify code
2017-03-03 15:27:32 -06:00
Winston Chang
42dedbbd9a Simplify user value check 2017-03-02 13:30:47 -06:00
Winston Chang
ea99bfdb16 Update NEWS 2017-02-28 10:48:48 -06:00
Winston Chang
2ccb934338 Merge pull request #1592 from akersting/master
fix: dateRangeInput did not respect weekstart arg
2017-02-28 10:46:35 -06:00
Winston Chang
367027cfbc Merge branch 'wch/redundant-setinput' 2017-02-28 09:23:17 -06:00
Winston Chang
c4ebd3b6d5 Merge pull request #1594 from rstudio/wch/fix-dynamic-input
Make sure input deduplication respects inputType. Closes #162
2017-02-28 09:19:41 -06:00
Winston Chang
5f8cd82a09 Update NEWS 2017-02-24 19:43:55 -06:00
Winston Chang
0ef15fa662 Remove redundant calls to setInput 2017-02-24 19:43:55 -06:00
Winston Chang
c05452af91 Update NEWS 2017-02-24 15:16:12 -06:00
Winston Chang
4c8bafcf9a Make sure input deduplication respects inputType. Closes #162 2017-02-24 15:11:18 -06:00
Andreas Kersting
034f30a49a fix: dateRangeInput did not respect weekstart arg 2017-02-23 07:38:10 +01:00
Winston Chang
0f13075e17 NEWS edits 2017-02-10 14:28:15 -06:00
Winston Chang
ad274a5981 Grunt 2017-02-10 14:26:48 -06:00
Winston Chang
fdbcbaec8a Merge pull request #1579 from albertosantini/fix-1577
Improve escapeHTML
2017-02-10 14:26:22 -06:00
Alberto Santini
9c09072ee6 Update NEWS 2017-02-10 20:16:57 +01:00
Alberto Santini
0a4ca56da9 Improve escapeHTML
Replacing one char after another is not a best practice, due to the order dependency of replacing, xss risk and performance.

Fix #1577
2017-02-10 18:15:07 +01:00
Winston Chang
2b494398f2 Merge pull request #1578 from rstudio/wch/ggplot-api
Add plot interaction support for ggplot2 api
2017-02-10 10:56:59 -06:00
Winston Chang
95585c2264 Update NEWS 2017-02-10 10:42:27 -06:00
Winston Chang
92f9f0da9e Restructure code for clarity 2017-02-09 11:23:13 -06:00
Winston Chang
fe943b5e95 Update plot interaction for ggplot2 > 2.2.1 2017-02-09 11:01:47 -06:00
Winston Chang
3479a4661a Prepare code for ggplot2 api 2017-02-02 11:12:22 -06:00
Winston Chang
7ba438cf7c Add entries to staticdocs index 2017-02-01 11:41:18 -06:00
Winston Chang
c761e9fba0 NEWS formatting fixes 2017-02-01 11:37:31 -06:00
Winston Chang
deae31ea4a Merge pull request #1570 from rstudio/wch/simplify-fileupload
Remove shiny:fileuploaded JS event
2017-02-01 11:34:01 -06:00
Winston Chang
547355a163 Grunt 2017-02-01 11:29:21 -06:00
Winston Chang
9be4cb132c NEWS 2017-02-01 11:29:21 -06:00
Winston Chang
3e25c9f3f4 Remove shiny:fileuploaded event 2017-02-01 11:17:08 -06:00
Barbara Borges Ribeiro
220c7e9139 decode URLs in staticHandler func - fixes #1565 (via #1566) 2017-02-01 06:27:11 +00:00
Winston Chang
79a085a9be Merge pull request #1547 from rstudio/wch/fix-progress
Fix progress bar
2017-01-31 20:38:38 -06:00
Winston Chang
b505c5a9d3 Grunt 2017-01-31 20:38:16 -06:00
Winston Chang
03ba660ea1 Update NEWS 2017-01-31 20:37:39 -06:00
Winston Chang
5aeb361f6d Set starting value to NULL 2017-01-31 20:36:28 -06:00
Winston Chang
0e519a4e97 Progress: store value as raw value instead of normalized 2017-01-31 20:36:28 -06:00
Winston Chang
4feee00d34 NULL value no longer makes progress bar go to 100%. Closes #1472
This also removes the documentation which said that using NULL would cause the
progress bar to be hidden.
2017-01-31 20:36:28 -06:00
Winston Chang
ef5e4cdc0a Merge pull request #1559 from rstudio/wch/download-event
Add shiny:filedownload Javascript event
2017-01-31 20:29:25 -06:00
Winston Chang
67c599f50b Update NEWS 2017-01-31 20:27:20 -06:00
Winston Chang
5af9b61357 Grunt 2017-01-31 20:25:00 -06:00
Winston Chang
1d6771b4ed Unexport markOutputAttrs and add snapshotExclude function 2017-01-31 20:24:52 -06:00
Winston Chang
c55dc0a58e Add ability to exclude outputs from snapshots 2017-01-31 20:23:34 -06:00
Winston Chang
c525d55db8 Add shiny:filedownload JS event 2017-01-31 20:23:34 -06:00
Winston Chang
408f66ef80 Merge pull request #1541 from rstudio/wch/file-input-event
Make fileInput trigger shiny:inputchanged.
2017-01-31 16:29:44 -06:00
Winston Chang
7f73a047a4 Grunt 2017-01-31 16:27:50 -06:00
Winston Chang
015bc98d60 Trigger inputchanged event when fileupload is completed 2017-01-31 16:27:16 -06:00
Winston Chang
5cd9ba609a Make fileInput trigger shiny:inputchanged. Closes #1511 2017-01-31 16:27:16 -06:00
Winston Chang
c8ed6544db Fix documentation link. Closes #1567 2017-01-31 11:40:24 -06:00
Winston Chang
1162113d3b Re-document 2017-01-30 13:47:20 -06:00
Winston Chang
1612503e7b Update selectize URLs. Closes #1564 2017-01-30 13:46:12 -06:00
Joe Cheng
34ba85df3b Merge pull request #1563 from rstudio/barbara/userInfo
Barbara/user info
2017-01-30 09:55:56 -08:00
Barbara Borges Ribeiro
8206e7d2a2 delete old message handler 2017-01-27 20:42:04 +00:00
Barbara Borges Ribeiro
3e29672c70 news item 2017-01-27 20:40:07 +00:00
Barbara Borges Ribeiro
f67aaafe4f some adjustments after feedback 2017-01-27 20:39:18 +00:00
Barbara Borges Ribeiro
ed704afc07 remove console.log and re-grunt 2017-01-27 20:38:17 +00:00
Barbara Borges Ribeiro
bbbfacb4b2 grunt 2017-01-27 20:37:58 +00:00
Barbara Borges Ribeiro
cf16d2e52d listify 2017-01-27 20:37:32 +00:00
Barbara Borges Ribeiro
6268e6e1c9 will be removed!! only for testing purposes 2017-01-27 20:36:37 +00:00
Barbara Borges Ribeiro
99b8e5b303 stuff 2017-01-27 20:36:37 +00:00
Winston Chang
73446af330 Convert tabs to spaces in examples 2017-01-26 15:06:15 -06:00
Barbara Borges Ribeiro
a0b917a207 support pushState for pseudo-nav
see the documentation for details (`?updateQueryString` and `?getQueryString`)
2017-01-25 23:45:26 +00:00
Winston Chang
53ec7edd06 Another typo 2017-01-17 12:02:39 -05:00
Winston Chang
ff804c0ff8 Typo 2017-01-17 12:01:51 -05:00
Winston Chang
9d69ff01b3 Update ion.rangeSlider to 2.1.6 (#1540)
* Update ion.rangeSlider to 2.1.6

* Simplify code when slider separator is ""

* Add links to NEWS
2017-01-17 12:00:47 -05:00
Winston Chang
61831f530f Merge pull request #1525 from rstudio/wch/ggplot-coord-fixed
Add plot interaction support for coord_fixed
2017-01-16 13:01:01 -05:00
Winston Chang
6065db1d24 Update NEWS 2017-01-16 13:00:41 -05:00
Winston Chang
270b8415e8 Add plot interaction support for coord_fixed. Closes #1121 2017-01-16 12:58:58 -05:00
Winston Chang
1987331a70 Bump version to 1.0.0.9000 2017-01-16 12:55:36 -05:00
Winston Chang
ab85216b96 Merge tag 'v1.0.0' 2017-01-13 13:36:23 -05:00
Winston Chang
b5cb78c77e Update URL 2017-01-10 10:13:06 -06:00
Winston Chang
e75c99672d Update NEWS 2017-01-09 12:38:48 -06:00
Winston Chang
7faba72ebe Fix URL 2017-01-09 12:38:48 -06:00
Winston Chang
cbe8fc1bdf Bump version to 1.0.0 2017-01-09 12:38:48 -06:00
Winston Chang
f66a7660e2 Merge pull request #1529 from rstudio/feature/res-path-numeric-prefix
Relax naming requirements for addResourcePath
2017-01-09 12:28:07 -06:00
Winston Chang
5f3159a203 Add link to PR in NEWS 2017-01-09 12:25:32 -06:00
JJ Allaire
76aeda4436 refine regex 2017-01-09 12:32:12 -05:00
JJ Allaire
fa791cd28c Relax naming requirements for addResourcePath()
First character no longer needs to be a letter. See https://github.com/rstudio/tutor/issues/4 for discussion.
2017-01-09 11:04:51 -05:00
Winston Chang
d836c68ee5 Grunt 2017-01-03 16:17:48 -06:00
Winston Chang
519d90f0a7 Update NEWS 2017-01-03 16:17:28 -06:00
Winston Chang
26400be6f7 Pressing Esc in a modal in a gadget only closes the modal. Closes #1453 (#1523) 2017-01-03 17:14:31 -05:00
Winston Chang
92ba7e9d54 Update yarn install instructions 2017-01-03 14:29:43 -06:00
Winston Chang
25eafe1e69 NEWS: more info on testing 2017-01-03 14:16:55 -06:00
Winston Chang
118a9ca861 Update NEWS 2017-01-03 12:54:06 -06:00
Winston Chang
174a1fe834 Update to font-awesome 4.7.0 2017-01-03 12:47:23 -06:00
Winston Chang
1e0f3f40a9 Replace structure(NULL) with structure(list())
In R-devel 71841, structure(NULL) was deprecated.
2016-12-28 16:43:29 -06:00
Barbara Borges Ribeiro
19623694f5 Added skipFirst arg to observeEvent (#1494)
* added skipFirs arg to observeEvent

* create getCurrentObserver() function

* better NEWS entry

* made code more consistent

* implemented `once` param to `observeEvent`; extensive documentation for `getCurrentObserver`

* implement dig param to `getCurrentObserver`

* fix bug that was causing unit tests to fail

* take two

* git commit

* removed function getCurrentObserver

* delete .globals$currentObserver variable

* update docs

* typo

* remove dupes in index.r (bah humbug)

* rerun devtools::document
2016-12-19 15:51:19 -08:00
Winston Chang
55a16043e1 Merge pull request #1510 from rstudio/joe/feature/debounce
Add reactive debounce and throttle functions
2016-12-16 11:10:02 -06:00
Winston Chang
29943b7edd Merge pull request #1482 from rstudio/barbara/runapp
Fixes #1358: more informative error message when calling runApp inside of an app's app.R
2016-12-16 10:15:35 -06:00
Joe Cheng
a1e2af9533 Add debounce/throttle tests, priority arg 2016-12-15 14:52:07 -08:00
Barbara Borges Ribeiro
c350e2a668 Fixes #1358: more informative error message when calling runApp inside of an app's app.R (or inside ui.R or server.R). 2016-12-15 21:50:39 +00:00
Joe Cheng
e0868ba2ab Fix #1013: flushReact should be called after app loads (#1503)
* Fix #1013: flushReact should be called after app loads

* Add link to pull request
2016-12-15 13:16:18 -06:00
Joe Cheng
bcefd1fbd8 Fix #117: Reactive expressions hold on to memory for longer than necessary (#1504)
* Fix #117: Reactive expressions hold on to memory for longer than necessary

* Fix broken link

* Add link to pull request
2016-12-15 13:15:00 -06:00
Joe Cheng
f5fbad0abf Add link to pull request 2016-12-15 11:14:48 -08:00
Joe Cheng
95b1a197be Remove unnecessary namespace 2016-12-15 11:11:29 -08:00
Joe Cheng
39169a36f5 Wording tweaks 2016-12-15 11:10:28 -08:00
Joe Cheng
3b1a409f07 Remove unnecessary link qualifier 2016-12-15 11:01:35 -08:00
Joe Cheng
accd70d4b4 Add session$userData feature (#1513)
* Add session$userData

* Tweak wording of NEWS

* Fix broken links
2016-12-15 12:50:20 -06:00
Winston Chang
3c7f4b760f Merge pull request #1514 from rstudio/joe/bugfix/fix-broken-links
Fix unqualified links to other packages
2016-12-15 12:42:19 -06:00
Joe Cheng
f7d7ccfd2c Fix unqualified links to other packages
R-devel warns on this now, causes Travis to fail
2016-12-15 10:35:46 -08:00
Joe Cheng
de98a03887 Add limitations section to debounce/throttle docs 2016-12-13 17:48:36 -08:00
Joe Cheng
0e11c240cb Add magrittr as Suggests because of ?debounce example 2016-12-13 17:29:29 -08:00
Joe Cheng
c0a298e484 Add reactive debounce and throttle functions 2016-12-13 17:22:12 -08:00
Winston Chang
907b9a9862 Merge pull request #1480 from rstudio/barbara/verbatim
Closes #1357: verbatimTextOutput should optionally be hidden if no content
2016-12-07 10:13:04 -06:00
Barbara Borges Ribeiro
8d70d91cf4 fix #1487: better error handling for insertUI when selector does not match anything in DOM (do console log) 2016-12-07 05:10:43 +00:00
Barbara Borges Ribeiro
6fb86859ce use past tense in all NEWS.md entries 2016-12-07 04:55:08 +00:00
Barbara Borges Ribeiro
fe733b319f Fixes #969: allow navbarPage's fluid param to control both containers 2016-12-07 00:22:33 +00:00
Barbara Borges Ribeiro
08b58f3055 allow navbarPage's fluid param to control both the content *and* the header containers 2016-12-07 00:21:49 +00:00
Barbara Borges Ribeiro
9f6659f526 added a new arg (placeholder = FALSE) to verbatimTextOutput() so that by default it doesn't show up when it is empty; improved the documentation example 2016-12-07 00:02:40 +00:00
Barbara Borges Ribeiro
d28397df93 Fix #1359: shinyApp options argument ignored when passed to runApp (#1483) 2016-12-06 20:52:19 +00:00
Barbara Borges Ribeiro
2e1c37146b Add ... arg to downloadButton (merge #1492)
Add ... arg to downloadButton
2016-12-05 15:37:02 +00:00
Barbara Borges Ribeiro
903adc8f97 Added ability to pass arguments to the a tag function called inside downloadButton() and downloadLink(). Closes #986. 2016-12-05 15:35:31 +00:00
Winston Chang
fc7f454382 Merge pull request #1449 from rstudio/barbara/bugfix/insert-ui
Fix #1438: `unbindAll()` should not be called when inserting content with `insertUI()`
2016-12-01 15:45:23 -06:00
Winston Chang
ef35fc63a1 Grunt 2016-12-01 15:41:51 -06:00
Barbara Borges Ribeiro
52a193b183 unbindAll() should not be called when inserting content with insertUI() 2016-12-01 15:40:17 -06:00
Winston Chang
dad401a6ec Merge pull request #1464 from rstudio/testmode-inject-js
Add support for injecting JS code when in test mode
2016-12-01 14:52:12 -06:00
Winston Chang
ec3f8118db Grunt 2016-12-01 10:47:02 -06:00
Winston Chang
cfc0194c00 Sort input, output, export by name 2016-12-01 10:46:46 -06:00
Winston Chang
dd28f52301 Add sortByName function 2016-12-01 10:46:46 -06:00
Winston Chang
9dcbd532e6 Add getTestSnapshotBaseUrl function 2016-12-01 10:46:46 -06:00
Winston Chang
16b4a2cad2 Rename testEndpointUrl to testSnapshotUrl 2016-12-01 10:46:46 -06:00
Winston Chang
bd9d8a035a Change arguments from plural to singular 2016-12-01 10:46:46 -06:00
Winston Chang
d55ffb0212 Change default snapshot format to JSON 2016-12-01 10:46:46 -06:00
Winston Chang
e76ddfd005 Emit message when running in test mode 2016-12-01 10:46:46 -06:00
Winston Chang
59145a3b40 Add testmode as an option to runApp 2016-12-01 10:46:46 -06:00
Winston Chang
c993f5343b Bump version to 0.14.2.9001 2016-12-01 10:46:46 -06:00
Winston Chang
b62acec5ee Use singular form of input, export, and output 2016-12-01 10:46:46 -06:00
Winston Chang
b34ab9cdd5 Add shiny:fileuploaded JS event 2016-12-01 10:46:46 -06:00
Winston Chang
e0a8ab852e Update NEWS 2016-12-01 10:46:46 -06:00
Winston Chang
bd5ebd0e41 Remove token check 2016-12-01 10:46:46 -06:00
Winston Chang
661e21d25b Safer method for injecting code in test mode 2016-12-01 10:46:46 -06:00
Winston Chang
dc69a2bc94 Make sure test values are named vectors 2016-12-01 10:46:46 -06:00
Winston Chang
e6fec6b27d Rename variable 2016-12-01 10:46:46 -06:00
Winston Chang
27b92f9838 Add args to getTestEndpointUrl 2016-12-01 10:46:46 -06:00
Winston Chang
3446def4dd Basic code injection support 2016-12-01 10:46:46 -06:00
Barbara Borges Ribeiro
2700206715 Improve documentation for submitButton and change 07_widgets example to use an action button (#1475)
* update 07_widgets example

* improved documentation for submitButton (including a warnign section and an full-app example)

* typo

* update documentation based on Winton's feedback
2016-11-28 13:19:40 -06:00
Winston Chang
fdfc6f70f3 Merge branch 'barbara/contributing' 2016-11-22 14:56:25 -06:00
Winston Chang
065c288edb Edits to contribution guidelines 2016-11-22 14:56:12 -06:00
Barbara Borges Ribeiro
3121d2c23e mention support for the optgroup tag in the documention for selectInput (specifically in the choices arg). Added example app too. 2016-11-22 11:28:35 -06:00
Barbara Borges Ribeiro
7cd3bb524c add download attribute to the a tag that generates downloadButoon and downloadLink 2016-11-18 21:00:28 -08:00
Barbara Borges Ribeiro
6b8cc97779 drafted new contribution guidelines 2016-11-19 02:22:16 +00:00
Winston Chang
b7112a1edd Add link to NEWS 2016-11-10 15:26:46 -06:00
Jonathan
28965b7356 Render HTML dependency <meta> tag contents correctly (#1463)
* render HTML dependency <meta> tag contents correctly

* use direct address rather than loop; update NEWS
2016-11-10 15:10:18 -06:00
Dean Attali
bd3aa28416 fix typo in dateInput documentation (#1454) 2016-11-02 09:53:40 -05:00
Winston Chang
9fed4ce24c Bump version to 0.14.2.9000 2016-11-01 15:40:04 -05:00
Winston Chang
90383e30dd Bump version to 0.14.2 2016-10-31 10:19:40 -05:00
Winston Chang
13f184e957 Remove NEWS entry for change that was reverted 2016-10-31 10:17:51 -05:00
Winston Chang
a7a2c6d7ff Add list2env wrapper, for R <3.2.0 (#1446)
* Add list2env wrapper, for R <3.2.0

* Update NEWS
2016-10-28 13:56:52 -05:00
Winston Chang
d1bf39d0ac Add exportTestValues function (#1436)
* Add onTestSnapshot function

* Add shiny.testing option

* Add entry to staticdocs index

* Bump version to 0.14.1.9002 and update NEWS

* Document params for onTestSnapshot

* Add session$enableTestEndpoint() method

* Un-export applyInputHandlers

* Grunt

* Provide inputs, outputs, and snapshot at test endpoint

* Remove non-working example

* Fix var name in documentation

* Rename shiny.testing to shiny.testmode

* Rename onTestSnapshot to exportTestValues and add example

* Add session$getTestEndpointUrl

* Grunt

* Add module support to exportTestValues

* Test endpoint allows specifying specific values

* session$getTestEndpointUrl: add arguments for choosing which values to return
2016-10-27 21:08:34 -05:00
Joe Cheng
7dff6b8415 Merge pull request #1387 from sipemu/master
options render for updateSelectizeInput did not worked in modules
2016-10-27 11:11:16 -07:00
Dean Attali
656e019829 allow overriding a JS custom message handler; fixes #1419 (#1445)
* allow overriding existing custom JS message handlers

* when a JS handler gets re-defined, only use the most recent one

* JS handler overwrite: changes re winston's comments

* overwrite JS handler: add NEWS item

* fix wrong URL in NEWS
2016-10-27 13:07:34 -05:00
Winston Chang
2133b0f498 Use === in Javascript 2016-10-26 21:01:36 -05:00
Winston Chang
bc4dcee2b1 allow shiny.trace option to specify which type of messages to relay; fixes #1422 (#1428)
Squashed commit of the following:

commit bdc4080032ff6b5b2de0f799aa307272f3905003
Author: Dean Attali <daattali@gmail.com>
Date:   Mon Oct 17 18:18:03 2016 -0700

    add PR link to news item

commit 22c695cde2b270ba8ec37d4862ad1f30de76ce68
Author: Dean Attali <daattali@gmail.com>
Date:   Mon Oct 17 15:01:24 2016 -0700

    update NEWS for #1422 fix

commit e669548c13f84f0929e4131c641a8333e08baa26
Author: Dean Attali <daattali@gmail.com>
Date:   Sat Oct 15 12:45:49 2016 -0700

    allow shiny.trace option to specify which type of messages to relay; fixes #1422
2016-10-26 12:24:00 -05:00
Winston Chang
0e8cf95739 Pass shinysession to applyInputHandlers
This fixes a problem where input handlers that require a session object
would throw errors.
2016-10-25 10:27:03 -05:00
Joe Cheng
e133290c57 Fix #1399: Duplicate binding error with insertUI and nested uiOutput (#1402)
* Fix #1399: Duplicate binding error with insertUI and nested uiOutput

* Update NEWS.md
2016-10-18 20:22:02 -05:00
shrektan
1429b0677e fix a typo: option() -> options() 2016-10-18 14:56:38 -05:00
Barbara Borges Ribeiro
d03ee36647 Fixes #1427: add event delegation so that modals do not close by mistake (#1430)
* Fixes #1427: add event delegation so that modal does not close when an element inside it is triggered as hidden

* use `this === e.target` instead

* added NEWS item

* `e.target` must be equal to `$(#shiny-modal)`, not `this`
2016-10-18 14:54:27 -05:00
Winston Chang
6e5880c642 Bump version and update NEWS 2016-10-18 13:51:43 -05:00
Winston Chang
fa93cffafb Add entry to staticdocs 2016-10-18 13:51:43 -05:00
Winston Chang
ce9af0fb57 Export function that applies input handlers 2016-10-18 13:51:43 -05:00
Winston Chang
95700d8d51 Fix dategrange comment 2016-10-17 13:37:25 -05:00
Winston Chang
fb15e98519 Merge pull request #1429 from rstudio/slider-setvalue
Make sliderInputBinding.setValue update value immediately
2016-10-17 12:29:14 -05:00
Winston Chang
3054cb7971 Update NEWS 2016-10-17 12:28:36 -05:00
Winston Chang
f84587cf5a Grunt 2016-10-17 12:22:21 -05:00
Winston Chang
538f38f314 sliderInputBinding: setValue changes value immediately 2016-10-17 12:22:21 -05:00
Winston Chang
06578349c7 Document InputBinding.subscribe's callback argument 2016-10-17 12:18:12 -05:00
Winston Chang
a807476171 sliderInputBinding: rename 'updating' to 'immediate' 2016-10-17 12:13:15 -05:00
Winston Chang
7aacf9ca89 Use Yarn instead of npm (#1416) 2016-10-12 12:51:05 -05:00
Winston Chang
50dae5fb83 Remove unneeded npm package 2016-10-11 13:04:38 -05:00
Winston Chang
0853c425fe Bump version to 0.14.1.9000 in DESCRIPTION 2016-10-11 12:59:06 -05:00
Barbara Borges Ribeiro
edcc676693 add "fade" arg to modalDialog() (#1414)
* add "fade" arg to modalDialog() that can be set to FALSE to remove default modal animation

* added documentation

* reflow comments

* news item
2016-10-10 15:03:25 -05:00
Winston Chang
c8a742a121 Bump version and update NEWS 2016-10-05 09:32:36 -05:00
Winston Chang
ee14a7e15f Merge tag 'v0.14.1'
Shiny 0.14.1 on CRAN
2016-10-05 09:29:07 -05:00
Winston Chang
e1eaccf409 Fix tests for compiled code on R-devel. Closes #1404 2016-10-03 16:23:11 -05:00
Winston Chang
d2aae52868 Update NEWS 2016-09-30 15:39:31 -05:00
Winston Chang
9158fb4745 Bump version to 0.14.1 2016-09-30 15:39:31 -05:00
Winston Chang
0ff5ef5337 Remove file 2016-09-30 15:39:13 -05:00
Joe Cheng
1ace145f85 Merge pull request #1392 from rstudio/ggplot-fix
Add plot interaction support for ggplot>2.1.0
2016-09-30 12:40:30 -07:00
Winston Chang
565eb4b450 Merge pull request #1397 from rstudio/barbara/bugfix/radio
Maintain names of factors when updating radio buttons' choices
2016-09-29 14:18:24 -05:00
Barbara Borges Ribeiro
f39861c43f more comments and NEWS 2016-09-29 19:48:56 +01:00
Barbara Borges Ribeiro
72838c248f news entry 2016-09-29 19:16:46 +01:00
Barbara Borges Ribeiro
9be8765ccf more tests 2016-09-29 19:14:18 +01:00
Barbara Borges Ribeiro
48732c4393 deleted commented out lines 2016-09-29 19:14:18 +01:00
Barbara Borges Ribeiro
5bf0b7c920 a better fix 2016-09-29 19:14:18 +01:00
Barbara Borges Ribeiro
51a4580d0f maintain names of factors when updating radio buttons' choices 2016-09-29 19:14:18 +01:00
Winston Chang
266e611afa Update NEWS 2016-09-27 23:07:23 -05:00
Winston Chang
22598b693c Add more plot interaction tests 2016-09-27 23:07:23 -05:00
Winston Chang
008fe38f10 Add support for coord_flip 2016-09-27 23:07:17 -05:00
Winston Chang
24e8123240 Add plot interaction support for ggplot>2.1.0 2016-09-27 16:02:28 -05:00
Simon Müller
6054f03c0d Update update-input.R 2016-09-21 22:53:41 +02:00
Winston Chang
476f6d83e2 Remove no-longer-necessary CSS class 2016-09-19 10:22:40 -05:00
Winston Chang
ec57109f39 Merge pull request #1374 from rstudio/datepicker-noconflict
Fix datepicker conflicts
2016-09-19 09:30:22 -05:00
Winston Chang
d73488f887 Grunt 2016-09-19 09:27:28 -05:00
Winston Chang
3201380c29 Set value after min in max when updating dates 2016-09-19 09:27:28 -05:00
Winston Chang
1f04b39ae3 Rename bootstrapDP to bsDatepicker 2016-09-16 23:39:26 -05:00
Winston Chang
9e2b47027c Update NEWS 2016-09-16 23:39:26 -05:00
Winston Chang
662149a98a Update to jQuery UI 1.12.1 2016-09-16 23:39:26 -05:00
Winston Chang
fafa31589d Update NEWS 2016-09-16 23:39:26 -05:00
Winston Chang
43a5940b9e Updates to dateRangeInputBinding for new datepicker API 2016-09-16 23:39:26 -05:00
Winston Chang
33908624fd Fix off-by-one error for datepicker's setStartDate and setEndDate 2016-09-16 23:39:26 -05:00
Winston Chang
ffef8a341f Add workaround for bootstrap datepicker bug with setStartDate and setEndDate 2016-09-16 23:39:26 -05:00
Winston Chang
a48c5df844 Don't try to set min/max date when undefined 2016-09-16 23:39:26 -05:00
Winston Chang
37b6a668ab Fix off-by-one dates 2016-09-16 23:39:26 -05:00
Winston Chang
2a9a7cc897 Enable noconflict for Bootstrap Datepicker. Closes #1346 2016-09-16 23:39:26 -05:00
Winston Chang
c62e6b5734 Update to Bootstrap Datepicker 1.6.4. Closes #1218 2016-09-16 23:39:26 -05:00
Winston Chang
6ec1d0b935 grunt clean && grunt 2016-09-16 23:37:31 -05:00
Winston Chang
6c5769fdd8 Add missing files to Grunt clean 2016-09-16 23:36:57 -05:00
Winston Chang
09acc5920c Allow using no separator for sliderInput numbers. Fixes #1369 2016-09-15 12:03:25 -05:00
Winston Chang
9613c58bf8 Merge pull request #1370 from rstudio/fix-bookmark-fileinput
Fix bookmark fileinput
2016-09-13 15:38:52 -05:00
Winston Chang
147f9ac64b Remove sourcetools workaround for Travis
This is no longer necessary because the new version of sourcetools on CRAN
does not need C++11
2016-09-13 12:52:15 -05:00
Winston Chang
cc1e8961a1 Update NEWS 2016-09-13 11:24:42 -05:00
Winston Chang
3b1b2f401d Use createUniqueId for consistency 2016-09-13 11:14:29 -05:00
Winston Chang
58a87b9b61 Copy restored file to temp directory 2016-09-13 11:13:21 -05:00
Winston Chang
f09475a6b5 Better check for unsafe paths in restored file inputs 2016-09-13 11:12:16 -05:00
Winston Chang
750422d858 Mark restored file inputs with correct serializer. Closes #1368 2016-09-13 10:49:08 -05:00
Winston Chang
03d911d335 Use cache for AppVeyor 2016-09-13 10:47:00 -05:00
Winston Chang
2747c11a46 Bump version to 0.14.0.9000 2016-09-13 10:46:15 -05:00
Winston Chang
5a9fe2637f Update shiny.rstudio.com URLs in NEWS 2016-09-12 09:36:32 -05:00
Winston Chang
a5787f9988 Bump version to 0.14 2016-09-08 15:03:19 -05:00
Winston Chang
85e22bb515 Ignore revdep 2016-09-08 15:03:19 -05:00
Barbara Borges Ribeiro
5e1e90ad80 fix validation bug 2016-09-07 19:22:02 +01:00
Winston Chang
fe85421c7e Fixes for R CMD check 2016-09-06 14:43:57 -05:00
Winston Chang
38af6ce279 Merge pull request #1362 from rstudio/barbara/update-old-release-news
Barbara/update old release news
2016-09-06 11:05:24 -05:00
Barbara Borges Ribeiro
fe92f16da4 updated 0.12 section 2016-09-05 20:55:38 +01:00
Barbara Borges Ribeiro
edc4b562f2 removed unnecessary line breaks now that we switched to .md 2016-09-05 20:42:20 +01:00
Barbara Borges Ribeiro
7b6a91064c updated 0.11 section 2016-09-05 19:52:28 +01:00
Winston Chang
a32414c6fc NEWS edits 2016-09-02 21:09:39 -05:00
Winston Chang
259b4e29de NEWS improvements (#1354) 2016-09-02 16:28:08 -05:00
Winston Chang
e56f80b546 Check whether hosting environment supports bookmarking (#1360)
* Check whether hosting environment supports bookmarking

* Show notification on startup if hosting environment doesn't support saved-to-server bookmarking
2016-09-02 14:19:41 -07:00
Barbara Borges Ribeiro
1ff52c5290 Merge branch 'master' of https://github.com/rstudio/shiny 2016-09-02 00:42:26 +01:00
Barbara Borges Ribeiro
70bd249f43 make explicit link to external package 2016-09-02 00:42:14 +01:00
Winston Chang
f2f7e43579 Convert validate example to single-file app. Closes #1345 (#1347) 2016-09-01 13:08:03 -07:00
Winston Chang
c36d60fcd4 Fix reactive highlighting in showcase mode. Closes #1350 (#1351) 2016-09-01 13:07:39 -07:00
Barbara Borges Ribeiro
0950f307d1 Merge pull request #1344 from rstudio/joe/feature/root-scope
Let modules get at the root scope (undocumented for now)
2016-09-01 04:58:17 +01:00
Joe Cheng
a9b7e4a85e Let modules get at the root scope (undocumented for now) 2016-08-31 14:44:45 -07:00
Winston Chang
912a886539 updateQueryString: add note about not working in IE9. Closes #1336 (#1339) 2016-08-31 12:17:49 -07:00
Winston Chang
f7484f49e5 Fix file uploads in IE9. Closes #1332 (#1342)
* Fix file uploads in IE9. Closes #1332

* Grunt
2016-08-31 12:17:24 -07:00
Joe Cheng
9f68be1925 Merge pull request #1341 from rstudio/ie9-fix-remove-modal
Fix modal removal for IE 9
2016-08-31 12:02:43 -07:00
Joe Cheng
ef298f8d7a Merge pull request #1337 from rstudio/fix-replay-plot
Make sure displaylist is on for recording/replaying plots
2016-08-31 12:01:32 -07:00
Winston Chang
c038f0e6ee Grunt 2016-08-31 11:36:16 -05:00
Winston Chang
3c53a93447 Wrap DOM object in jQuery. Fixes #1335 2016-08-31 11:35:48 -05:00
Winston Chang
7e86e65cce Make sure displaylist is on for recording/replaying plots 2016-08-30 20:09:45 -05:00
Winston Chang
ad171d6cbb Better checks in modal example 2016-08-30 17:02:07 -05:00
Joe Cheng
76ffc20836 Merge pull request #1329 from rstudio/progress-compatibility
Add old-style rendering option to progress bars
2016-08-30 14:50:32 -07:00
Winston Chang
c4cc5b6dfc Fix renderPlot's execOnResize logic
This was found in #1331, but the real problem with that issue is that
the mclust::mclust2Dplot function has changed since we wrote the example
app.
2016-08-30 16:37:50 -05:00
Winston Chang
878c9210d3 Add shinyOption for progress.style 2016-08-30 16:15:55 -05:00
Winston Chang
35c982b367 Grunt 2016-08-29 19:48:56 -05:00
Winston Chang
9c4ff080af Update NEWS 2016-08-29 19:47:12 -05:00
Winston Chang
d32ca64a03 Add old-style rendering as an option for progress 2016-08-29 16:05:43 -05:00
Winston Chang
53b89390be Rename shiny-progress CSS class to shiny-progress-notification 2016-08-29 15:19:45 -05:00
Winston Chang
a8e09d7fe6 Add sections to NEWS and add some new items 2016-08-26 12:26:30 -05:00
Winston Chang
0c7cf20e7e Switch NEWS to Markdown 2016-08-26 11:43:38 -05:00
Winston Chang
6ebcee33c5 Add some issue numbers to NEWS 2016-08-26 11:39:20 -05:00
Winston Chang
c73544fb59 Fix misplaced NEWS items 2016-08-26 11:29:10 -05:00
Winston Chang
37c1f93bcb Merge pull request #1320 from rstudio/joe/docs/sendBinaryMessage
NEWS, doc update for sendBinaryMessage
2016-08-25 20:25:51 -05:00
Joe Cheng
95aa2e10fc NEWS, doc update for sendBinaryMessage 2016-08-25 15:48:53 -07:00
Joe Cheng
279e6e3925 Merge remote-tracking branch 'origin/daef/feature/binary-messages' 2016-08-25 13:08:29 -07:00
Joe Cheng
8a661d5ee4 Code review feedback 2016-08-25 13:04:58 -07:00
Joe Cheng
67fcb40455 Merge pull request #1313 from rstudio/bookmarking-arg
Add enableBookmarking argument to shinyApp()
2016-08-25 13:00:04 -07:00
Winston Chang
641524c80e More docs for enableBookmarking 2016-08-24 17:00:59 -05:00
Winston Chang
55802354d4 Add enableBookmarking arg to shinyApp() 2016-08-24 14:47:56 -05:00
Winston Chang
75f4f5c0bd Merge pull request #1317 from MangoTheCat/fix/updatedaterangeinteraction
Fix updateDateRangeInput interaction from #1299 & #1315
2016-08-24 13:43:55 -05:00
Gábor Csárdi
382e9dee55 Grunt 2016-08-23 22:52:41 +01:00
Gábor Csárdi
6861d4029e Fix updateDateRangeInput interaction from #1299 & #1315 2016-08-23 22:51:18 +01:00
Joe Cheng
370ef16854 Slight tweaks
- Rename arguments to type/message
- Check tag length after converting to bytes
2016-08-23 14:08:04 -07:00
Gábor Csárdi
9dbe434792 Fix updateDateRangeInput when only one of start/end updated (#1315) 2016-08-23 16:07:53 -05:00
Joe Cheng
21a0e95623 Merge commit 'd1353e8eaebc3f878fe9074919948d662caf8a89' 2016-08-23 13:58:40 -07:00
Winston Chang
57c6307479 Merge pull request #1314 from rstudio/joe/bugfix/downloadhandler-no-data
Fix #1122: Do something sensible when downloadHandler doesn't create a file
2016-08-23 15:50:39 -05:00
Winston Chang
01d8b1f468 Merge pull request #1299 from MangoTheCat/fix/resetdateinput
Allow updateDateInput to set input fields to empty
2016-08-23 15:48:25 -05:00
Joe Cheng
ef6b82a0a3 Fix #1122: Do something sensible when downloadHandler doesn't create a
file
2016-08-23 13:48:24 -07:00
Gábor Csárdi
19b7d1a7c5 Rebuild minified files 2016-08-23 21:21:35 +01:00
Gábor Csárdi
097d901191 Updates can clear date and date range inputs 2016-08-23 21:21:10 +01:00
Winston Chang
a1b5846b29 Remove extra comma 2016-08-23 10:54:37 -05:00
Winston Chang
dbdb353e69 Add updateQueryString example 2016-08-23 10:30:12 -05:00
Winston Chang
4456eac1fd Make staticdocs tests work in R CMD check 2016-08-22 21:04:19 -05:00
Winston Chang
ba3f8f432e Update staticdocs index. Closes #1293 2016-08-22 20:38:16 -05:00
Winston Chang
bab539f52c Make it possible to have multiple bookmark buttons (#1310) 2016-08-19 21:13:27 -07:00
Winston Chang
42dbb128be Fix handling of NULLs in updateDateInput 2016-08-19 14:36:29 -05:00
Winston Chang
5e4a6cb15f Fix priority of onRestore observer 2016-08-19 14:12:57 -05:00
Winston Chang
73e45ce911 Clarify observer priority documentation 2016-08-19 14:10:24 -05:00
Winston Chang
1e40043456 Add travis fix for R-devel (thanks to @jimhester) 2016-08-19 12:12:42 -05:00
Winston Chang
7f3b952ec7 Documentation updates 2016-08-19 11:53:31 -05:00
Winston Chang
82887dc1c1 Do Travis checks on multiple R versions 2016-08-19 10:16:54 -05:00
Winston Chang
71380ab37a Replace stopWithCondition with reactiveStop 2016-08-18 16:54:42 -05:00
Winston Chang
5d00804758 Add size argument to modalDialog (#1308) 2016-08-18 14:43:57 -07:00
Winston Chang
84364c65b0 Bookmark/restore actionButtons (#1304) 2016-08-18 14:42:19 -07:00
Winston Chang
1b59b705ae Fix bookmark URL when there are no input values. Fixes #1306 2016-08-17 14:00:14 -05:00
Winston Chang
bc90fe6f99 Don't error when creating tabsets without id
The bug was introduced by #1296.
2016-08-16 20:02:33 -05:00
Winston Chang
c8d6a0833e Merge pull request #1301 from daattali/patch-2
fix typo in NEWS
2016-08-16 13:57:28 -05:00
Winston Chang
d8fc7d27ec Add Dismiss button to URL modal 2016-08-16 13:00:42 -05:00
Winston Chang
1e44b19ff0 Fix typo in bookmarkButton documentation 2016-08-16 12:28:37 -05:00
Winston Chang
cc8b2cd20e Document that enableBookamrking can be called in onStart function 2016-08-16 12:22:19 -05:00
Dean Attali
057b1e294c fix typo in NEWS 2016-08-13 01:54:43 -07:00
Winston Chang
0653e790c7 Merge pull request #1298 from rstudio/handle-malformed-dates
Don't crash on malformed date input values. Closes #803
2016-08-12 21:29:00 -05:00
Winston Chang
6d72bbcb76 Don't crash on malformed date input values. Closes #803 2016-08-12 21:28:43 -05:00
Winston Chang
59e6f08455 Merge branch 'textarea' 2016-08-12 21:26:55 -05:00
Winston Chang
8fdccf50a8 Update NEWS 2016-08-12 21:26:19 -05:00
Winston Chang
1c7e11c5d9 Textarea refinements 2016-08-12 21:26:18 -05:00
Winston Chang
1756fbbb23 Merge branch 'fix-update-date' 2016-08-12 21:23:42 -05:00
Winston Chang
7bb939ab7f Restore bookmarked tabs. Fixes #1282 (#1296) 2016-08-12 18:53:44 -07:00
Nuno Agostinho
4fa0abbd5a Add arguments height, rows and cols 2016-08-12 17:19:23 -05:00
Nuno Agostinho
1e5f0266ef Fix missing parenthesis 2016-08-12 17:19:23 -05:00
Nuno Agostinho
3dee62105e Fix value assignment of text area input 2016-08-12 17:19:23 -05:00
Nuno Agostinho
680b2323d5 Update documentation relative to textarea input 2016-08-12 17:19:23 -05:00
Nuno Agostinho
562b4dad4d Add textarea input 2016-08-12 17:19:23 -05:00
Joe Cheng
079a82dfe4 executeElapsed gets stuck returning TRUE even when nothing was executed
Fixes #1278
2016-08-12 17:19:23 -05:00
Winston Chang
16f7eb43b0 Merge branch 'joe/bugfix/too-often-flush' 2016-08-12 15:24:25 -05:00
Winston Chang
4b0ed3f224 updateDateInput: better handling of malformed dates. Closes #1179 2016-08-12 14:43:44 -05:00
Winston Chang
1d453b694d Add documentation about using selected=character(0). Closes #1182 2016-08-12 14:22:54 -05:00
Barbara Borges Ribeiro
751e8c189e fixes #1093 (#1291)
* fixes #1093

* check if NULL
2016-08-11 14:29:24 -07:00
Winston Chang
183e9a3d0b Bookmarking fixes (#1281)
* Rename invalidateReactiveValue to freezeReactiveValue

* Make onFlush and onFlushed use 'once' argument

* session$flushOutput: schedule another flush if needed

* Catch all errors before they propagate to websocket

* Restore original logic for progressKeys
2016-08-11 11:58:07 -07:00
Winston Chang
5f0f4dd485 Merge pull request #1285 from rstudio/joe/bugfix/update-radio-buttons-modules
Fix #1144: RadioButtons and checkBoxGroup do not work in modules when they are updated
2016-08-11 13:17:15 -05:00
Barbara Borges Ribeiro
20f05662aa fixes #1289 2016-08-11 15:57:31 +01:00
Joe Cheng
963471b43f Fix #1144: RadioButtons and checkBoxGroup do not work in modules when they are updated
The unqualified input ID was being used to generate name attributes
on radio and checkboxes.
2016-08-10 15:52:01 -07:00
Joe Cheng
fdb52e0243 executeElapsed gets stuck returning TRUE even when nothing was executed
Fixes #1278
2016-08-10 15:10:31 -07:00
Winston Chang
d1e4483f98 Upgrade to Font-Awesome 4.6.3. Closes #1274 2016-08-10 15:40:10 -05:00
Winston Chang
b194ada316 Upgrade to Bootstrap 3.3.7 2016-08-10 15:34:51 -05:00
Winston Chang
3a25a2dcbf Upgrade to jQuery 1.12.4. Closes #1251 2016-08-10 15:24:08 -05:00
Barbara Borges Ribeiro
85e4497fbe fixes #1270; improves docs; export isTruthy() 2016-08-10 20:45:40 +01:00
Barbara Borges Ribeiro
0bfa5e7ea6 allow sticky nodes in reactlog if users drags them (#1283) 2016-08-10 20:04:37 +01:00
Barbara Borges Ribeiro
013599890f Solve updateSelectInput bug in IE 11.0 (#1277) 2016-08-09 19:08:30 +01:00
Winston Chang
519e552405 Unset shinyOptions when set to NULL 2016-08-08 13:03:07 -05:00
Winston Chang
32a4ec49f7 Bump version and update NEWS 2016-08-05 16:19:57 -05:00
Winston Chang
3223332906 Merge pull request #1209 from wch/bookmarkable-state
Bookmarkable state
2016-08-05 16:15:12 -05:00
Winston Chang
f78bd08440 Correctly handle bookmark options for global.R and app.R 2016-08-05 16:08:49 -05:00
Winston Chang
99b5f92d7a Add showBookmarkUrlModal 2016-08-03 16:07:49 -05:00
Barbara Borges Ribeiro
1cc5e84104 Barbara/error handling/port as socket (#1263)
* catch if `port` is being used incorrectly (see issue #971)

* better error msg
2016-08-03 15:50:30 -05:00
Winston Chang
8346f5ab08 Fix enableBookmarking references 2016-08-03 14:41:37 -05:00
Winston Chang
dc60a39ba9 Fix tests to be order-insensitive 2016-08-02 13:47:42 -05:00
Winston Chang
16f7872553 Grunt 2016-08-02 11:18:25 -05:00
Winston Chang
75e7c4b2ca More informative error messages 2016-08-02 11:10:17 -05:00
Barbara Borges Ribeiro
c5d5ddd7d2 Merge pull request #1267 from rstudio/barbara/remove-example-extra-line
had forgotten to run devtools::document for #1266...
2016-08-02 04:16:22 +01:00
Barbara Borges Ribeiro
98a81e3708 had forgotten to run devtools::document 2016-08-02 04:13:35 +01:00
Barbara Borges Ribeiro
ecdbdb944a Merge pull request #1266 from rstudio/barbara/remove-example-extra-line
Barbara/remove example extra line
2016-08-02 03:51:41 +01:00
Barbara Borges Ribeiro
8a2846461b removed extra line at end of example section 2016-08-02 03:40:56 +01:00
Winston Chang
6bfb9a2f57 More details in enableBookmarking man page 2016-08-01 20:46:43 -05:00
Winston Chang
85dfb2d4eb urlModal: always show Ctrl/Cmd-C copy message 2016-08-01 20:00:05 -05:00
Barbara Borges Ribeiro
8f1d0c2b8f Barbara/appveyor (#1265) 2016-08-02 01:26:48 +01:00
Winston Chang
829494c03e Make bookmark button work when there's a submitButton 2016-08-01 16:13:43 -05:00
Winston Chang
f89fade28d Rename updateLocationBar to updateQueryString 2016-08-01 16:13:25 -05:00
Winston Chang
9081b1dadd Simplify list2env 2016-08-01 14:22:23 -05:00
Winston Chang
84dac544af Make sure state ID doesn't have invalid chars 2016-08-01 14:16:50 -05:00
Winston Chang
49f1ac333d Always get appDir when shinyApp object is created 2016-08-01 14:01:16 -05:00
Winston Chang
a2b761094b Fix bookmark values tests 2016-07-29 16:07:18 -05:00
Winston Chang
54bd3d480f Fixes for R CMD check 2016-07-29 15:59:56 -05:00
Winston Chang
b281f8fa32 Merge branch 'master' into bookmarkable-state 2016-07-29 15:47:31 -05:00
Winston Chang
a3732f845e Update bookmarking documentation 2016-07-27 16:17:21 -05:00
Winston Chang
38f6d0a020 When restoring modules, only provide state$dir if present 2016-07-26 16:24:36 -05:00
Winston Chang
a0e5da758a Ensure that state$values can't be replaced 2016-07-26 16:24:02 -05:00
Winston Chang
dcbe10c1c7 Keep state$values as an environment for save and restore 2016-07-26 14:33:04 -05:00
Joe Cheng
1f823d2a1b Fix #931: Observer memory leak (#1256)
* Fix #931: Observer memory leak

Observers were being prevented from being garbage collected by
their own onReactiveDomainEnded() event handlers. This commit
fixes that by making sure that those event handlers are only
registered when autoDestroy=TRUE, and that they are unregistered
both on destruction and when autoDestroy is changed.

* Remove extraneous self$ prefixes

* Add comment explaining autoDestroyHandle
2016-07-26 11:56:47 -07:00
Winston Chang
12d0a9e11a For session_proxy, add [[ and disallow $<- and [[<- (#1262) 2016-07-26 11:21:38 -07:00
Winston Chang
326b294c83 Change progress indicators to use notification API (#1160) 2016-07-26 11:16:08 -07:00
Winston Chang
50f213ae71 Fixes for R CMD check 2016-07-26 10:32:13 -05:00
Winston Chang
91d4fd8849 Fix behavior when onBookmark() is called multiple times in a module 2016-07-25 22:29:55 -05:00
Winston Chang
3f1985a9dc Allow modules to exclude their inputs 2016-07-25 22:10:38 -05:00
Winston Chang
573a71f09d New version of reactiveValuesToList 2016-07-25 16:32:01 -05:00
Winston Chang
57900fa287 Move methods out of ShinySaveState 2016-07-25 16:31:47 -05:00
Winston Chang
fa721d9614 More informative comments 2016-07-25 16:31:47 -05:00
Winston Chang
e64bbacf68 Define filterNamespace and unNamespace locally 2016-07-25 16:31:47 -05:00
Winston Chang
6ee2edc757 Add namespace support to reactiveValuesToList 2016-07-25 13:58:21 -05:00
Winston Chang
9ec4faf0d0 Allow modules to call onBookmark, onRestore, onRestored 2016-07-25 10:52:41 -05:00
Winston Chang
5be3ba2ffa Use Callbacks objects for bookmarking callbacks 2016-07-21 15:28:43 -05:00
Winston Chang
a5ee96656b Add onFlush, onFlushed, and onSessionEnded functions 2016-07-21 14:33:43 -05:00
Winston Chang
2db71d0323 Re-document 2016-07-21 14:33:42 -05:00
Winston Chang
dcf321047f When bookmarkStore="disable", don't restore 2016-07-21 13:55:45 -05:00
Winston Chang
4982110be9 configureBookmarking affect next shinyApp object creation 2016-07-21 12:49:36 -05:00
Winston Chang
28547e90d1 Fix memory leak (#1254)
* When observer is destroyed, invalidate context. Closes #1253

* Update NEWS
2016-07-20 21:01:29 -07:00
Joe Cheng
f70187597f Merge pull request #1222 from rstudio/joe/bugfix/chrome-unsafe-ports
Don't use randomly-chosen port numbers that Chrome deems unsafe
2016-07-20 13:36:05 -07:00
Barbara Borges Ribeiro
333e454e78 Merge pull request #1252 from rstudio/barbara/bugfix/where
give `where` arg a default value ("replace")
2016-07-20 19:47:00 +01:00
Barbara Borges Ribeiro
61cfd11644 give where arg a default value ("replace") 2016-07-20 19:05:20 +01:00
Winston Chang
1c970c8176 Remove configureBookmarking; add onBookmark, onBookmarked, onRestore, onRestored 2016-07-19 14:31:57 -05:00
Winston Chang
1fea54ca5a Merge pull request #1249 from daattali/patch-1
fix typo
2016-07-19 13:31:12 -05:00
Dean Attali
faccc42b22 fix typo 2016-07-17 02:42:41 -04:00
Winston Chang
460f4769a5 Add _inputs_ for url-encoded state 2016-07-12 12:30:37 -05:00
Winston Chang
f465643b75 Rename 'type' argument to 'store' 2016-07-11 23:00:19 -05:00
Winston Chang
a8afd71f96 Rename shiny_persist to shiny_bookmarks 2016-07-08 16:36:58 -05:00
Winston Chang
2274d60207 Change function(req) to function(request) 2016-07-08 16:23:52 -05:00
Winston Chang
57159bccfd Show copy instructions in bookmark dialog 2016-07-08 16:22:09 -05:00
Winston Chang
2888124752 Capture and log errors in initializing RestoreContext 2016-07-08 15:22:58 -05:00
Winston Chang
408e751dcf Capture and log errors in bookmarking/restoring 2016-07-08 15:22:21 -05:00
Winston Chang
af5dcc38a4 Add onRestored argument 2016-07-07 12:44:10 -05:00
Winston Chang
81434640d6 Use name 'bookmark' in more places 2016-07-07 12:04:53 -05:00
Barbara Borges Ribeiro
a45b58d956 Merge pull request #1239 from rstudio/joe/bugfix/insert-ui-initialize
Fix insertUI bug. Closes #1220, #1231, #1232
2016-07-06 22:04:00 +01:00
Barbara Borges Ribeiro
2c5e9a5e76 moved multiple to 4th argument 2016-07-06 21:44:52 +01:00
Barbara Borges Ribeiro
9fb847b179 Merge branch 'master' into joe/bugfix/insert-ui-initialize 2016-07-06 21:37:58 +01:00
Barbara Borges Ribeiro
b8341b2ba8 Merge pull request #1238 from rstudio/feature/pool-scheduler
Better pool support (minor change)
2016-07-06 21:35:21 +01:00
Barbara Borges Ribeiro
26d6e4da2c allows callback to be garbage collected 2016-07-06 21:29:12 +01:00
Barbara Borges Ribeiro
b16ed602d5 rebased with master
Merge branch 'joe/bugfix/insert-ui-initialize' of https://github.com/rstudio/shiny into joe/bugfix/insert-ui-initialize

# Conflicts:
#	inst/www/shared/shiny.js.map
#	inst/www/shared/shiny.min.js
#	inst/www/shared/shiny.min.js.map
2016-07-06 18:04:17 +01:00
Barbara Borges Ribeiro
24aab4d5d3 Merge branch 'master' of https://github.com/rstudio/shiny 2016-07-06 14:18:49 +01:00
Barbara Borges Ribeiro
2eb69d421a fix to outputOptions 2016-07-06 14:18:38 +01:00
Winston Chang
cb52706f2f Add bookmarking example with arbitrary values 2016-07-05 16:35:00 -05:00
Winston Chang
f44d232e8b Add check that UI is a function when restoring state 2016-07-05 16:28:09 -05:00
Winston Chang
a0ac79b9dd Documentation updates 2016-07-05 15:30:42 -05:00
Joe Cheng
177a2a8a1e Input not being initialized with insertUI if beforeStart/afterEnd 2016-07-05 11:06:25 -07:00
Barbara Borges Ribeiro
8b21a87175 Update NEWS 2016-06-30 17:51:09 +01:00
Barbara Borges Ribeiro
6d2dd8e315 Merge pull request #1226 from rstudio/feature/pool-scheduler
Support pool package
2016-06-30 17:49:52 +01:00
Joe Cheng
8b3aff599b Don't use randomly-chosen port numbers that Chrome deems unsafe
Still OK to use these ports if the user asks for them explicitly
2016-06-25 22:37:22 -07:00
Joe Cheng
deb9b74f27 Do equivalent of "mkdir -p" when making state dir 2016-06-25 14:25:22 -07:00
Winston Chang
591de3cbe8 Don't restore state if in a subapp 2016-06-20 16:00:25 -05:00
Winston Chang
f7151e2132 Change '_state_id' to '__state_id__' 2016-06-20 15:12:10 -05:00
Winston Chang
44521be6dd Gracefully handle errors in restoring state 2016-06-20 12:54:04 -05:00
Winston Chang
30416cdbb5 Grunt 2016-06-16 12:44:28 -05:00
Winston Chang
d04da2d256 Add asList method 2016-06-16 12:44:09 -05:00
Winston Chang
231d8a1949 Move loading and decoding of query string into RestoreContext 2016-06-16 10:39:45 -05:00
Winston Chang
3207bec805 Add ShinyRestoreContext class 2016-06-15 15:08:33 -05:00
Winston Chang
425a71e382 Replace bookmarkConfig with bookmarkObserver 2016-06-15 14:55:29 -05:00
Winston Chang
daa12ab2ec Revise how onSave is called; move persist() and encode() into ShinyState object 2016-06-15 14:55:06 -05:00
Joe Cheng
4c652389c5 Support pool package 2016-06-14 12:58:50 -07:00
Winston Chang
f69d88a656 Refinements to save button 2016-06-14 13:23:58 -05:00
Winston Chang
098cbc1456 Better splitting of state query string 2016-06-13 23:19:35 -05:00
Winston Chang
5f2da953a9 Add invalidateReactiveValue function 2016-06-13 22:12:28 -05:00
Winston Chang
638d999fcc Replace updateQueryString with updateLocationBar 2016-06-13 16:47:24 -05:00
Winston Chang
fa80fd64da Make 'restorable' opt-out instead of opt-in 2016-06-13 14:24:21 -05:00
Winston Chang
e4dad82dde Rename 'save' to 'persist' 2016-06-13 12:38:43 -05:00
Winston Chang
d65ff924c8 Add bookmarkButton 2016-06-10 12:47:31 -05:00
Winston Chang
96e9661aaa Fix reactive dependencies when restoring values 2016-06-10 10:55:18 -05:00
Winston Chang
8829d2ebd4 Properly mark actionButtons and passwordInputs as unserializable 2016-06-10 10:44:51 -05:00
Winston Chang
c019280d8a Call onRestore only if it exists 2016-06-10 10:38:04 -05:00
Winston Chang
8d3e5fc160 Refinements 2016-06-10 10:11:55 -05:00
Winston Chang
d3f1312c0b Remove 'enable' argument 2016-06-09 14:55:33 -05:00
Winston Chang
c58f48a1e4 Add support for bookmarking arbitrary values 2016-06-09 14:45:55 -05:00
Winston Chang
979e93509e parseQueryString: ignore extra ampersands 2016-06-09 13:01:36 -05:00
Winston Chang
135c3709b4 Prepare things for separate values 2016-06-09 11:57:45 -05:00
Winston Chang
08400d3f18 Add configureBookmarking function 2016-06-08 12:56:03 -05:00
Winston Chang
bf52075d1b Merge pull request #1197 from rstudio/joe/feature/resetBrush
Add ability to reset brush with session$resetBrush/Shiny.resetBrush
2016-06-03 13:04:01 -05:00
Winston Chang
56befda288 Remove outdated example 2016-06-03 12:48:34 -05:00
Winston Chang
3d68f1dc62 Remove bookmarkOutput; add saveStateModal and encodeStateModal 2016-06-03 12:48:33 -05:00
Winston Chang
970036ce1a Remove clipboard.js 2016-06-03 12:48:33 -05:00
Winston Chang
62108f28f4 Fix argument defaults 2016-06-02 12:52:19 -05:00
Winston Chang
66bbb072c3 Remove createBookmark function 2016-06-02 12:48:17 -05:00
Winston Chang
6c52c26a62 Make names consistent 2016-06-02 11:47:56 -05:00
Winston Chang
d52943d1bf Remove unused code path 2016-06-01 21:41:35 -05:00
Winston Chang
7cb1bbe3d6 Use new ID each time state is saved 2016-06-01 18:12:07 -05:00
Winston Chang
2548c46b8b Check for '..' in restored file input path 2016-06-01 18:07:33 -05:00
Winston Chang
dd5118116b Use wrapper functions for saving/restoring state 2016-06-01 17:10:56 -05:00
Winston Chang
77a9b66028 Merge pull request #1201 from rstudio/bugfix/avoid-radix-sort-overflow
avoid overflow in R 3.3.0 radix sort
2016-05-27 21:39:15 -05:00
Kevin Ushey
e813dab81c avoid overflow in R 3.3.0 radix sort 2016-05-27 14:48:44 -07:00
Winston Chang
6696880178 Add ability to save and restore fileInputs. Also improve fileInput appearance 2016-05-27 14:42:00 -05:00
Winston Chang
8e5952d9ae Add serializers 2016-05-26 12:43:01 -05:00
Joe Cheng
360c1d5953 Add ability to reset brush with session$resetBrush/Shiny.resetBrush 2016-05-25 15:37:27 -07:00
Winston Chang
a7aa6ced19 Save each state in a subdirectory 2016-05-20 14:52:52 -05:00
Winston Chang
97eea669d4 Better error handling when saving/restoring state 2016-05-20 14:17:23 -05:00
Winston Chang
c84777928e Use same state ID throughout a session 2016-05-20 14:10:26 -05:00
Winston Chang
490064a953 Remove unneeded randomID function 2016-05-20 14:10:26 -05:00
Winston Chang
d5975195b3 Initial version of saving state 2016-05-20 14:10:26 -05:00
Winston Chang
9588c36abb Merge branch 'joe/feature/insert-UI' 2016-05-18 15:53:50 -05:00
Barbara Borges Ribeiro
f9200ac135 small fixes; documentation; got rid of unnecassary things 2016-05-18 12:35:25 +01:00
Winston Chang
fffb9606ec Merge pull request #1185 from rstudio/barbara/showcase-update
Barbara/showcase update
2016-05-16 10:04:24 -05:00
Winston Chang
781e15cb84 Restore values only if 'restorable' option is set 2016-05-13 21:06:06 -05:00
Winston Chang
9742001a71 Add shiny options 2016-05-13 20:37:58 -05:00
Barbara Borges Ribeiro
e92eee5ffc removed constraint that forced elements inserted with insertUI to be wrapped in a div/span 2016-05-13 15:28:02 -05:00
Barbara Borges Ribeiro
293c1d471c tiny fix 2016-05-13 14:34:07 -05:00
Barbara Borges Ribeiro
384240b6a4 added NEWS item for IncludeWWW 2016-05-13 14:26:45 -05:00
Winston Chang
6fd626a3ec Disable seralizing of passwords and actionButtons 2016-05-12 17:03:25 -05:00
Winston Chang
bb4ce2f978 Don't clear bookmark DOM elements on error 2016-05-12 15:27:17 -05:00
Barbara Borges Ribeiro
2269e05058 code highliting; dropdown menu for the www files 2016-05-12 15:12:04 -05:00
Winston Chang
ca2a07b816 Add ability to invalidate a reactive value 2016-05-12 10:21:29 -05:00
Winston Chang
38c7bb35e0 Code cleanup 2016-05-12 10:06:44 -05:00
Winston Chang
4f6408f3e1 Add optional update button for bookmarkOutput 2016-05-12 10:06:44 -05:00
Winston Chang
7910d9fde4 Add argument to exclude values from bookmarking 2016-05-12 10:06:43 -05:00
Winston Chang
0258d7e24f Make sure bookmark output is not a text input 2016-05-12 10:06:43 -05:00
Winston Chang
85556ed532 Don't error when no restore context available 2016-05-12 10:06:43 -05:00
Winston Chang
cecb04b097 Make restore context available from server code 2016-05-12 10:06:43 -05:00
Winston Chang
8a7c5c18d0 Add tooltip on copy 2016-05-12 10:06:43 -05:00
Winston Chang
14a1a3f574 Rename functions 2016-05-12 10:06:43 -05:00
Winston Chang
c19f2a7499 Add license info for clipboard.js 2016-05-12 10:05:37 -05:00
Winston Chang
df95be5455 Add bookmarkOutput 2016-05-12 10:05:37 -05:00
Winston Chang
00bef13f1c Add ability for inputs to restore bookmarked values 2016-05-12 10:05:37 -05:00
Winston Chang
a6a35905a7 Clearer variable names 2016-05-12 10:05:37 -05:00
Winston Chang
93f28ef55c Preserve type of bookmarked data 2016-05-12 10:05:36 -05:00
Joe Cheng
bbcb9573cd Add example 2016-05-12 10:05:36 -05:00
Winston Chang
43cc6e19d4 Fixes 2016-05-12 10:05:36 -05:00
Joe Cheng
f4a44664c7 Bookmarkable state wip 2016-05-12 10:05:36 -05:00
Barbara Borges Ribeiro
dd7a3269ad added wwwFiles boolean option to DESCRIPTION file 2016-05-07 17:21:59 +01:00
Winston Chang
157d1b20c5 Fixes for R CMD check 2016-05-06 15:14:09 -05:00
Winston Chang
85fe0c00c2 Fix tests 2016-05-06 15:10:45 -05:00
Winston Chang
91092b8a96 Fix function labels for profiling 2016-05-06 15:03:00 -05:00
Barbara Borges Ribeiro
1ed237cfcc init commit 2016-05-05 16:11:43 +01:00
Barbara Borges Ribeiro
c7044498d5 added NEWS item for insertUI / removeUI 2016-05-05 14:17:45 +01:00
Joe Cheng
1d2a2fbcae Merge remote-tracking branch 'origin/joe/feature/insert-UI' 2016-05-04 11:34:54 -07:00
Barbara Borges Ribeiro
9b015e8cae documentation update 2016-05-03 13:57:10 +01:00
Barbara Borges Ribeiro
0a8c26fff4 call sendImageSize from unbindOutputs 2016-05-02 20:02:41 +01:00
Barbara Borges Ribeiro
506de72666 fixed typos; included argument defaults; removed 'shown', 'hidden' triggers following chat with Winston 2016-05-02 18:27:15 +01:00
Barbara Borges Ribeiro
a5b4156b56 moved insertAdjacentElement to the right place 2016-05-02 15:19:08 +01:00
Barbara Borges Ribeiro
da4b42cb1d ran grunt 2016-05-02 14:50:46 +01:00
Barbara Borges Ribeiro
53790f8247 various updates 2016-05-02 14:48:05 +01:00
Barbara Borges Ribeiro
69780d4727 added sendImage and sendOUtputHIddenState 2016-04-29 06:33:06 +01:00
Barbara Borges Ribeiro
aa2b644684 updated documentation; added ... argument to onFlush() and onFlushed() in order to be able to pass in arguments to the func 2016-04-29 05:27:26 +01:00
Barbara Borges Ribeiro
a12e8875a6 changed everything from sendCustomMessage to session$sendMessage 2016-04-29 05:16:22 +01:00
Barbara Borges Ribeiro
9e91b265ce sendInsertUI now uses sendMessage instead of sendCustomMessage 2016-04-29 04:46:09 +01:00
Barbara Borges Ribeiro
8c12e3ab90 added insertAdjacentElement for compatibility with Firefox 2016-04-28 12:03:15 +01:00
Winston Chang
7e303b4fc0 Merge pull request #1157 from rstudio/modal
Add modal dialogs
2016-04-27 15:30:02 -05:00
Winston Chang
40e0fcff30 Change modal example 2016-04-27 15:29:18 -05:00
Winston Chang
3c9e74b23e Re-document 2016-04-26 15:30:03 -05:00
Barbara Borges Ribeiro
6b001eb7c3 updated insertUI; added removeUI 2016-04-25 23:03:18 +01:00
Winston Chang
f81621aa66 Merge pull request #1158 from rstudio/example-cleanup
Clean up examples
2016-04-22 13:05:36 -05:00
Winston Chang
08c7484087 Rename argument 2016-04-21 15:22:43 -05:00
Barbara Borges Ribeiro
a8c68f3e30 updated shiny-options text 2016-04-18 17:28:45 +01:00
Barbara Borges Ribeiro
0e6698d760 updated NEWS 2016-04-18 02:12:47 +01:00
Barbara Borges Ribeiro
f3d4f9ff23 Merge pull request #1156 from rstudio/barbara/error-hiding
Barbara/error hiding
2016-04-18 01:56:26 +01:00
Barbara Borges Ribeiro
d711f17081 changed sanitization default to FALSE (on local development) 2016-04-18 01:44:43 +01:00
Barbara Borges Ribeiro
d35eba45c5 tiny fix 2016-04-18 01:34:50 +01:00
Barbara Borges Ribeiro
cd53e79b19 removed classError argument to safeError function 2016-04-18 01:27:37 +01:00
Barbara Borges Ribeiro
3db7029534 Merge branch 'master' of https://github.com/rstudio/shiny 2016-04-15 16:50:19 +01:00
Barbara Borges Ribeiro
ad1e52bf19 got rid of warning that popped up when renderFunc took no arguments; there really isn't a good reason to require this (not at this point at least) 2016-04-15 16:49:52 +01:00
Barbara Borges Ribeiro
e08791a284 update to safeError 2016-04-14 18:20:49 +01:00
Barbara Borges Ribeiro
8d1deeb568 undo last commit to be able to merge automatically 2016-04-14 18:02:16 +01:00
Barbara Borges Ribeiro
375c7789a2 updated NEWS 2016-04-14 17:52:10 +01:00
Barbara Borges Ribeiro
ec8a81aedb Merge pull request #1163 from bborgesr/barbara/fix-tabsetpanel
deprecated position arg to tabsetPanel; updated NEWS; cc @jcheng5 @wch
2016-04-14 17:49:51 +01:00
Barbara Borges Ribeiro
033d513aee added version to shinyDeprecated call; updated NEWS 2016-04-14 17:43:24 +01:00
Barbara Borges Ribeiro
fb3e4e4881 Changed customStop to stop(safeError). Refactored some middleware.R code. Fixed downloadHandler's bug of not responding to safeError. 2016-04-14 17:31:34 +01:00
Joe Cheng
8a30c006e7 Prototype insertUI functionality 2016-04-13 16:12:30 -07:00
Barbara Borges Ribeiro
3f76679673 another update to NEWS 2016-04-07 22:22:51 +01:00
Barbara Borges Ribeiro
1cee5d4b41 deprecated position arg to tabsetPanel; updated NEWS 2016-04-07 22:15:15 +01:00
Barbara Borges Ribeiro
3107eec697 removed unnecessary line 2016-04-07 02:01:56 +01:00
Barbara Borges Ribeiro
477d46316e updated customStop() documentation example to match Winston's pattern 2016-04-06 14:08:11 +01:00
Winston Chang
3133693a0e Update NEWS 2016-04-05 20:58:48 -05:00
Winston Chang
bc7d701298 Make examples runnable with shinyApp() 2016-04-05 20:53:59 -05:00
Winston Chang
5d6d75b4f3 Remove shinyUI() and shinyServer() from examples 2016-04-05 15:23:23 -05:00
Winston Chang
73d48a7b37 Grunt 2016-04-05 13:19:27 -05:00
Winston Chang
ed7b9a9989 Modal dialog refinements 2016-04-05 13:18:57 -05:00
Winston Chang
e1a955752f Add modal dialogs 2016-04-05 13:18:56 -05:00
Winston Chang
0bdc8f0b2b Update package.json 2016-04-05 09:45:06 -05:00
Barbara Borges Ribeiro
a692b3ced8 implemented error hiding for ui.R and downloadHandler() cases 2016-04-05 15:28:05 +01:00
Winston Chang
2f5b93861d Merge pull request #1152 from daattali/master
add placeholder option to passwordInput()
2016-04-04 11:23:44 -05:00
Joe Cheng
110183585c Merge pull request #1143 from rstudio/joe/feature/output-arg-passthrough
Joe/feature/output arg passthrough
2016-04-03 08:10:44 -07:00
Barbara Borges Ribeiro
7eb29586a7 a few minor tweaks 2016-04-03 15:24:17 +01:00
Barbara Borges Ribeiro
401065a23e a lot of not very productive experimentation 2016-04-03 15:00:59 +01:00
Dean Attali
4e5e0fb0ce add placeholder option to passwordInput() 2016-04-02 18:44:10 -07:00
Barbara Borges Ribeiro
d41a06611e fixed documentation 2016-04-01 23:57:20 +01:00
Barbara Borges Ribeiro
26c3c27726 a few tweaks to customStop() 2016-04-01 22:47:58 +01:00
Barbara Borges Ribeiro
19ab63e041 a little code refactoring and added a customStop() function 2016-04-01 02:45:41 +01:00
Barbara Borges Ribeiro
5dafdab3d7 made the tracker construct - now an R6 class - easier to understand (more obvious); fixed the shinysession and name issues related to the renderFunc's 2016-04-01 00:44:14 +01:00
Barbara Borges Ribeiro
afbb17d428 errors are now sanitized in the app by default (must use options(shiny.sanitize.errors = FALSE) to override this behavior) 2016-03-30 07:29:58 +01:00
Winston Chang
8a721fbd25 Bump version to 0.13.2.9001 and update NEWS
Shiny 0.13.2 was released from another branch so its changes to NEWS were
incorporated here
2016-03-29 22:46:46 -05:00
Winston Chang
5d91a409e7 Merge pull request #1150 from rstudio/navbarpage-selected
Allow setting selected item in navbarPage. Closes #970
2016-03-29 22:35:18 -05:00
Winston Chang
8470f7caf8 Allow setting selected item in navbarPage. Closes #970 2016-03-29 22:32:00 -05:00
Winston Chang
67e279928e Merge pull request #1147 from rstudio/navbar-horizontal-divider
navbarMenu horizontal dividers
2016-03-29 22:13:24 -05:00
Winston Chang
77ac3a62b7 Check that tab arguments are unnamed 2016-03-29 12:56:43 -05:00
Winston Chang
12eaa3a162 Reconnection refinements 2016-03-29 12:41:46 -05:00
Joe Cheng
bbd5dd7b4f Merge pull request #1132 from rstudio/joe/reactive-graph-data
Update reactive graph sample data to include time
2016-03-29 09:54:15 -07:00
Joe Cheng
38fcd6e267 Merge pull request #1074 from rstudio/reconnect
Reconnect
2016-03-29 09:53:20 -07:00
Winston Chang
fd7f683eaa Remove bootstrapDependency function. Closes #1069 2016-03-29 11:12:05 -05:00
Winston Chang
e15f9acd91 Grunt 2016-03-28 21:30:27 -05:00
Winston Chang
7cb0882c73 Add "force" option to allowReconnect 2016-03-28 21:29:23 -05:00
Winston Chang
486d4d1c88 Add 'action' parameter to notifications 2016-03-28 15:15:07 -05:00
Winston Chang
ded8b13e96 Reconnect UI refinements 2016-03-28 14:42:44 -05:00
Barbara Borges Ribeiro
c7eb7ba861 passed error through if handler accepts it 2016-03-28 20:31:39 +01:00
Barbara Borges Ribeiro
4920bff8fd tiny documentation update 2016-03-28 18:24:04 +01:00
Barbara Borges Ribeiro
d78edf5dda removed func arg from render functions; fixed issue introduced by rebase a few commits ago 2016-03-28 18:19:37 +01:00
Winston Chang
7510c02d83 Update ion.RangeSlider to 2.1.2 2016-03-28 11:17:07 -05:00
Barbara Borges Ribeiro
2d7b729473 got rid of unnecessary lines 2016-03-28 15:46:55 +01:00
Barbara Borges Ribeiro
0495fe2d71 updated renderFunc's to include a shinysession arg 2016-03-28 15:31:33 +01:00
Barbara Borges Ribeiro
d7da5df734 updated integration etsts 2016-03-28 13:18:22 +01:00
Barbara Borges Ribeiro
4462b6bd39 changed a warning to an error, following the "fail fast" principle 2016-03-28 13:00:11 +01:00
Barbara Borges Ribeiro
80e1edeeb2 a better way to check which context the render function is being called from 2016-03-28 12:54:54 +01:00
Winston Chang
11af421f10 Use notification API for reconnection interface 2016-03-25 16:39:58 -05:00
Winston Chang
686ff235e7 New reconnect UI 2016-03-25 15:43:08 -05:00
Winston Chang
31f76a6d4d Add back gray-out on disconnect 2016-03-25 15:40:46 -05:00
Winston Chang
50078078e0 Export show/hideReconnectDialog functions 2016-03-25 15:40:45 -05:00
Winston Chang
be85e1e2f7 Add onConnected and onDisconnected 2016-03-25 15:40:45 -05:00
Winston Chang
9ad1574292 Allow Shiny Server to properly override methods 2016-03-25 15:40:45 -05:00
Winston Chang
4b71825707 Increase reconnect delay time with subsequent attempts 2016-03-25 15:40:45 -05:00
Winston Chang
fb1fd88947 Tweaks to disconnection/reconnection UI 2016-03-25 15:40:45 -05:00
Winston Chang
dca527d8b6 Allow app to control reconnection behavior 2016-03-25 15:40:45 -05:00
Winston Chang
3452a445fe Show box when trying to reconnect 2016-03-25 15:40:45 -05:00
Winston Chang
a06e9d2bef Implement auto-reconnect 2016-03-25 15:39:31 -05:00
Winston Chang
7a3961a280 Add support for menu section headers 2016-03-25 09:29:42 -05:00
Winston Chang
54729d8fb4 Update NEWS 2016-03-24 20:11:44 -05:00
Winston Chang
c2e17ee182 Add support for horizontal dividers in navbarMenu 2016-03-24 20:11:07 -05:00
Barbara Borges Ribeiro
bc0064d4b9 harcoded colors used for the color-coding of the time labels (creditted colorbrewer) 2016-03-25 00:51:19 +00:00
Barbara Borges Ribeiro
03685dbb61 added check for valid arguments if passed via outputArgs 2016-03-25 00:22:48 +00:00
Barbara Borges Ribeiro
26fcba8ed5 really not a solution... 2016-03-24 22:42:57 +00:00
Barbara Borges Ribeiro
bc15b65538 added outputArgs to all other renderXXX functions following the pattern used for renderPlot 2016-03-24 22:42:57 +00:00
Joe Cheng
e9ab34a9c1 Provide xxxOutput args via renderXXX passthrough
This will allow you to customize outputs when used in an R Markdown
document
2016-03-24 22:21:48 +00:00
Winston Chang
0bf512ebdd Grunt 2016-03-24 17:11:12 -05:00
Winston Chang
7646fbeaa0 Bump version to 0.13.1.9002 2016-03-24 17:11:02 -05:00
Winston Chang
84b4766013 Merge pull request #1141 from rstudio/notifications
Notification interface
2016-03-24 17:09:31 -05:00
Winston Chang
3a48734b2f Re-document 2016-03-24 14:07:37 -05:00
Winston Chang
36ae332959 Remove some public methods for notifications 2016-03-24 14:01:28 -05:00
Winston Chang
3e0d8da9d6 Add exports.renderContent to modularize content rendering in JS 2016-03-23 15:46:44 -05:00
Winston Chang
2fcb4dbe50 Modularize dependency handling in R 2016-03-23 15:46:03 -05:00
Winston Chang
09c93bfb39 Escape ID 2016-03-23 14:34:20 -05:00
Winston Chang
34068b1598 Rename 'style' to 'type' 2016-03-23 14:34:20 -05:00
Barbara Borges Ribeiro
a67da1c99a added color scale for time labels 2016-03-23 16:26:33 +00:00
Winston Chang
0d6754761d Add style argument 2016-03-22 15:36:21 -05:00
Winston Chang
898f7b66cf Rename argument from 'html' to 'ui' 2016-03-22 14:47:07 -05:00
Winston Chang
c18f3e86f0 Add note about IDs 2016-03-22 13:46:21 -05:00
Barbara Borges Ribeiro
de51922f10 Trigger 2016-03-22 17:02:38 +00:00
Winston Chang
be0cb18bfc Merge pull request #1138 from rstudio/joe/bugfix/htmltemplate-doc-update
Update htmlTemplate docs for htmltools 0.3.5
2016-03-22 11:13:31 -05:00
Winston Chang
39fd1db3c0 Bump htmltools required version to 0.3.5 2016-03-22 11:07:15 -05:00
Winston Chang
b4565e7354 Fix coordmap tests 2016-03-22 11:05:59 -05:00
Winston Chang
e28cada4dd Handle tag inputs and escape HTML text 2016-03-21 20:10:17 -05:00
Joe Cheng
6daac65968 Add missing entries to staticdocs index 2016-03-21 17:00:17 -07:00
Joe Cheng
1ecc49c450 Update htmlTemplate docs for htmltools 0.3.5 2016-03-21 16:53:46 -07:00
Barbara Borges Ribeiro
f96e7d9aaa stored the timeElapsed float on the node instead of the fully formatted string; made sure we're not showing any time elapsed info while the node is active (it could be confusing) 2016-03-21 23:25:17 +00:00
Barbara Borges Ribeiro
c637bba867 changed time label color; updated default argument to renderReactLog 2016-03-21 22:19:45 +00:00
Barbara Borges Ribeiro
bdc6554ca8 added time argument 2016-03-21 21:53:34 +00:00
Winston Chang
ecb59e9c31 Add R notification functions 2016-03-21 16:47:55 -05:00
Winston Chang
1b39184e98 Add randomID function 2016-03-21 16:43:35 -05:00
Barbara Borges Ribeiro
2a35ba64f7 fixed y positioning 2016-03-21 21:15:32 +00:00
Barbara Borges Ribeiro
3a5123627d updated multilineTextNode 2016-03-21 21:04:27 +00:00
Barbara Borges Ribeiro
a18eeecd59 separated text label and time label 2016-03-21 20:59:32 +00:00
Winston Chang
85e3f04738 Restyle notifications and add close button 2016-03-21 13:59:12 -05:00
Barbara Borges Ribeiro
cc59864377 experimenting 2016-03-21 18:49:47 +00:00
Barbara Borges Ribeiro
5b10cbf2e2 added 'time elapsed' to nodes' labels 2016-03-21 14:30:42 +00:00
Barbara Borges Ribeiro
fc6b83bb5d Merge pull request #1136 from rstudio/barbara/renderTable-fixes
tiny update following the bigger renderTable() PR
2016-03-18 21:20:29 +00:00
Barbara Borges Ribeiro
bc509f55d9 added NEWS item documenting the change to renderTable() and fixed tiny bug (stop() message was spanning two lines with only one string) 2016-03-18 21:15:35 +00:00
Winston Chang
f81301ece6 Simplify notification API 2016-03-18 15:53:40 -05:00
Winston Chang
382e5c1f43 Rename Shiny.Notification to Shiny.notifications 2016-03-18 14:59:43 -05:00
Winston Chang
0243f74dcd Add delay before removal 2016-03-18 14:45:21 -05:00
Winston Chang
58737ef454 Add notification JS API 2016-03-18 14:45:21 -05:00
Winston Chang
940cea82ca Merge pull request #1133 from rstudio/es6
Add tooling for ES6
2016-03-18 14:44:53 -05:00
Winston Chang
5683e36733 Add estraverse-fb npm dependency 2016-03-18 14:42:03 -05:00
Winston Chang
f5137b7935 Grunt 2016-03-18 14:16:47 -05:00
Winston Chang
0c2af42c69 Make ESLint gave warnings instead of errors 2016-03-18 14:15:36 -05:00
Winston Chang
760dc5d0c6 Add babel polyfill 2016-03-18 14:15:36 -05:00
Winston Chang
5331aa08a7 Fixes for eslint 2016-03-18 14:15:36 -05:00
Winston Chang
375d7cc7b1 Update eslint rules 2016-03-18 14:15:36 -05:00
Winston Chang
a05f3dd640 Update npm packages 2016-03-18 14:15:36 -05:00
Winston Chang
b91c1b44ba Switch from jshint to eslint 2016-03-18 14:15:36 -05:00
Winston Chang
6efb01a397 Use Babel for ES6->ES5 transpilation 2016-03-18 14:15:36 -05:00
Barbara Borges Ribeiro
1843eca6c0 Merge pull request #1134 from bborgesr/updateActionButton
Verify button icon format and created updateActionButton()
2016-03-18 19:01:50 +00:00
Barbara Borges Ribeiro
506e3e8a48 added another check in the JS to make sure that we're finding the correct icon 2016-03-18 18:55:38 +00:00
Barbara Borges Ribeiro
0e5a3cc5aa throw error instead of warning in validateIcon(); updated documentation 2016-03-18 15:32:06 +00:00
Barbara Borges Ribeiro
d2dd76e13d fixed typo 2016-03-17 21:36:51 +00:00
Barbara Borges Ribeiro
470b82fd64 compiled documentation 2016-03-17 21:20:42 +00:00
Barbara Borges Ribeiro
e04dd3a4b1 check icon validity more robustly; set icon=character(0) as the way to get rid of a previous icon; updated documentaion and NEWS 2016-03-17 21:15:49 +00:00
Barbara Borges Ribeiro
2d39e06c97 find i-tag elements with *any* class (to circumvent the issue of selecting italicized text) 2016-03-17 14:55:57 +00:00
Barbara Borges Ribeiro
e1fc74bdc1 updates to input_binding_actionbutton.js and got rid of isIcon function (substituted by simple check instead) 2016-03-17 14:47:48 +00:00
Barbara Borges Ribeiro
3ab5d7f861 verify that button icons are in the right format (not necessarily valid though) and added updateActionButton() 2016-03-15 22:19:21 +00:00
Winston Chang
d63dd6086a Merge pull request #1129 from bborgesr/newRenderTable
Improved renderTable()
2016-03-15 12:43:02 -05:00
Barbara Borges Ribeiro
a8d9895a9b updated documentation 2016-03-15 16:58:42 +00:00
Barbara Borges Ribeiro
f8a7257af3 improved defaultAlignment function and changed names of spacing value options 2016-03-15 16:47:35 +00:00
Barbara Borges Ribeiro
4703028988 actually with multiple tables, their ids would all be identical (bad), so switched back to using classes to gain specificity 2016-03-15 00:55:48 +00:00
Barbara Borges Ribeiro
87523cdbd5 created table id to add css specificity 2016-03-15 00:38:18 +00:00
Barbara Borges Ribeiro
d9567ed035 check valid spacing 2016-03-15 00:01:52 +00:00
Barbara Borges Ribeiro
0ab277662a updated documentation 2016-03-14 23:00:15 +00:00
Barbara Borges Ribeiro
2eeb94e39c changed bordered to spacing with four possible values, rather than only two 2016-03-14 22:48:55 +00:00
Joe Cheng
4b441d10b3 Update reactive graph sample data to include time 2016-03-14 15:37:53 -07:00
Barbara Borges Ribeiro
37a1d3d61e improved defaultAlignment function 2016-03-14 20:24:41 +00:00
Barbara Borges Ribeiro
3839338c15 mostly spacing 2016-03-14 20:13:08 +00:00
Barbara Borges Ribeiro
bdee5790e6 added alignment default character ("?") 2016-03-14 18:39:51 +00:00
Barbara Borges Ribeiro
d0dab25dae tried fix 2016-03-14 16:16:22 +00:00
Barbara Borges Ribeiro
b14b7b00c2 actually padding is necessary for headers too 2016-03-14 14:57:38 +00:00
Barbara Borges Ribeiro
248bfcccda padding on all cells 2016-03-14 14:54:31 +00:00
Barbara Borges Ribeiro
9b5833205b made the check for empty data frame more robust 2016-03-12 18:24:19 +00:00
Barbara Borges Ribeiro
07f8589090 coerce the input to a data frame (important if the input was a matrix for example, as some parts of the code might not apply) 2016-03-12 18:12:50 +00:00
Barbara Borges Ribeiro
f77f83dfeb fixed a tiny bug introduced by the previous commit 2016-03-12 18:03:59 +00:00
Barbara Borges Ribeiro
e3d3d916ba improved regex for substitution (less fragile, less hack-ish) 2016-03-12 17:59:45 +00:00
Barbara Borges Ribeiro
cccf219cd2 simplified alignment vector and got rid of an unnecessary variable 2016-03-12 17:55:05 +00:00
Barbara Borges Ribeiro
0896b2f7b8 initialize header_alignments in a clearer way 2016-03-12 17:36:01 +00:00
Barbara Borges Ribeiro
cc406262ac added spaces after commas in a couple of places where they were missing 2016-03-12 17:23:43 +00:00
Barbara Borges Ribeiro
0f20063eb8 added "$" to regex to make sure we're subbing "</table>" only at the end of the input 2016-03-12 17:04:29 +00:00
Barbara Borges Ribeiro
5f32b165f2 updated createWrapper() per Joe's suggestion, added spaces between the "=" 2016-03-12 16:46:59 +00:00
Winston Chang
3cadd1789b Merge pull request #1130 from dmpe/master
update bootstrap to 3.3.6
2016-03-11 16:03:24 -06:00
dmpe
e486778b36 note to news file and upgrade number in R file 2016-03-11 19:21:25 +01:00
Barbara Borges Ribeiro
7fe6453bbb vectorized form to add format args to classNames 2016-03-11 16:26:07 +00:00
Barbara Borges Ribeiro
9f88d2b6d6 made isNumber() 1000x more elegant 2016-03-11 16:19:29 +00:00
Barbara Borges Ribeiro
8f9d52699d return NULL instead of the empty string if no data is provided 2016-03-11 16:00:00 +00:00
Barbara Borges Ribeiro
0a774a8c55 "the" changed to "of" 2016-03-11 15:52:05 +00:00
Barbara Borges Ribeiro
d4ced34a11 2nd update to width documentation (copied straight from plotOutput() ) 2016-03-11 15:36:14 +00:00
Barbara Borges Ribeiro
85a762a0b9 updated width documentation 2016-03-11 15:34:34 +00:00
dmpe
b255fecc6e update bootstrap to 3.3.6
see https://github.com/rstudio/shiny/issues/1056
2016-03-11 13:23:38 +01:00
Barbara Borges Ribeiro
734d2e2594 latex bug in documentation (but shouldn't this be allowed?) 2016-03-11 10:58:18 +00:00
Barbara Borges Ribeiro
2e292b4636 commenting and documenting 2016-03-11 10:44:02 +00:00
Barbara Borges Ribeiro
f0bc7356ac made sure theader is only present the argument colnames is set to TRUE 2016-03-10 23:34:53 +00:00
Winston Chang
1bcb6ab931 Add note about grunt clean 2016-03-10 11:08:15 -06:00
Barbara Borges Ribeiro
ef65937662 replaced format argument with 4 flags (striped, bordered, hover, condensed) and made headers look like bootstrap's 2016-03-09 22:54:11 +00:00
Barbara Borges Ribeiro
3369b8b5b2 finally got headers to align nicely with columns 2016-03-09 01:44:23 +00:00
Winston Chang
28db561cd9 Bump version to 0.13.1.9001 and update NEWS 2016-03-08 17:03:55 -06:00
Winston Chang
0622326e1b Merge pull request #1126 from rstudio/commas
Add code diagnostics for missing/extra commas, and for unmatched }, ), and ]
2016-03-08 17:01:36 -06:00
Winston Chang
c6e2593e4e Streamline diagnoseCode 2016-03-08 16:54:28 -06:00
Barbara Borges Ribeiro
d0e3279a67 aesthethics 2016-03-08 17:00:42 +00:00
Winston Chang
aee5bda9ec Add workaround for quartz res bug
The quartz device is hard-coded to use 72 ppi in some places, and this
causes problems with grid unit calculations when a value other than 72
is used.
2016-03-08 09:54:01 -06:00
Barbara Borges Ribeiro
979b4a8861 used row.names() function instead of rownames() to avoid naming conflicts 2016-03-07 12:56:00 +00:00
Barbara Borges Ribeiro
c10cd4b474 removed unnecessary css, and garbage collection for renderBootstrapTable 2016-03-07 12:33:43 +00:00
Barbara Borges Ribeiro
4aa1d19845 replaced renderTable with renderBootstrapTable (but kept name renderTable) and ensured backward compatibility 2016-03-07 12:29:43 +00:00
Barbara Borges Ribeiro
7ff51d89fc check if rownames are numbers or strings 2016-03-07 12:21:39 +00:00
Winston Chang
ea9d94e42f Add code diagnostics (missing/extra commas) 2016-03-04 15:11:34 -06:00
Barbara Borges Ribeiro
a9ba0fdb0b added arguments, minimal functional code 2016-03-04 15:13:07 +00:00
Barbara Borges Ribeiro
af19c3331c added more function arguments 2016-03-04 00:01:09 +00:00
Winston Chang
5e98b930ee Move tests from inst/ to tests/ 2016-03-03 15:00:51 -06:00
Barbara Borges Ribeiro
057d160392 changes to make function compatible with table demo app 2016-03-03 15:54:59 +00:00
Barbara Borges Ribeiro
6b2899c219 fixed small width bug 2016-03-02 15:22:16 +00:00
Barbara Borges Ribeiro
85290e687c added customizable width 2016-03-02 15:05:50 +00:00
Barbara Borges Ribeiro
d778e81f42 aesthetic changes 2016-03-02 14:03:56 +00:00
Barbara Borges Ribeiro
2bfad21604 added renderBootstrapTable 2016-03-01 15:55:58 +00:00
Winston Chang
373e0d3a9f Fix NEWS after weird merge 2016-02-22 11:37:30 -06:00
Joe Cheng
5e83403d0c Update NEWS 2016-02-22 09:30:22 -08:00
Winston Chang
cbe76aab83 Merge pull request #1117 from rstudio/joe/feature/abort-output
Add ability to abort the processing of outputs
2016-02-22 11:20:17 -06:00
Joe Cheng
26de088520 s/abortOutput/cancelOutput/; add req option 2016-02-22 09:12:30 -08:00
Winston Chang
98430edb17 Merge branch 'replay-plot' 2016-02-19 13:57:38 -06:00
Winston Chang
48c6784e51 Change 'replay' option to 'execOnResize' 2016-02-19 13:52:36 -06:00
Winston Chang
dc0f5af3ef Rename 'render' to 'plotObj' 2016-02-19 13:42:54 -06:00
Winston Chang
af85e6f2a6 Merge pull request #1116 from yihui/warn-non-UTF8
Closes #810: check if the input file is encoded in UTF-8 and warn if not
2016-02-19 10:00:49 -06:00
Joe Cheng
4e91af4d64 Add ability to abort the processing of outputs
abortOutput() leaves the state of the output unchanged,
unlike req(), validate(), or stop().
2016-02-19 00:33:10 -08:00
Yihui Xie
faf87a5dee Closes #810: check if the input file is encoded in UTF-8 and warn if not
The validUTF8() function is still in R-devel, and they probably will never export it, so let's use iconv(x, from = 'UTF-8', to = 'UTF-8') to test if x is encoded in UTF-8

also closes #1113
2016-02-19 00:02:25 -06:00
Winston Chang
517c5d356f Merge tag 'v0.13.1'
Manually bumped version to 0.13.1.9000.
2016-02-18 12:45:00 -06:00
Winston Chang
931be22247 Bump version to 0.13.1 2016-02-17 12:03:55 -06:00
Joe Cheng
8697360eb7 Really fix docs. 2016-02-17 11:46:02 -06:00
Joe Cheng
e3a867132a Use parent.frame() instead of sys.parent() 2016-02-17 11:45:48 -06:00
Joe Cheng
c96debadc5 Fix docs/check 2016-02-17 11:45:16 -06:00
Joe Cheng
02520d4f54 Pass tests. reactive(function() { ... }) is NO LONGER supported. 2016-02-17 11:45:10 -06:00
Joe Cheng
5070b63d5b Partial fix of debugger breakage
There are two problems I'm trying to solve here.

1) Somewhere along the way, exprToFunction gained a hardcoded
   assumption that two stack frames up is a variable "expr",
   meaning anything that called installExprFunction had to have
   the first argument be exactly "expr". I think I got this
   fixed, now the only assumption made by both installExprFunc
   and exprToFunc is if they are called with quoted = FALSE,
   then the caller is merely passing through code that originated
   exactly one more level up the stack frame. If the code is
   less than one level up, i.e. an end user is directly passing
   code into installExprFunction or exprToFunction, then it won't
   work; and if the code is more than one level up (someone is
   passing code into function A which passes through to function
   B which calls installExprFunction, with quoted = FALSE) then
   it also won't work.

2) registerDebugHook calls were broken in various places by the
   name/envir registered with the hook being different than the
   name/envir through which the function was actually called.
   This generally seems fixable by moving the registerDebugHook
   call closer to the name/envir that will ultimately be called
   (e.g. call registerDebugHook directly from wrapFunctionLabel).

There still seems to be a problem here in that breakpoints in
RStudio are hit but then the IDE automatically runs "n" multiple
times. Also the unit tests don't currently pass, I haven't
investigated that yet.
2016-02-17 11:45:01 -06:00
Joe Cheng
eaa722b10d Fix flexCol on RStudio Desktop for Win/Linux
RStudio Desktop requires the older -webkit vendor-prefixed
flex box properties. I missed the one for flex-direction.
2016-02-17 11:32:47 -06:00
Winston Chang
1bc3c90286 Update NEWS 2016-02-16 14:07:49 -06:00
Winston Chang
afd00edee3 Add replay option 2016-02-16 14:07:49 -06:00
Winston Chang
b712398208 If plot code errors, re-execute on resize 2016-02-16 13:39:11 -06:00
Winston Chang
7586e91b4f Fix coordmap tests 2016-02-15 16:01:34 -06:00
Winston Chang
9eba82c107 Fix vars 2016-02-15 16:01:15 -06:00
Winston Chang
ccdc219a09 More cleanup 2016-02-15 15:39:05 -06:00
Yihui Xie
60d01e76e9 Merge pull request #1109 from vnijs/master
Closes #692
2016-02-13 00:38:06 -06:00
mostly-harmless
b5cfd4152e Fix for https://github.com/rstudio/shiny/issues/692 2016-02-12 22:15:34 -08:00
Winston Chang
32c4c8ae32 Code cleanup 2016-02-12 15:59:10 -06:00
Winston Chang
bd4c506d22 Implement replayPlot when width/height changes 2016-02-12 13:26:41 -06:00
Winston Chang
476dd7cd56 Collect needed data structures 2016-02-11 14:45:43 -06:00
Winston Chang
8176f84715 Restructure ggplot2 coordmap extraction 2016-02-11 14:25:20 -06:00
Winston Chang
6bd33721d8 Separate rendering code into a reactive 2016-02-11 12:27:16 -06:00
Winston Chang
c9d9671288 More restructuring 2016-02-11 12:25:38 -06:00
Winston Chang
2a821edf5f Small restructure of renderPlot 2016-02-11 12:25:38 -06:00
Winston Chang
68b85bdc87 Merge branch 'fix-plot-flicker2' 2016-02-11 12:20:45 -06:00
Winston Chang
83cf5907c3 Merge pull request #1072 from rstudio/rm-do-call
Remove unneeded do.call
2016-02-11 10:24:47 -06:00
Winston Chang
c912b6547c Merge pull request #1106 from yihui/travis-cache
Set sudo to false explicitly to enable caching
2016-02-11 10:23:08 -06:00
Yihui Xie
bf04b74f87 Set sudo to false explicitly to enable caching 2016-02-10 13:34:24 -06:00
Joe Cheng
9d1e008990 Merge pull request #1099 from rstudio/joe/bugfix/debug-fix
Partial fix of debugger breakage
2016-02-10 08:15:59 -08:00
Joe Cheng
d9e5285a3b Really fix docs. 2016-02-09 16:29:15 -08:00
Joe Cheng
84937b7a0b Use parent.frame() instead of sys.parent() 2016-02-09 16:29:15 -08:00
Joe Cheng
924b3e16cf Fix docs/check 2016-02-09 16:29:15 -08:00
Joe Cheng
2a8cf01410 Pass tests. reactive(function() { ... }) is NO LONGER supported. 2016-02-09 16:29:14 -08:00
Joe Cheng
a3a5cfee6c Partial fix of debugger breakage
There are two problems I'm trying to solve here.

1) Somewhere along the way, exprToFunction gained a hardcoded
   assumption that two stack frames up is a variable "expr",
   meaning anything that called installExprFunction had to have
   the first argument be exactly "expr". I think I got this
   fixed, now the only assumption made by both installExprFunc
   and exprToFunc is if they are called with quoted = FALSE,
   then the caller is merely passing through code that originated
   exactly one more level up the stack frame. If the code is
   less than one level up, i.e. an end user is directly passing
   code into installExprFunction or exprToFunction, then it won't
   work; and if the code is more than one level up (someone is
   passing code into function A which passes through to function
   B which calls installExprFunction, with quoted = FALSE) then
   it also won't work.

2) registerDebugHook calls were broken in various places by the
   name/envir registered with the hook being different than the
   name/envir through which the function was actually called.
   This generally seems fixable by moving the registerDebugHook
   call closer to the name/envir that will ultimately be called
   (e.g. call registerDebugHook directly from wrapFunctionLabel).

There still seems to be a problem here in that breakpoints in
RStudio are hit but then the IDE automatically runs "n" multiple
times. Also the unit tests don't currently pass, I haven't
investigated that yet.
2016-02-09 16:29:14 -08:00
Joe Cheng
2c04441591 Merge pull request #1105 from rstudio/travis-update
Take advantage of new travis features
2016-02-09 16:28:33 -08:00
Winston Chang
a4eab8e216 Grunt 2016-02-09 16:03:59 -06:00
Winston Chang
189f9589d4 Unset attributes in img that aren't present in new data 2016-02-09 16:02:39 -06:00
Hadley Wickham
880721e0d0 Take advantage of new travis features
This will cache package install between checks, which should make it run quite a bit faster - this is what @jimhester's has been working on
2016-02-09 14:02:33 -06:00
Winston Chang
6ab65e2031 Fix plot flickering on Safari and Firefox. Closes #776
Previously, a new img tag was added when a new plot was sent, but now it uses
the same img tag and changes the src attribute.
2016-02-09 11:08:25 -06:00
Winston Chang
e871934cfd Fix package name for Travis 2016-02-06 14:46:51 -06:00
Winston Chang
686390c1f2 Merge pull request #1096 from yihui/bugfix/datatables-warning
Fixes #561: make sure DataTables always gets a correct number of columns of data
2016-02-04 10:12:56 -06:00
Yihui Xie
a8b9fb1708 use the CRAN version of htmltools 2016-02-03 14:02:24 -06:00
Yihui Xie
55d3764169 Fixes #561: should discard the query when the number of columns in the request is different with the number of columns of the actual data 2016-02-03 10:54:37 -06:00
Winston Chang
cb5bc3d631 Merge pull request #1088 from rstudio/joe/bugfix/flexcol
Fix flexCol on RStudio Desktop for Win/Linux
2016-01-20 12:12:51 -06:00
Joe Cheng
543e66eb00 Fix flexCol on RStudio Desktop for Win/Linux
RStudio Desktop requires the older -webkit vendor-prefixed
flex box properties. I missed the one for flex-direction.
2016-01-20 09:20:22 -08:00
Winston Chang
b658983fb8 Remove JavaScript events vignette
This vignette has been migrated to a Shiny Dev Center article.
2016-01-15 15:30:24 -06:00
Winston Chang
cfb3e42337 Merge pull request #1080 from rstudio/internal-messages
Don't use sendCustomMessage for messages internal to Shiny
2016-01-15 12:19:23 -06:00
Winston Chang
36815b5e43 Concat and minify shiny.js 2016-01-15 11:54:10 -06:00
Winston Chang
897e077aca Convert internal use of sendCustomMessage to sendMessage 2016-01-15 11:53:51 -06:00
Winston Chang
f395960ffa Add session$sendMessage wrapper function 2016-01-15 11:46:23 -06:00
Winston Chang
fb301717f5 Bump version to 0.13.0.9000 2016-01-14 10:49:08 -06:00
Winston Chang
46da93519f Bump version to 0.13.0 2016-01-12 13:33:14 -06:00
Winston Chang
ce0f2c51a9 Use explicit namespaces 2016-01-12 13:33:14 -06:00
Winston Chang
04b4b8da4f Use --run-donttest when checking package 2016-01-12 13:16:18 -06:00
Winston Chang
877d7451dd Merge pull request #1073 from rstudio/joe/staticdocs-tweaks
Tweaks for improved staticdocs rendering
2016-01-12 13:00:07 -06:00
Joe Cheng
7e6a68a2b1 CRAN maintainers prefer \donttest over \dontrun 2016-01-12 10:10:16 -08:00
Joe Cheng
caca515ba0 Tweaks for improved staticdocs rendering
- \donttest -> \dontrun, otherwise staticdocs hangs
- Put NS before ns.sep so usage entries are in a better order
2016-01-11 12:20:19 -08:00
Winston Chang
d548b78dee Remove unneeded do.call
It's OK to remove this do.call now that we are using R6 instead of Ref Classes.
2016-01-08 16:19:08 -06:00
Joe Cheng
f2410abc48 Merge remote-tracking branch 'origin/image-attr'
Conflicts:
	inst/www/shared/shiny.js
	inst/www/shared/shiny.js.map
	inst/www/shared/shiny.min.js
	inst/www/shared/shiny.min.js.map
2016-01-08 10:55:21 -08:00
Joe Cheng
483a7d34c5 Merge pull request #1071 from rstudio/fix-hidden-slider
Fix hidden slider
2016-01-08 10:53:00 -08:00
Winston Chang
e872411285 Build and minify shiny.js 2016-01-08 10:00:22 -06:00
Winston Chang
fc7e6bf542 Revert "Simpler fix for updating hidden sliders (#1010)"
This reverts commit 4e1caee7da.
See https://github.com/rstudio/shiny/issues/1010#issuecomment-169971201
2016-01-08 10:00:05 -06:00
Winston Chang
16d42b6421 Add bootstrapLib to staticdocs index 2016-01-07 13:51:56 -06:00
Winston Chang
2f25d25eec Use setAttribute() function to set image attributes. Fixes #936 2016-01-06 15:03:18 -06:00
Winston Chang
be1081a4b9 Add note about printing ggplot2 graphics 2016-01-06 14:11:16 -06:00
Joe Cheng
1608b652d7 Fix unnecessary ::: 2016-01-05 14:02:16 -08:00
Winston Chang
5dd19a878c Bump version to 0.2.12.9009 2016-01-05 15:59:19 -06:00
Winston Chang
3314f4b5b8 Update NEWS 2016-01-05 15:59:11 -06:00
Winston Chang
5977e0fe89 Update NEWS 2016-01-05 15:30:59 -06:00
Winston Chang
f477dcba4a Merge pull request #1068 from rstudio/template-bootstrap
Pull out bootstrapLib into separate function
2016-01-05 15:30:32 -06:00
Winston Chang
6c5f0c5379 Pull out bootstrapLib into separate function 2016-01-05 14:57:53 -06:00
Winston Chang
257eb1bed0 Merge pull request #1067 from rstudio/joe/bugfix/module-progress
Fix progress for Shiny modules
2016-01-05 11:59:18 -06:00
Joe Cheng
9c4d142c2d Fix progress for Shiny modules
Too-specific class check was being used, interfered with the
"duck typed" session-like objects we use for modules.
2016-01-05 09:41:52 -08:00
Winston Chang
8e89a1f154 Add README file with info about jQuery UI 2016-01-05 11:03:34 -06:00
Winston Chang
b0952c0374 Use jQuery UI build without datepicker. Fixes #1042 2016-01-05 11:03:07 -06:00
Winston Chang
ac95dcb3f2 Fix head content location 2016-01-04 10:52:26 -06:00
Joe Cheng
ce4043f038 Update metadata 2015-12-31 11:07:35 -08:00
Joe Cheng
0d26857e31 Merge pull request #1031 from rstudio/template
Use templates from htmltools
2015-12-31 11:03:14 -08:00
Joe Cheng
85bea95f6b Merge pull request #1029 from rstudio/joe/feature/knit_print.reactive
Add knit_print.reactive
2015-12-30 14:31:26 -08:00
Winston Chang
10a46c507f Merge pull request #1059 from rstudio/joe/bugfix/gadgets
Fix stopApp bug, and fix flex box in RStudio
2015-12-30 09:38:24 -06:00
Joe Cheng
d35d76e1d0 Use flex box layout vendor prefixes
This fixes fillRow/fillCol for RStudio on Windows and Linux
2015-12-29 15:59:04 -08:00
Joe Cheng
aaa05b22df Return stopApp value without visibility info 2015-12-29 15:57:23 -08:00
Winston Chang
c5fa30f0de Make encoding tests work cleanly on different platforms 2015-12-29 15:41:49 -06:00
Joe Cheng
43fe1a9a0e Merge pull request #1057 from rstudio/joe/feature/gadget-cancel
runGadget automatically handles cancel button
2015-12-28 14:18:17 -08:00
Joe Cheng
aa296fcb69 Don't show call when user cancels gadget 2015-12-28 13:56:01 -08:00
Joe Cheng
b9c7023489 Refactor server function arg matching 2015-12-28 12:43:06 -08:00
Joe Cheng
efcd286039 Code review feedback 2015-12-28 11:56:13 -08:00
Joe Cheng
98014f9495 Code review feedback 2015-12-28 11:53:52 -08:00
Joe Cheng
2702a18ea2 Add stopApp test 2015-12-28 11:18:15 -08:00
Joe Cheng
4a8da3e1e2 runGadget handles cancel automatically (by default) 2015-12-27 23:46:47 -08:00
Joe Cheng
cfe38c00f3 Proper visibility and error handling from stopApp 2015-12-27 23:35:09 -08:00
Joe Cheng
af0463ed46 Update metadata 2015-12-23 17:47:24 -08:00
Joe Cheng
c02f4691e0 Merge pull request #1054 from rstudio/joe/feature/runGadget
Migrate runGadget and viewer functions from shinygadgets
2015-12-23 17:45:12 -08:00
Joe Cheng
5d89393fff Merge pull request #1039 from rstudio/joe/feature/fillPage
Add fillPage, flexRow, flexCol
2015-12-23 17:44:56 -08:00
Joe Cheng
e7ce28204b Remove dependency on newer htmltools
The css function is in htmltools 0.2.11, which isn't on CRAN
yet. Due to a perfect storm of release scheduling we need to
get fillPage onto shiny master before we have a chance to
put htmltools on CRAN.
2015-12-23 17:32:46 -08:00
Joe Cheng
8fc4a75e8c Specify remote repo for htmltools
Makes devtools install easier
2015-12-23 17:31:11 -08:00
Joe Cheng
26c89a09e8 Update staticdocs index 2015-12-23 17:31:11 -08:00
Joe Cheng
25a1493520 Add details to fillRow doc about containers 2015-12-23 17:31:10 -08:00
Joe Cheng
b18722f776 flex:none is more appropriate than flex:initial for weight=NA 2015-12-23 17:31:10 -08:00
Joe Cheng
3f3fd9ae21 Install htmltools from github until 0.2.11 goes to cran 2015-12-23 17:31:10 -08:00
Joe Cheng
94ea3c7dab Require htmltools 0.2.11 2015-12-23 17:31:10 -08:00
Joe Cheng
6c2fea7926 Rename flexRow/flexCol to fillRow/fillCol, other tweaks
I decided against the name flexRow/flexCol as the "flex" prefix
is too general for these implementations, which are mostly just
useful for filling the space with the children. Flex box has a
lot more features than that, such as centering, wrapping,
justifying, etc., but I don't currently know how to design an
API that presents the full power of flex box without also
presenting the full complexity of it as well.

This commit also includes some tweaks to the impl of flexfill
to fix the behavior of children with 100% size along the main
axis, and also introduces support for NA flex values, which
sizes the flex item according to its contents.
2015-12-23 17:31:10 -08:00
Joe Cheng
e08fd47b0e Add fillPage, flexRow, flexCol 2015-12-23 17:31:05 -08:00
Joe Cheng
0fd76e8768 Migrate runGadget and viewer functions from shinygadgets 2015-12-23 15:33:30 -08:00
Joe Cheng
72aaf3055a Update NEWS 2015-12-23 11:46:03 -08:00
Winston Chang
94a943a68c Merge pull request #1052 from rstudio/joe/font-awesome-4.5.0
Upgrade Font Awesome to 4.5.0
2015-12-23 13:08:27 -06:00
Joe Cheng
e867dcfdb1 Upgrade Font Awesome to 4.5.0 2015-12-23 11:03:33 -08:00
Joe Cheng
9a22a89b06 Add docs 2015-12-23 09:42:29 -08:00
Joe Cheng
791e8200bc Install htmltools from github until 0.2.11 goes to cran 2015-12-22 14:06:51 -08:00
Joe Cheng
d96217d49a Merge pull request #1049 from rstudio/joe/bugfix/http-iframe-stampede
Defer subapp iframe loading
2015-12-22 12:26:49 -08:00
Joe Cheng
6bfd65aa19 Guard against window.Shiny not being defined 2015-12-22 11:53:36 -08:00
Joe Cheng
2da9bc07ac Defer subapp iframe loading until main app has loaded
Fixes #1047 defer loading of iframes
2015-12-22 11:14:12 -08:00
Joe Cheng
6d7a562b7a Fix staticdocs
Without this fix, current version of staticdocs won't pull plotOutput
into the index page.
2015-12-21 11:57:01 -08:00
Joe Cheng
0aa1dfb8e1 Merge pull request #1032 from yihui/yihui/encoding-tests
Add some tests for character encodings
2015-12-17 13:36:26 -08:00
Winston Chang
e9e7dc298f Merge pull request #1037 from rstudio/joe/feature/req
Add `req` function for validating required inputs/values
2015-12-17 14:39:40 -06:00
Joe Cheng
ed3b71e396 Remove unnecessary environment() call 2015-12-17 11:58:17 -08:00
Joe Cheng
3450a037a9 Further simplification and more tests for req() 2015-12-17 11:29:54 -08:00
Joe Cheng
f57626d256 req() simplification 2015-12-17 11:16:09 -08:00
Joe Cheng
c1c3fa4d3a Fix a couple of req edge cases 2015-12-17 11:13:33 -08:00
Joe Cheng
300433f7de req() now short-circuits on falsy values 2015-12-17 10:53:13 -08:00
Joe Cheng
eee6f4ed81 Add req function for validating required inputs/values 2015-12-16 10:04:05 -08:00
Joe Cheng
2eb29bd8aa Merge pull request #1034 from rstudio/fix-hidden-slider
Simpler fix for updating hidden sliders (#1010)
2015-12-15 15:57:11 -08:00
Joe Cheng
3a0ce86f51 Remove unnecessary check (feedback from @wch) 2015-12-15 15:36:43 -08:00
Joe Cheng
6041b8cbb2 Roxygenize 2015-12-14 18:00:29 -08:00
Joe Cheng
3ba8fcb7b8 Merge pull request #1036 from rstudio/joe/bugfix/validation-error-behavior
Fix validation error handling
2015-12-14 17:16:04 -08:00
Joe Cheng
f74d9c93a2 Merge pull request #1035 from rstudio/joe/bugfix/multiline-label
Fix warnings when renderXXX is called with explicit namespace
2015-12-14 17:15:50 -08:00
Joe Cheng
739c162281 Fix warnings when renderXXX is called with explicit namespace
Calling shiny::renderText(...) instead of renderText(...) would
cause warnings.
2015-12-14 17:11:40 -08:00
Joe Cheng
a2700c900d Fix validation error handling
Validation errors were behaving too much like real errors: they were
being printed with stack traces, and passed to the options(shiny.error)
function. Also, if a reactive() cached a validation error, on future
calls the error would be re-raised (which is correct) without the
custom class names attached (which is not).
2015-12-14 16:31:57 -08:00
Winston Chang
4e1caee7da Simpler fix for updating hidden sliders (#1010)
This also reverts the previous fix, #1026
2015-12-10 15:49:23 -06:00
Yihui Xie
76a54249bb Add some tests for character encodings 2015-12-10 15:23:31 -06:00
Winston Chang
0e894cb043 Use templates from htmltools 2015-12-10 15:11:03 -06:00
Winston Chang
01bbee59eb Merge pull request #1023 from yihui/bugfix/1018
Fixes #1018: make sure the selected value is always returned from sever-side selectize
2015-12-10 13:44:24 -06:00
Joe Cheng
26a0c3520c Add knit_print.reactive
Allows us to drop reactive expressions right into Rmd docs
with runtime:shiny and have them stay up-to-date.
2015-12-09 16:34:55 -08:00
Yihui Xie
6056c35de3 add a news item, and run grunt 2015-12-09 11:56:13 -06:00
Yihui Xie
4202991ca5 Fixes #1018: make sure the selected value is always returned from server-side selectize 2015-12-09 11:52:50 -06:00
Joe Cheng
788931c7c7 Merge pull request #1027 from yihui/yihui/srcfilecopy
Check R version at runtime (#968)
2015-12-09 09:48:59 -08:00
Yihui Xie
b2d0505c7c Check R version at runtime (#968) 2015-12-08 20:33:52 -06:00
Winston Chang
8b710d651f Merge pull request #1026 from rstudio/joe/bugfix/hidden-slider-update
Fix #1010: updateSliderInput doesn't update hidden sliders
2015-12-08 19:50:12 -06:00
Joe Cheng
93697bb01d Merge pull request #1025 from yihui/bugfix/source-utf8
Fixes #1003: correctly parse source code that can be represented with native encoding
2015-12-08 15:51:51 -08:00
Joe Cheng
89cd58e4f8 Fix #1010: updateSliderInput doesn't update hidden sliders 2015-12-08 11:13:18 -08:00
Yihui Xie
a622f029a0 Fixes #1003: when the source code can be represented via the native encoding on Windows, rewrite the code to a temporary file with the native encoding and parse it 2015-12-07 16:28:45 -06:00
Winston Chang
97afb52904 Re-document with Roxygen2 5.0.1 2015-12-02 15:43:25 -06:00
Joe Cheng
02ea31be08 Fix #1020: Graphics are cut off 2015-12-01 13:47:26 -08:00
david.zotloeterer
d1353e8eae fixed custom message obj 2015-12-01 13:36:32 +01:00
david.zotloeterer
935a76d16b cleanup 2015-12-01 13:29:41 +01:00
david.zotloeterer
db4c41f420 grunted 2015-12-01 12:59:48 +01:00
david.zotloeterer
62f5af8e0b fixed typo 2015-12-01 12:42:05 +01:00
david.zotloeterer
ff9aefb649 more tagging 2015-12-01 12:39:41 +01:00
david.zotloeterer
2b10d03e1f added binary tags 2015-12-01 12:11:44 +01:00
david.zotloeterer
a27efbd937 added binary messages, yes, ws can do dat! 2015-12-01 12:03:07 +01:00
Joe Cheng
b5e49a6619 Fix bugs reported by @daattali
- reactive srcrefToLabel call fails if code is pasted in at RStudio console
- Stack trace fails when promise (!?) is in call stack
2015-11-24 11:55:08 -08:00
Joe Cheng
179c931f85 Bump version 2015-11-23 10:58:30 -08:00
Joe Cheng
4d3fa2c8ac Merge pull request #1011 from rstudio/joe/feature/better-errors
Better errors
2015-11-20 12:56:24 -08:00
Joe Cheng
8e4f7387d0 Better stack traces for observeEvent and eventReactive 2015-11-16 13:10:53 -08:00
Joe Cheng
feb630b2c5 Catch errors when trying to print stack trace
No known errors will occur when printing the stack trace, but since
this is fairly complicated code executing when an error has already
happened, better to be on the defensive.
2015-11-16 13:08:34 -08:00
Joe Cheng
948dfbb56b More tests 2015-11-16 12:50:20 -08:00
Joe Cheng
5c3ac75b34 Errors in ui function should get stack traces 2015-11-16 12:46:22 -08:00
Joe Cheng
adc5c8e37a Normalize shiny dir in smoketest stack traces 2015-11-16 12:45:59 -08:00
Joe Cheng
52d594c143 Quick and dirty smoke test infrastructure 2015-11-16 12:29:02 -08:00
Joe Cheng
1018b0d966 Errors in ui.R, server.R, server func, etc. all get stack traces 2015-11-16 10:48:16 -08:00
Joe Cheng
0ce153d788 Doc updates
Code had to be rearranged to make the functions show up in the
help docs in the right order
2015-11-14 00:26:23 -08:00
Joe Cheng
ff9756c739 Add more exports, tests 2015-11-14 00:17:19 -08:00
Joe Cheng
b3dd7e5397 Remove support for shiny.observer.error option
It is dangerous to set this on a per-process basis. If we even
still want the ability to have observer errors not kill the
session (debatable) we should do so by having an option on the
session object that is set when the shiny server function runs.

Not only does this remove support for the option, but now we
will refuse to connect and will abort the session if the option
is set to a non-NULL value. This is to prevent apps from moving
forward with the assumption that their option will work, when
it really won't. (I doubt anyone is using it anyway, it's so
obscure...)
2015-11-13 18:13:14 -08:00
Joe Cheng
6ac0a80896 Update NEWS with stack trace announcement 2015-11-13 17:58:18 -08:00
Joe Cheng
93f774c7e7 Add exports/docs 2015-11-13 17:52:26 -08:00
Joe Cheng
661c08549d Automatically wrap installExprFunction with function labels
This lowers the burden on renderXXX functions having nice stack traces
2015-11-13 16:43:15 -08:00
Joe Cheng
c8acc44012 Add comments to stacktraceon/off directives indicating their partners 2015-11-13 16:25:22 -08:00
Joe Cheng
aabf00659e Random improvements to stack traces
- More selective removal of frames at end of call stack
- Add withLogErrors, printError, stripStackTrace convenience funcs
- Properly capture/log errors for various levels of unhandled errors
- Unhide stacks for flush/flushed/sessionended callbacks
2015-11-13 16:03:18 -08:00
Joe Cheng
a9bc41492c Collapse stack trace to eliminate irrelevant bits 2015-11-13 12:36:55 -08:00
Winston Chang
12b0484e9a Merge pull request #875 from wch/rendertable-args
Separate xtable from print.xtable args. Closes #761
2015-11-13 11:48:41 -06:00
Joe Cheng
d3605dbcb3 Collapse parts of the stack 2015-11-12 16:40:56 -08:00
Joe Cheng
d9a016f94c Move error-handling logic into conditions.R 2015-11-11 16:20:26 -08:00
Joe Cheng
a13657ac23 Work properly with non-call sys.call() objects 2015-11-11 15:54:03 -08:00
Joe Cheng
d6c95a9e89 wip 2015-11-11 12:14:42 -08:00
Winston Chang
825e9e04c1 Get xtable args using formals() 2015-11-05 13:04:43 -06:00
Winston Chang
c596e44c5a Separate xtable from print.xtable args. Closes #761 2015-11-05 13:01:01 -06:00
Winston Chang
66be9004fe Move renderTable to separate file 2015-11-05 12:59:04 -06:00
Winston Chang
119ebb0f07 Merge pull request #1005 from rstudio/joe/bootstrap-3.3.5
Upgrade bootstrap to 3.3.5
2015-11-05 12:43:34 -06:00
Joe Cheng
d509fcac29 Merge pull request #1004 from rstudio/joe/feature/autoreload
Implement autoreload
2015-11-05 10:43:13 -08:00
Joe Cheng
c79e933586 Merge pull request #1002 from rstudio/joe/bugfix/nested-scopes
Fix nested scopes
2015-11-05 10:32:23 -08:00
Joe Cheng
3c3cfc02a0 Merge pull request #997 from wch/download-fix
Update download to work correctly with R 3.2.2 on Mac. Fixes #996
2015-11-05 10:27:51 -08:00
Joe Cheng
e32de7b940 Update bootstrap htmlDependency version 2015-11-05 07:38:00 -08:00
Joe Cheng
d7b1759afb Upgrade bootstrap to 3.3.5 2015-11-04 22:56:31 -08:00
Joe Cheng
e391c1fda3 Implement autoreload 2015-11-04 13:44:38 -08:00
Joe Cheng
46d8d3b469 Fix nested scopes
The session$makeScope function was not correctly taking the session's
own namespace into account (i.e. all makeScope() method calls were
being performed against the root session).
2015-11-03 12:33:39 -08:00
Joe Cheng
9fde7509fa Merge pull request #1000 from rstudio/joe/feature/invalidatelater-default-session
Don't require session to be explicitly passed to invalidateLater
2015-11-02 16:21:43 -08:00
Joe Cheng
a767a61f43 Don't require session to be explicitly passed to invalidateLater
These functions were created before getDefaultReactiveDomain()
existed, so the only way to get ahold of the current session was
if the caller explicitly passed it.

This is slightly backwards incompatible, in that existing calls
to invalidateLater() that don't pass a session argument will
behave slightly differently (bound to the current session instead
of to no session), but those calls would have triggered a warning
for all but the very earliest versions of Shiny.
2015-11-02 14:19:29 -08:00
Joe Cheng
ad28e03536 Merge pull request #999 from yihui/bugfix/ie9-upload
Fixes #990: revert to checking if FileList is supported by the browser
2015-11-02 11:13:57 -08:00
Yihui Xie
5f9e9c2e03 grunt 2015-11-02 12:21:56 -06:00
Yihui Xie
2be6d7a65c Fixes #990: revert to checking if FileList is supported by the browser, instead of checking IE8 literally (partially reverted a41e1dafc2) 2015-11-02 12:21:30 -06:00
Winston Chang
712c4cb985 Update download to work correctly with R 3.2.2 on Mac. Fixes #996 2015-10-30 12:08:48 -05:00
Winston Chang
7948a0a4fa Merge pull request #993 from rstudio/joe/feature/reactlog-labels
Cleaner reactlog labels for reactives and outputs
2015-10-30 11:57:57 -05:00
Joe Cheng
ce9e95f256 Fix parseQueryString example (thanks Chris Beeley) 2015-10-29 16:15:47 -07:00
Joe Cheng
7ed5ca94a2 reactlog label code review feedback
- Don't clobber explicitly-provided label
- Let `reactives$x1 <- reactive(...)` work
2015-10-29 10:27:06 -07:00
Winston Chang
e635589c52 Merge pull request #992 from rstudio/joe/feature/reactlog-time
Add timing data to reactlog entries
2015-10-29 10:06:08 -05:00
Joe Cheng
490721437f Merge pull request #994 from RCura/patch-1
Correct a regression within modules
2015-10-28 18:23:36 -07:00
Robin Cura
7e25a1566f Correct a regression within modules
Commit 07f2792cf9 introduced an error, replacing `e$parent = parentSession` with `e$parent <= parentSession`, while it should have been `e$parent <- parentSession`
2015-10-29 02:03:12 +01:00
Joe Cheng
c08b3b0c30 Update metadata 2015-10-28 15:30:07 -07:00
Joe Cheng
f1de132a2a Merge pull request #988 from rstudio/joe/feature/namespaces
Shiny modules
2015-10-28 15:22:57 -07:00
Joe Cheng
c440c60bdf Cleaner reactlog labels for reactives and outputs
Instead of showing the code, try to just show the name
of the reactive/output. Uses a fairly flaky algorithm
for determining the name of the reactive; will only
work in cases where the definition of the reactive
begins with "foo <- reactive({".
2015-10-28 14:37:00 -07:00
Joe Cheng
c367176a17 Add timing data to reactlog entries 2015-10-28 13:49:39 -07:00
Joe Cheng
3d13c39a4c Also override registerDataObj (essential for data table, DT, and selectize server mode) 2015-10-27 16:33:46 -07:00
Joe Cheng
07f2792cf9 Change evil = to righteous <- 2015-10-27 15:01:44 -07:00
Joe Cheng
303fce5f15 Merge pull request #983 from wch/clear-checkbox
updateCheckboxGroup: allow clearing all choices. Fixes #981
2015-10-27 15:00:20 -07:00
Joe Cheng
46c8bfdd34 Merge pull request #979 from wch/profiling-enhancements
Enhancements to help profiling
2015-10-27 14:59:59 -07:00
Winston Chang
c36a22ad5e Add information about clearing choices 2015-10-23 16:04:17 -05:00
Winston Chang
49eba95a9c Simplify function naming 2015-10-23 15:48:33 -05:00
Winston Chang
2dacc6ce40 Use cleaner method for generating function 2015-10-23 15:44:24 -05:00
Winston Chang
5ccf02f5c3 Merge pull request #984 from rstudio/update-jquery
Update to jQuery 1.11.3 and jQuery UI 1.11.4
2015-10-23 15:08:27 -05:00
Joe Cheng
86c67de8ff Add session$ns(); some light refactoring; add tests; fix staticdocs 2015-10-20 23:49:24 -07:00
Joe Cheng
dac7eb5997 Simplify modules, by removing moduleUI and path arguments 2015-10-20 15:12:11 -07:00
Winston Chang
fd725552a5 Update to jQuery UI 1.11.4 2015-10-19 13:44:23 -05:00
Winston Chang
1e1a897970 Update to jQuery 1.11.3 2015-10-19 13:31:44 -05:00
Joe Cheng
59a643c006 Update metadata 2015-10-16 10:24:05 -07:00
Joe Cheng
1a492208e6 Merge pull request #982 from rstudio/feature/single-file-runapp
Let runApp accept single .R file parameters
2015-10-16 10:16:29 -07:00
Winston Chang
bc0a19f55d updateCheckboxGroup: allow clearing all choices. Fixes #981 2015-10-16 11:44:09 -05:00
Jonathan McPherson
85e2e00bc4 let runApp accept single .R file parameters 2015-10-16 09:22:44 -07:00
Joe Cheng
93dd8bbf28 Merge pull request #980 from rstudio/joe/bugfix/select-value-escaping
Fix improperly escaped quote chars in select choices
2015-10-15 12:56:54 -07:00
Joe Cheng
2f15a219df Fix improperly escaped quote chars in select choices 2015-10-15 12:49:50 -07:00
Yihui Xie
4fc73b1344 A news item for #968 2015-10-15 13:45:00 -05:00
Joe Cheng
48b56ba08d Merge pull request #968 from yihui/bugfix/961-unicode
A more fundamental fix to the Unicode issue
2015-10-15 11:17:45 -07:00
Joe Cheng
94ca733c7c Merge pull request #967 from rstudio/joe/bugfix/placeholder
Add placeholder parameter to textInput
2015-10-15 11:15:10 -07:00
Winston Chang
4af2436a0e Rename 'func' to more descriptive name 2015-10-14 16:40:33 -05:00
Winston Chang
20c2bb9d50 Simplify try(tryCatch()) to just tryCatch()
This also has the benefit of printing a more helpful error message at
the console. It now indicates which output an error occurred in.
2015-10-14 16:40:33 -05:00
Winston Chang
33bac0db3c Add function relabeler and relabel outputs 2015-10-14 16:40:33 -05:00
Winston Chang
8893db9098 Update NEWS 2015-10-12 22:39:51 -05:00
Winston Chang
c46658a5c8 Correctly handle unit and unit.list objects. Closes #962 2015-10-12 22:31:32 -05:00
Joe Cheng
5f651aed3e LICENSE typo 2015-10-12 12:32:00 -04:00
Joe Cheng
534bc9c6e2 Pass tests 2015-10-05 15:15:54 -04:00
Joe Cheng
bb09885237 Add callModule/moduleUI functions; scope sendInputMessage 2015-10-05 14:56:01 -04:00
Joe Cheng
3ff6aaa6db Add namespacing functionality
- Need to carefully review ShinySession, think about
  each and every public method and whether it should
  be passthrough or do something different for a
  namespaced session.

- It would be nice if we do the namespace splitting
  at the server.R level and actually have numerous
  reactivevalues objects for inputs, one for each
  namespace. This will make the reactive hooks for
  names() and reactiveValuesToList() correct, as
  right now they will oversubscribe if you're in a
  namespaced session. Also it would prevent outer
  sessions from seeing the values of their child
  namespaces. (Though is that good or bad...?)
2015-10-02 12:51:18 -07:00
Joe Cheng
fa7c034d16 Merge pull request #955 from rstudio/joe/feature/reactlog-bysession
Fix couple of issues with reactlog
2015-09-24 09:54:35 -07:00
Joe Cheng
ca870ccd75 Merge pull request #966 from rstudio/joe/bugfix/showcase-highlighting
Fix highlighting of reactives in showcase mode
2015-09-24 09:54:01 -07:00
Yihui Xie
89fe2ff217 a more fundamental fix of the Unicode issue
for R <= 3.2.2, Unicode chars don't work for shiny mainly because we want to
preserve the source reference, and unfortunately srcfilecopy() fails because of
the bug https://bugs.r-project.org/bugzilla3/show_bug.cgi?id=16264

here I use lines = '' to get around the bug, and assign the source lines to
the srcfile object later, so there is no grep("\n", multibyte_chars) occuring

I also replaced source() with a custom version, which is much simpler and works
better with Unicode chars
2015-09-23 23:00:20 -05:00
Joe Cheng
6c6775376e Add placeholder parameter to textInput 2015-09-23 18:28:08 -07:00
Yihui Xie
bd3b3881d8 after reading a file as UTF-8, try to convert it to native encoding on Windows only if the conversion is not lossy 2015-09-23 18:33:01 -05:00
Yihui Xie
078189599c the check is.na(iconv(x, 'UTF-8')) does not really make sense
e.g. iconv('\u2264', 'UTF-8') converts the smaller than or equal sign to an
equal sign in the English (US) locale, which is lossy

we just assume the input is UTF-8 instead, and do not fall back to native
encoding any more
2015-09-23 18:31:16 -05:00
Yihui Xie
9afcd2a411 don't declare encoding on the anonymouse file connection
otherwise writeLines(useBytes = TRUE) may not work (#961)
2015-09-22 01:11:38 -05:00
Yihui Xie
0afd1649c1 textConnection() can be lossy; use an anonymous file connection instead to preserve UTF-8 characters 2015-09-22 01:11:37 -05:00
Yihui Xie
0947a63103 make sure writeLines() does not convert text to native encoding 2015-09-22 01:11:32 -05:00
Yihui Xie
79223bddc5 make sure the UI HTML is rendered into a connection with UTF-8 encoding 2015-09-21 22:25:12 -05:00
Yihui Xie
1871dd6b71 convert the result of readLines() to UTF-8 using enc2utf8() instead, since enc2native() can be lossy 2015-09-21 21:49:12 -05:00
Yihui Xie
4adc3088d1 fixes #961: the JSON string from jsonlite::toJSON() is always encoded in UTF-8, so there is no need to re-encode it
actually re-encoding the string with native encoding can be lossy (some UTF-8 characters may not be representable in the native encoding)
2015-09-21 21:46:11 -05:00
Yihui Xie
79dd7e1bf5 shiny requires R >= 3.0.0 2015-09-21 21:44:03 -05:00
Joe Cheng
6718d377bb Fix and enhance reactlog
* Reactlog shortcut was broken due to reactlog.js not being included in
  the gruntfile
* Reactlog has always shown every reactive event since the beginning of
  the process (or at least since options(shiny.reactlog=TRUE)). This
  commit makes it so Ctrl+F3 invocation only shows reactives that either
  belong to no session (e.g. observers and reactives declared at the top
  of server.R), or belong to this session.
2015-09-13 02:46:52 -07:00
Joe Cheng
d4e3329d7a Fix highlighting of reactives in showcase mode
This has been broken since we switched to jsonlite. Reactives
don't highlight because their srcref is in an S3(?) class that
jsonlite doesn't recognize, whereas RJSONIO would treat it as
a numeric vector.
2015-09-12 20:20:13 -07:00
Joe Cheng
99295f0983 Bump version, update NEWS 2015-09-09 22:13:45 -07:00
Winston Chang
3606c36cb9 Merge pull request #950 from rstudio/joe/feature/grunt-clean
Add 'grunt clean' to delete shiny build artifacts
2015-09-09 15:49:02 -05:00
Winston Chang
3d5c184acc Merge pull request #949 from rstudio/joe/feature/shared-brush-id
Allow shared brush IDs
2015-09-09 15:48:43 -05:00
Joe Cheng
9e03b17498 Add 'grunt clean' to delete shiny build artifacts 2015-09-09 12:19:43 -07:00
Joe Cheng
129714b044 Allow shared brush IDs 2015-09-09 12:12:47 -07:00
Joe Cheng
67823556d2 Merge pull request #939 from yihui/bugfix/selectize-selected
Fixes #929: defer setValue() for selectize until the options have been loaded from server
2015-09-09 12:10:03 -07:00
Yihui Xie
273e71e3c4 run grunt 2015-09-09 13:38:51 -05:00
Yihui Xie
076ac26929 call setValue() only once
otherwise every time an Ajax response is returned (e.g. during searching), the value is set to data.value
2015-09-09 13:29:37 -05:00
Yihui Xie
5a022b0a2c upgrade selectize.js from 0.11.2 to 0.12.1 to fix the ordering issue in #929
also fixes #865
2015-09-09 13:29:37 -05:00
Yihui Xie
9ab493a81f make sure mop is numeric
it is funny that head(1:11,'100') produces a bunch of NA's, but  head(1:11,'12') does not
2015-09-09 13:29:37 -05:00
Yihui Xie
dfc1f32595 Fixes #929: defer setValue() for selectize until the options have been loaded from server
Previously I was using a hack to set the selected value of selectize, i.e. add the selected option(s) to selectize via addOptions() (because the selected option(s) may not have existed); this hack can be removed and we can set the value in the `success` callback of the Ajax request, by which time the options will be available
2015-09-09 13:29:37 -05:00
Joe Cheng
e6fd30fb78 Merge pull request #935 from yihui/doc/events-vignette
Add a package vignette for the JS events
2015-09-09 10:33:52 -07:00
Joe Cheng
c8d338912a Merge pull request #918 from rstudio/joe/bugfix/binding-getid
Fix #676: getId(el) not being used in output binding
2015-09-09 10:33:45 -07:00
Winston Chang
d9d9e0b33f Add info about printing ggplot objects 2015-09-08 15:07:40 -05:00
Yihui Xie
1da7b83956 Bump version 2015-09-04 20:54:30 -05:00
Yihui Xie
29c545d2e3 Bump fontawesome version after #932 2015-09-04 20:53:54 -05:00
Joe Cheng
431b345c82 Fix #676: getId(el) not being used in output binding 2015-09-04 15:14:04 -07:00
Joe Cheng
8773b1b38f Merge pull request #946 from yihui/bugfix/recalculating
Typo: name -> message.name
2015-09-04 14:53:43 -07:00
Yihui Xie
52efb3dc16 Typo: name -> message.name 2015-09-04 15:43:21 -05:00
Yihui Xie
9ccd179b04 document the rest of events: shiny:conditional, shiny:visualchange, shiny:recalculating, shiny:recalculated 2015-09-04 15:09:34 -05:00
Joe Cheng
a8b35c49a7 Merge pull request #932 from dselivanov/master
Bump fontawesome version to 4.4.0, fixes #913
2015-09-04 12:15:31 -07:00
Peter K. Shultz
4e027f1a45 Update README.md
Add missing period.
2015-09-04 12:13:28 -07:00
Joe Cheng
119182454b Merge pull request #943 from yihui/feature/events-more
Events shiny:visualchange, shiny:conditional, and shiny:recalculating
2015-09-04 11:34:48 -07:00
Yihui Xie
04e10a4f0d Run grunt 2015-09-02 12:30:22 -05:00
Yihui Xie
4e5c5f9c5b Move the shiny:conditional event to the top of $updateConditionals() 2015-09-02 12:29:37 -05:00
Yihui Xie
1ee2a25eca Trigger the recalculating event on null when the binding does not exist 2015-09-02 12:29:01 -05:00
Yihui Xie
838e132515 Trigger shiny:visualchange in doSendOutputHiddenState() as well. Added a 'visible' property to the event object. 2015-08-31 17:07:11 -05:00
Yihui Xie
da76a843ee DO not assume '# + message.name' is the element id. Find the element through this.$bindings[name].el instead. 2015-08-31 17:02:14 -05:00
Yihui Xie
b0676b8b31 Trigger shiny:recalculated after the calculation is done 2015-08-31 16:38:46 -05:00
Yihui Xie
83c3656d29 Events shiny:visualchange, shiny:conditional, and shiny:recalculating 2015-08-31 15:58:05 -05:00
Yihui Xie
5ddd6cc94e add a summary section to the events vignette 2015-08-27 23:21:36 -05:00
Yihui Xie
90419765af Merge pull request #938 from yihui/bugfix/933
Fixes #933: make sure type is of length one
2015-08-26 11:27:05 -05:00
Yihui Xie
acad9354a6 Fixes #933: make sure type is of length one 2015-08-26 10:48:38 -05:00
Yihui Xie
9105dd7b04 Add a package vignette for the JS events 2015-08-24 15:25:58 -05:00
Joe Cheng
71adee1f38 Merge pull request #930 from yihui/feature/events
More JS events
2015-08-24 12:50:10 -07:00
Yihui Xie
3cbe3831ec Run grunt 2015-08-21 16:19:02 -05:00
Yihui Xie
619aa4f05a Events shiny:busy and shiny:idle
Keep track of the number of observer callbacks during addPendingFlush() and executeFlushCallbacks(). Send a custom message when the number is 0.
2015-08-21 16:12:45 -05:00
Yihui Xie
4df37d6f3e The shiny:updateinput event for inputs 2015-08-21 16:10:01 -05:00
Yihui Xie
58f8b482f5 The message object may be exactly false (or a falsy value), in which case shiny will fail to send the message to the handler. Use .hasOwnProperty() instead. 2015-08-21 16:09:25 -05:00
Yihui Xie
168f5e32af The shiny:message event 2015-08-21 16:08:16 -05:00
Yihui Xie
06bf28f10c Events shiny:value and shiny:error for outputs 2015-08-21 16:07:33 -05:00
Yihui Xie
620fdc0d9f The shiny:inputchanged event 2015-08-21 16:06:56 -05:00
Yihui Xie
bdac0e2456 Events shiny:bound and shiny:unbound for inputs and outputs 2015-08-21 16:06:00 -05:00
Dmitry Selivanov
60a57a0a40 Bump fontawesome version to 4.4.0, fixes #913 2015-08-20 12:34:52 +03:00
Yihui Xie
a242ae3849 Merge pull request #920 from yihui/yihui/selectize-dragdrop
fixes #902: add jQueryUI dependency when the drag_drop plugin is used in selectize
2015-08-06 21:46:30 -05:00
Yihui Xie
ced4060b5c fixes #902: add jQueryUI dependency when the drag_drop plugin is used in selectize 2015-08-06 16:59:51 -05:00
Winston Chang
0b3eb7a237 Merge tag 'v0.12.2'
Shiny 0.12.2
2015-08-05 15:08:21 -05:00
Winston Chang
c82f87cd76 Fix NEWS formatting 2015-08-04 23:05:30 -05:00
Winston Chang
51d8a6d9bf Bump version to 0.12.2 2015-08-04 23:00:34 -05:00
Winston Chang
d334aa2088 Merge branch 'http-head' 2015-08-04 22:59:49 -05:00
Winston Chang
710e003bdc Update httpuv version 2015-08-04 22:59:26 -05:00
Winston Chang
b2f5b4f861 Update NEWS 2015-08-04 22:58:21 -05:00
Winston Chang
0ac87930c8 Add support for HTTP HEAD requests 2015-08-04 22:58:21 -05:00
Winston Chang
241a482236 Add explicit namespace to non-base functions 2015-08-04 12:30:41 -05:00
Winston Chang
2abaffafcf Move imageOutput docs to plotOutput 2015-08-04 12:23:06 -05:00
Winston Chang
4545fedf31 Update NEWS 2015-08-03 16:05:39 -05:00
Joe Cheng
a47a690a68 Merge pull request #909 from rstudio/joe/bugfix/runGist
Fix runGist
2015-07-22 14:08:05 -07:00
Joe Cheng
f89c44e899 Fix runGist
Looks like GitHub changed the format of gist downloads from .tar.gz
to .zip
2015-07-22 10:30:57 -07:00
Winston Chang
59b0df5c82 Concat and minify shiny.js 2015-07-21 13:01:16 -05:00
Yihui Xie
5ec6ffb30a Merge pull request #905 from rstudio/joe/doc-tweaks
Doc tweaks (fixes #898)
2015-07-21 12:51:28 -05:00
Winston Chang
5956d2009c Minor code cleanup in slider JS code 2015-07-21 12:32:40 -05:00
Winston Chang
d9c7f21c02 Make updateSliderInput work with date/datetimes. Fixes #904 2015-07-21 12:32:18 -05:00
Winston Chang
926e508b8d Fix updateSliderInput example code 2015-07-21 12:31:31 -05:00
Winston Chang
ac83772945 Don't use scientific notation for sending slider values 2015-07-21 12:31:17 -05:00
Joe Cheng
cddf5cf70f Doc tweaks 2015-07-21 10:15:04 -07:00
Winston Chang
d53acdb46a Update NEWS 2015-07-20 14:14:38 -05:00
Winston Chang
cfae8f4fc6 Update to ion.rangeSlider 2.0.12 2015-07-20 14:09:26 -05:00
Joe Cheng
74cd4cecbf Merge remote-tracking branch 'yihui/feature/events'
Conflicts:
	inst/www/shared/shiny.js
	inst/www/shared/shiny.js.map
	inst/www/shared/shiny.min.js
	inst/www/shared/shiny.min.js.map
2015-07-16 10:24:49 -07:00
Joe Cheng
3e9e6a1389 Merge pull request #885 from rstudio/slider-improvements
Slider improvements
2015-07-16 10:21:25 -07:00
Joe Cheng
9788450c08 Merge pull request #874 from wch/file-remove
Remove uploaded files when session ends. Fixes #798
2015-07-16 10:02:27 -07:00
Yihui Xie
10b27aed34 grunt build and bump version 2015-07-14 13:52:49 -05:00
Joe Cheng
64f95be828 Merge pull request #892 from yihui/feature/events-connect
Events shiny:connected and shiny:disconnected
2015-07-14 11:35:49 -07:00
Yihui Xie
a54634023b trigger shiny:connected when the socket is opened and shiny:disconnected when it is closed 2015-07-14 13:22:55 -05:00
Winston Chang
9d942b78ef Merge pull request #881 from yihui/updateNavbarPage
Add two aliases of updateTabsetPanel(): updateNavbarPage() and updateNavlistPanel()
2015-07-03 11:00:33 -05:00
Winston Chang
4cd5357241 Set dragRange=TRUE as the default 2015-07-02 20:25:42 -05:00
Winston Chang
f985a96988 Concat and minify shiny.js 2015-07-02 16:50:43 -05:00
Winston Chang
0e3938da79 Add timezone support 2015-07-02 16:50:43 -05:00
Winston Chang
ec9bfc4731 sliderInput: add timeFormat argument 2015-07-02 16:50:43 -05:00
Winston Chang
9b91ebb8d2 Add strftime Javascript library 2015-07-02 16:50:43 -05:00
Winston Chang
da3f2367d7 Add range dragging functionality 2015-07-02 16:50:43 -05:00
Winston Chang
17cdeec34b Add Date and POSIXt support to sliders 2015-07-02 16:50:43 -05:00
Winston Chang
3446afd087 Move input handlers to separate file 2015-07-02 16:50:43 -05:00
Winston Chang
b12fef652c Update to ionRangeSlider 2.0.10 2015-07-02 16:50:43 -05:00
Winston Chang
21c7193281 Remove unneeded copy of normalize.css 2015-07-02 12:48:16 -05:00
Yihui Xie
a5e64274a2 Add two aliases of updateTabsetPanel(): updateNavbarPage() and updateNavlistPanel()
https://groups.google.com/d/msg/shiny-discuss/8VctqPqeurw/uAQIBvA1CpAJ
2015-07-02 01:37:14 -05:00
Winston Chang
3817202875 Make sure that directory removal is safe 2015-07-01 13:41:54 -05:00
Winston Chang
874fcb12a1 Remove uploaded files when session ends. Closes #798 2015-07-01 13:32:06 -05:00
Winston Chang
e0c5783703 Refactor fileUpoadContext to use private members 2015-07-01 13:32:05 -05:00
Winston Chang
a57e037b05 Fix docs for submitButton 2015-06-26 16:40:32 -05:00
Winston Chang
8546918cbb Merge pull request #873 from wch/input-width
Add width option to input functions
2015-06-18 13:14:54 -05:00
Winston Chang
82284029f2 Update NEWS 2015-06-18 13:12:49 -05:00
Winston Chang
7c20e865a5 Add width option to input functions. Closes #834, closes #589 2015-06-18 13:12:49 -05:00
Winston Chang
79267d4e12 Move input functions to separate files 2015-06-18 10:47:00 -05:00
Winston Chang
50aeb70597 Update NEWS with changes from 0.12.1 2015-06-18 10:46:26 -05:00
Joe Cheng
1d22a79074 Bump version 2015-06-15 08:47:49 -07:00
Joe Cheng
7f442f4206 Un-deprecate data table functions until DT stabilizes 2015-06-11 23:27:21 -07:00
Yihui Xie
985326989c Bump version after #857 2015-06-11 00:09:13 -05:00
Joe Cheng
be8f2afa37 Merge pull request #857 from rstudio/joe/bugfix/rebind
Fix #856: Outputs can not be unbound and re-bound
2015-06-08 18:08:19 -07:00
Joe Cheng
98882984b4 Fix #856: Outputs can not be unbound and re-bound 2015-06-08 16:56:08 -07:00
Winston Chang
a6cd0fdb85 Update NEWS 2015-06-03 14:03:16 -05:00
Winston Chang
7bc5ba7e9a Merge pull request #852 from rstudio/slider-motion
Slider fixes
2015-06-03 13:47:51 -05:00
Winston Chang
37e552cd36 Move sliderInput code into separate file 2015-06-02 15:36:03 -05:00
Winston Chang
51e2a4de7d Concat and minify shiny.js 2015-06-02 14:14:54 -05:00
Winston Chang
91ce2fcb06 Remove no-longer-needed workaround 2015-06-02 14:14:54 -05:00
Winston Chang
925a379702 Don't overshoot end of slider
This previously resulted in a bug where the animation would loop even if
loop=FALSE.
2015-06-02 14:14:54 -05:00
Winston Chang
3153cfd0ff Move both handles when animating double sliders 2015-06-02 14:14:54 -05:00
Winston Chang
ac8831b4c7 Use methods() instead of .S3methods(). Fixes #849
The .S3methods() function was introduced in R 3.2.0, so this code was broken
on older versions of R.
2015-06-02 14:14:31 -05:00
Joe Cheng
acc535e1a4 Merge pull request #850 from rstudio/min-option
Add shiny.minified option for minified JavaScript. Closes #826
2015-06-01 21:54:33 -07:00
Winston Chang
fdacb4fe7d Add shiny.minified option for minified JavaScript. Closes #826 2015-06-01 20:58:10 -05:00
Winston Chang
fc7208469d Add staticdocs entries for interactive plots 2015-05-26 22:44:26 -05:00
Winston Chang
5c38cb733a Safer method for finding which method would be called 2015-05-26 17:05:10 -05:00
Winston Chang
515a67a320 Don't attempt to extract coordmap when print.ggplot is not used (#841) 2015-05-21 17:00:51 -05:00
Winston Chang
941348f1db Override print.ggplot method in renderPlot. Fixes #841 2015-05-21 16:45:39 -05:00
Joe Cheng
8d7752b0bc Merge pull request #840 from rstudio/joe/bugfix/methods-depend
Depend on methods so Rscript doesn't fail
2015-05-21 09:57:50 -07:00
Joe Cheng
15af660424 Depend on methods so Rscript doesn't fail 2015-05-21 09:56:16 -07:00
Joe Cheng
790555ae89 Bump version, NEWS 2015-05-20 14:35:04 -07:00
Joe Cheng
3cc4df4e29 Merge pull request #837 from rstudio/joe/bugfix/callbacks-fifo
Ensure that callbacks fire in a FIFO order
2015-05-20 14:32:46 -07:00
Joe Cheng
395d1cee70 Ensure that callbacks fire in a FIFO order
Version bump required so Leaflet can detect this fix
2015-05-20 13:29:56 -07:00
Yihui Xie
89bc7efbca query$field is either an atomic vector, or a matrix, so use c() to coerce the result to a vector (previously RJSONIO::fromJSON() would return a list, but now jsonlite returns a matrix) 2015-05-20 12:44:13 -05:00
Yihui Xie
8f893a9752 bump version 2015-05-19 16:15:24 -05:00
Yihui Xie
54e02e412c make sure q$search[['value']] is not of length zero 2015-05-19 16:14:30 -05:00
Winston Chang
808d7aab3f Merge tag 'v0.12.0'
Shiny 0.12.0 released to CRAN
2015-05-19 09:52:19 -05:00
Winston Chang
24a8f8f38b Merge pull request #830 from rstudio/check-htmlwidgets
Check htmlwidgets version
2015-05-18 11:58:48 -05:00
Winston Chang
90c00bed2f Check htmlwidgets version 2015-05-18 11:56:02 -05:00
Winston Chang
054c911a1f Clear cran comments 2015-05-18 11:07:42 -05:00
Winston Chang
c2d5432a5d Bump version to 0.12.0 2015-05-18 10:10:53 -05:00
Winston Chang
dd64b70f5b Concat and minify shiny.js 2015-05-18 09:49:10 -05:00
Yihui Xie
a69dbeb10f bump version 2015-05-17 15:20:16 -05:00
Yihui Xie
976a768446 white spaces 2015-05-17 15:19:04 -05:00
Yihui Xie
5612cec91f Merge pull request #829 from yihui/deprecate-datatables
closes #807: add messages of deprecation for DataTables in shiny
2015-05-17 15:17:51 -05:00
Yihui Xie
46996eb81c closes #807: add messages of deprecation for DataTables in shiny 2015-05-15 18:21:58 -05:00
Winston Chang
12990f9fb2 Merge pull request #823 from yihui/bugfix/814
Load selectize options after initialization in the server mode
2015-05-15 15:22:39 -05:00
Yihui Xie
77ff988232 a news item for the change in server-side selectize 2015-05-15 15:17:31 -05:00
Yihui Xie
8df98c29b8 this comment is no longer true 2015-05-15 15:06:23 -05:00
Yihui Xie
7554f8395b fixes #814: load options after initialization of selectize in the server mode 2015-05-15 15:05:39 -05:00
Winston Chang
6fc0bac106 Properly use hoverClip option 2015-05-13 11:42:18 -05:00
Winston Chang
d252feddc9 Change nullOutside default to TRUE 2015-05-13 11:16:48 -05:00
Winston Chang
8c2645498d Merge pull request #824 from rstudio/interaction-tweaks
Interaction tweaks
2015-05-13 11:14:46 -05:00
Winston Chang
528acc4aa4 Concat and minify shiny.js 2015-05-13 11:08:47 -05:00
Winston Chang
2ce45eab06 Hovering: add option to send NULL when mouse is outside 2015-05-13 11:08:16 -05:00
Winston Chang
074c24aa10 Show brush only after mouse starts moving 2015-05-11 22:31:56 -05:00
Winston Chang
79e4007732 Add option to return all selected rows for mouse interactions 2015-05-11 15:56:34 -05:00
Winston Chang
742ce6673c Re-document with roxygen2 4.1.1 2015-05-11 15:55:51 -05:00
Winston Chang
4a74f588b9 nearPoints: add _dist column even when zero rows selected 2015-05-05 23:11:33 -05:00
Winston Chang
f876dc066c Minify shiny.js 2015-05-05 23:11:33 -05:00
Winston Chang
65aaf386c2 Lock grunt-contrib-uglify version
Version changes of the grunt-contrib-uglify version can result in different
min.js output. Lock it so the minified files won't have spurious changes.
2015-05-05 23:01:24 -05:00
Winston Chang
4eae6bd362 Update NEWS 2015-05-01 14:59:23 -05:00
Joe Cheng
4f7cfd6bd4 Bump dev version for ggplot2 interactive graphics 2015-05-01 09:53:46 -07:00
Joe Cheng
1136ad09ee Merge pull request #802 from rstudio/interact-ggplot
BOOM!!!!
2015-05-01 09:51:51 -07:00
Winston Chang
4a67bd945c Concat and minify shiny.js 2015-05-01 11:29:31 -05:00
Winston Chang
a2841f7cf2 Allow selectBrush to operate in just x or y direction 2015-05-01 11:28:43 -05:00
Winston Chang
4fa6e9dafe Fix off-by-one positioning error for base graphics 2015-05-01 11:28:43 -05:00
Winston Chang
7ebd7959f9 Document data structures for plot interactions 2015-05-01 09:58:00 -05:00
Winston Chang
4386015cff brushedPoints and nearPoints: handle Dates and POSIXt properly 2015-05-01 09:56:24 -05:00
Winston Chang
5cd014f7e6 Fix restoring brush with new coordmap panel data format 2015-05-01 09:56:24 -05:00
Winston Chang
30d0bfbdf0 Rename selectBrush to brushedPoints 2015-05-01 09:56:24 -05:00
Joe Cheng
48cfeca220 Merge pull request #797 from rstudio/joe/input-logging
Add session$onInputReceived
2015-04-30 22:10:21 -07:00
Winston Chang
5fefc48a0b Fix variable name 2015-04-29 13:19:46 -05:00
Winston Chang
42f2ae16ec Document missing argument 2015-04-29 13:19:46 -05:00
Winston Chang
3d47b0201f Simplify selectBrush and nearPoints code 2015-04-29 12:17:28 -05:00
Winston Chang
7607b1215f Update tests 2015-04-29 11:49:36 -05:00
Winston Chang
eae2b40898 Add nearPoints() function 2015-04-29 11:48:33 -05:00
Winston Chang
8e253046d8 Merge pull request #813 from pvictor/master
Change in sliderInput
2015-04-29 10:37:02 -05:00
pvictor
b0e17f02b5 Change in sliderInput
Add `animate$playButton` and `animate$pauseButton` in `sliderTag` to add possibility to custom button with `animateOptions`
2015-04-29 15:30:25 +02:00
Winston Chang
3f3c131737 Automatically find var names for brush selection 2015-04-27 17:04:07 -05:00
Winston Chang
2b227fcca5 Send variable mappings in coordmap 2015-04-27 15:22:43 -05:00
Winston Chang
639e55b537 Rename underBrush to selectBrush 2015-04-25 18:00:11 -04:00
Winston Chang
8386404b25 Capture and display coordmap errors 2015-04-25 09:38:40 -04:00
Winston Chang
a093afb630 More informative comments 2015-04-23 11:53:31 -05:00
Winston Chang
7208688128 Simplify facet code 2015-04-23 11:53:31 -05:00
Winston Chang
b94d406bd9 Treat shiny.js as binary 2015-04-23 11:53:31 -05:00
Winston Chang
79188b7d62 Add underBrush() function 2015-04-23 11:53:31 -05:00
Winston Chang
85b2fc503d Make brush div 1px larger 2015-04-20 15:06:00 -05:00
Winston Chang
57f33109b2 Change default brush color to blue 2015-04-20 15:06:00 -05:00
Winston Chang
d039547886 Fixes for R CMD check in R 3.2.0 2015-04-20 11:55:31 -05:00
Winston Chang
55621b7826 Use NULL for session$user and $groups 2015-04-17 13:23:50 -05:00
Winston Chang
854730f258 Fix restoring brush with facets in IE8/9 2015-04-17 12:15:38 -05:00
Winston Chang
9c4f73f314 Respect falsy opts for imageOutput 2015-04-16 23:43:20 -05:00
Winston Chang
e1fa491af7 Fix panel matching logic 2015-04-16 23:40:08 -05:00
Winston Chang
b909a3e05c Allow brush resizing 2015-04-16 23:40:07 -05:00
Winston Chang
4159c539e7 Consolidate code for width/height 2015-04-16 23:40:07 -05:00
Winston Chang
d1bd232ec7 Grunt: jshint before uglify 2015-04-16 23:40:07 -05:00
Winston Chang
a47898a2c4 Fix min/max order for reversed scales 2015-04-16 23:40:07 -05:00
Winston Chang
06b69e516a Pixelratio workaround 2015-04-16 23:40:07 -05:00
Winston Chang
312c89aaee Fix panel scale order for facet_grid 2015-04-16 23:40:07 -05:00
Winston Chang
a5b1f020ae Simplify sendBrushInfo 2015-04-16 23:40:07 -05:00
Winston Chang
e9cd1bef43 Send brush data when reset 2015-04-16 23:40:07 -05:00
Winston Chang
7b17ce5de1 Fix brush import for reverse scales 2015-04-16 23:40:07 -05:00
Winston Chang
ffb1b06bf4 Use 'expand' parameter 2015-04-16 23:40:06 -05:00
Winston Chang
21e9ffec97 Cleaner coordmap initialization 2015-04-16 23:40:06 -05:00
Winston Chang
7cfaa2adfc Move clipToBounds from coordmap to panel 2015-04-16 23:40:06 -05:00
Winston Chang
4e80e35976 Get correct coordinates for panels 2015-04-16 23:40:06 -05:00
Winston Chang
e9f78f6ace Restore brush even when scales change 2015-04-16 23:40:06 -05:00
Winston Chang
4d074c6fa9 Fix log scaling 2015-04-16 23:40:06 -05:00
Winston Chang
0b3c2e198e Add functions to coordmap object 2015-04-16 23:40:06 -05:00
Winston Chang
48cd7200cc Partial implementation of scale/inv 2015-04-16 23:40:06 -05:00
Winston Chang
d925702b98 Fix height/width calculation of brush div 2015-04-16 23:40:06 -05:00
Winston Chang
55cbd72a47 Gruntfile: add watch support for concat 2015-04-16 23:40:06 -05:00
Winston Chang
fbf1ba172f Implement client-side support for facets 2015-04-16 23:40:05 -05:00
Winston Chang
abb722f405 Fix bottom/top reversal 2015-04-16 23:40:05 -05:00
Winston Chang
2c121dc2c3 Put shiftToRange in right place 2015-04-16 23:40:05 -05:00
Winston Chang
dbcdbda2ef Modularize brush code 2015-04-16 23:40:05 -05:00
Winston Chang
03784ba82e Partial refactoring of brush 2015-04-16 23:40:05 -05:00
Winston Chang
04768ad8fa Encode facet information 2015-04-16 23:40:05 -05:00
Winston Chang
29943408e5 Consolidate coordinate functions 2015-04-16 23:40:05 -05:00
Winston Chang
dbadc05bef Better function name 2015-04-16 23:40:05 -05:00
Winston Chang
2e6347b380 Safe handling of discrete scales 2015-04-16 23:40:05 -05:00
Winston Chang
6c65b1ffde Add support for ggplot2 log coord transforms 2015-04-16 23:40:05 -05:00
Winston Chang
358416687f Add support for ggplot2 log scales 2015-04-16 23:40:04 -05:00
Winston Chang
1dc061e1c6 Add support for ggplot2 reversed scales 2015-04-16 23:40:04 -05:00
Winston Chang
e7f2572f42 Treat minified JS and map files like binary 2015-04-16 23:40:04 -05:00
Winston Chang
463ee7e027 Add click/hover/brush support for ggplot2 2015-04-16 23:40:04 -05:00
Winston Chang
667bc95d02 Rename coordmap usr and bounds to domain and range 2015-04-16 23:40:04 -05:00
Winston Chang
3f8cc71814 Use separate function for getting coordmap 2015-04-16 23:40:04 -05:00
Winston Chang
a9a6e96a6a Move renderPlot into separate file 2015-04-16 23:40:04 -05:00
Winston Chang
02caf05aaf Fix formatting in flowLayout documentation 2015-04-14 11:04:50 -05:00
Joe Cheng
da88678a43 Merge pull request #796 from mikelove/patch-1
flowLayout's man page: % needs to be escaped
2015-04-14 09:03:15 -07:00
Mike Love
1e8a9de60a flowLayout's man page: % needs to be escaped
or else it turns into a commend in the Rd file
2015-04-14 11:51:38 -04:00
Joe Cheng
1a6181cb15 Merge pull request #778 from rstudio/bugfix/clear-select-choices
Allow updateSelectInput(choices=character(0)) to clear select choices
2015-04-14 08:42:53 -07:00
Yihui Xie
ece69342b8 bump version 2015-04-13 10:09:59 -05:00
Yihui Xie
fe601d631b bump version of mime to 0.3
due to the fact that mime < 0.3 used GPL but copied code from Rook, which is specifically GPL-2; mime >= 0.3 also uses GPL-2 since GPL implies 2 or 3, and 3 does not work with 2
2015-04-13 10:09:26 -05:00
Yihui Xie
42d2e5aaef bump version requirement of jsonlite due to toJSON(json_verbatim = TRUE) (#795) 2015-04-13 10:06:39 -05:00
Winston Chang
bac7ab7f01 Merge pull request #795 from yihui/feature/verbatim-json
Treat the output of toJSON() as a verbatim JSON string
2015-04-09 10:29:46 -05:00
Yihui Xie
c6ac1474d4 Treat the output of toJSON() as a verbatim JSON string, and do not double-encode it
https://github.com/jeroenooms/jsonlite/commit/6fd201b3ad

also see ramnathv/htmlwidgets#28
2015-04-08 21:38:15 -05:00
Winston Chang
5a9c4ad8f3 Reinstate image error message fix
This fix for #783 seems to have gotten lost when shiny.js was split up.
2015-04-08 10:01:45 -05:00
Winston Chang
babc59f85c Clarifcations in tools README 2015-03-30 20:00:13 -05:00
Winston Chang
982a4361cd Merge pull request #775 from rstudio/split-js
Split up shiny.js into multiple files
2015-03-30 16:20:05 -05:00
Winston Chang
15e53ca55e Remove extraneous indenting 2015-03-30 16:18:26 -05:00
Winston Chang
ceb428b8bd Split up shiny.js 2015-03-30 16:17:04 -05:00
Winston Chang
b7fe3ed745 Update to ionRangeSlider 2.0.6. Closes #777 2015-03-27 15:31:37 -05:00
Winston Chang
817b614e61 Clear error messages in imageOuputs. Fixes #783 2015-03-27 15:11:35 -05:00
Joe Cheng
3321e95b54 Add session$onInputReceived 2015-03-26 16:04:04 -07:00
Winston Chang
fd5f536d14 Use jsonlite 0.9.15 2015-03-26 09:55:45 -05:00
Joe Cheng
fdbcb32be7 Allow updateSelectInput(choices=character(0)) to clear select choices 2015-03-24 13:00:00 -07:00
Winston Chang
a774cee1d9 Remove unused function 2015-03-21 22:19:58 -05:00
Winston Chang
1c46f227d2 Update travis config to use dev version of jsonlite 2015-03-20 15:28:36 -05:00
Winston Chang
6191c96347 Update NEWS 2015-03-20 15:13:49 -05:00
Winston Chang
12918fdfee Actually udpate jsonlite version 2015-03-20 15:13:39 -05:00
Winston Chang
8cea246fc8 Bump version to 0.11.1.9003 and increase jsonlite version dependency 2015-03-20 15:00:07 -05:00
Winston Chang
41455a008b Update toJSON for more RJSONIO compatibility 2015-03-20 14:58:28 -05:00
Winston Chang
be22d5c95d Merge branch 'interactive-graphic'
Conflicts:
	inst/www/shared/shiny.min.js
	inst/www/shared/shiny.min.js.map

Re-minified the shiny.min.js file in the merge.
2015-03-20 14:51:52 -05:00
Winston Chang
b298a62e46 Merge pull request #773 from yihui/feature/json-date
use ISO8601 and UTC for POSIX[c|l]t time by default
2015-03-20 11:06:57 -05:00
Winston Chang
839045ed66 Clear pending event on double click 2015-03-20 10:51:01 -05:00
Yihui Xie
a4a5c61fef use ISO8601 and UTC for POSIX[c|l]t time by default 2015-03-19 16:17:33 -05:00
Winston Chang
dd6aa9e4cf Minify shiny.js 2015-03-19 16:00:12 -05:00
Winston Chang
e299b51779 Simplify pending event tracking 2015-03-19 15:58:35 -05:00
Winston Chang
d3f0129c3f Expand region to start a brush 2015-03-19 15:49:25 -05:00
Winston Chang
ae938c66cc Add overview comments 2015-03-19 15:26:15 -05:00
Winston Chang
8d662f4f89 Add distance threshold for two clicks to count as a double-click 2015-03-19 15:06:48 -05:00
Winston Chang
a1caa41fe9 Simplify conversion of options to HTML properties 2015-03-19 13:55:13 -05:00
Winston Chang
6028263681 Fix some simple issues from pull request feedback 2015-03-18 20:16:06 -05:00
Winston Chang
30f9291496 Update documentation 2015-03-17 13:08:05 -05:00
Winston Chang
2400a44ded Minify shiny.js 2015-03-17 12:43:44 -05:00
Winston Chang
952556a9d1 Add option to reset brush on new image 2015-03-17 12:40:20 -05:00
Winston Chang
2e18b5c64b Fix indentation 2015-03-17 12:40:20 -05:00
Winston Chang
cb499c6105 Remove no-longer-needed IE9/10 workaround 2015-03-16 22:35:31 -05:00
Winston Chang
7f87bcddc1 Rename file 2015-03-16 22:28:00 -05:00
Winston Chang
6798917bc9 Simplify namespacing of image interaction events 2015-03-16 22:25:18 -05:00
Winston Chang
cf3f32ac37 Add dblclick workaround for IE8 2015-03-16 22:00:41 -05:00
Winston Chang
a41e1dafc2 Add IE version detection code 2015-03-16 22:00:23 -05:00
Winston Chang
3ac5124e5c Make sure a double click doesn't trigger click event 2015-03-16 21:27:13 -05:00
Winston Chang
83a472794b Add double-click event 2015-03-16 19:44:40 -05:00
Winston Chang
af78d62b76 Change click/hover/brush arguments 2015-03-16 16:05:50 -05:00
Winston Chang
27a0708909 Add left/right or top/bottom borders for x or y brushing 2015-03-16 14:27:05 -05:00
Winston Chang
5ab58f86ba Change event listener bindings fo IE8 compatibility
Binding mousemove event listeners to the window apparently doesn't work in IE8,
so bind to document instead.
2015-03-16 13:49:45 -05:00
Winston Chang
2c0bfdccf9 Restructure brushing and dragging event handlers 2015-03-16 12:52:52 -05:00
Winston Chang
581618370b Remove unnecessary code 2015-03-16 12:52:51 -05:00
Winston Chang
bdf217c45a Reorganize event handlers so they work properly in IE<=10 2015-03-16 12:52:51 -05:00
Winston Chang
42d6594159 Fix drag and selection on IE 2015-03-13 16:26:56 -05:00
Winston Chang
fac1750b63 Document direction argument for brushOptions 2015-03-13 16:09:52 -05:00
Winston Chang
6907d192f5 Allow mousemove and mouseup outside of the image 2015-03-13 14:32:23 -05:00
Winston Chang
0380f36489 Make sure bounds are constrained to plotting region 2015-03-13 13:48:19 -05:00
Winston Chang
1524dc2680 Add x and y brushing
This also contains a big refactoring of the brushing code.
2015-03-13 12:49:59 -05:00
Winston Chang
c95cc0a52b Better function name 2015-03-11 23:13:25 -05:00
Winston Chang
a876c5a888 Fix plotting region check 2015-03-11 23:09:51 -05:00
Winston Chang
bdd925886a Show grab and grabbing cursor with brush 2015-03-11 23:09:51 -05:00
Winston Chang
4d3d292add Only respond to left mouse button 2015-03-11 15:58:13 -05:00
Winston Chang
48f03e79e2 Add brushOptions and hoverOptions functions
Also clean up help for imageOutput and plotOutput, and add examples.
2015-03-11 15:37:22 -05:00
Winston Chang
e3af622a36 Replace bind() with explicit function wrappers 2015-03-11 12:25:45 -05:00
Winston Chang
dcb300ab50 Merge pull request #763 from rstudio/joe/bugfix/slider-delay
Fix 250ms delay in updateSliderInput(value=...) roundtrip.
2015-03-11 00:17:08 -05:00
Winston Chang
95ffd46a63 Clear click/brush/hover values when new image is received 2015-03-10 23:19:25 -05:00
Winston Chang
6f5d4a8620 Fix off-by-one error in plot pixel coordinates 2015-03-10 22:48:57 -05:00
Winston Chang
62855cc969 Fix clipping bounds off-by-one error 2015-03-10 22:42:55 -05:00
Winston Chang
bdfe9dfab2 Fix bug where brush goes outside 2015-03-10 22:42:55 -05:00
Joe Cheng
465ddf1a01 Fix 250ms delay in updateSliderInput(value=...) roundtrip. 2015-03-10 15:17:40 -07:00
Winston Chang
18a4ac1653 Refactor click and hover handlers to use shared function 2015-03-10 16:52:27 -05:00
Winston Chang
76d55144c5 Add clip option for click, hover, and brush 2015-03-10 16:23:27 -05:00
Winston Chang
665590a2f9 Add isPending method to Throttler 2015-03-10 15:32:12 -05:00
Winston Chang
81aa9a31c6 Don't send brush info second time on mouseup 2015-03-10 14:34:57 -05:00
Winston Chang
082490708f Consolidate image output options 2015-03-10 14:26:14 -05:00
Winston Chang
20ca4f8260 Add debounce and throttle options to brush 2015-03-10 14:16:38 -05:00
Winston Chang
eda057eb07 Disable image dragging when brushing in Firefox 2015-03-10 13:31:32 -05:00
Winston Chang
aed31c0eba Simplify image render logic
Now this exits early if data is empty.
2015-03-10 11:10:25 -05:00
Winston Chang
ea585458c7 Fix offset calculation for brush dragging 2015-03-10 10:48:51 -05:00
Winston Chang
e226e1c045 Add click/hover/brush support to imageOutputs 2015-03-10 10:47:03 -05:00
Winston Chang
ef330dd613 Formatting tweaks 2015-03-10 09:52:09 -05:00
Winston Chang
1225560ccd Streamline hover handler 2015-03-10 09:52:09 -05:00
Winston Chang
eef184e6ef Use crosshair cursor for brush 2015-03-09 22:02:04 -05:00
Winston Chang
50337eb731 Get jQuery object just once 2015-03-09 22:01:46 -05:00
Winston Chang
77f5e7d581 Add ability to clear previous brush 2015-03-09 21:54:13 -05:00
Winston Chang
02118bac76 Add brush dragging 2015-03-09 21:48:02 -05:00
Winston Chang
8b41be238a Refactor createBrushHandler 2015-03-09 20:39:31 -05:00
Winston Chang
8791e70c67 Add visible overlay for brush 2015-03-09 20:13:37 -05:00
Winston Chang
34a4b8f2d2 Add basic brushing support 2015-03-09 16:18:32 -05:00
Winston Chang
54c936b010 Refactor hover handler 2015-03-09 14:52:44 -05:00
Winston Chang
ed8d95e055 Move mouse coordinates to separate function 2015-03-09 14:17:12 -05:00
Winston Chang
25e8d080af Use lists instead of named vectors
jsonlite 0.9.14 drops names of named vectors, so we'll use lists instead.
2015-03-09 13:29:51 -05:00
Winston Chang
4599a7ab4e Merge pull request #759 from wch/fix-checkbox
Fix checkbox input binding (closes #206)
2015-03-06 15:03:58 -06:00
Winston Chang
5a106e0e6d Fix checkbox input binding (closes #206)
This fixes the bug introduced by #754.
2015-03-06 14:19:48 -06:00
Winston Chang
e4a211ba02 Send HTTP errors as UTF-8
This fixes an issue related to #736.
2015-03-06 10:27:30 -06:00
Joe Cheng
7ab373c942 Merge pull request #756 from rstudio/feature/port-option
Add shiny.port option
2015-03-06 01:41:00 -06:00
Winston Chang
18f1ebf715 Merge pull request #758 from yihui/DataTables1.10.5
upgrade DataTables to 1.10.5
2015-03-05 22:11:43 -06:00
Yihui Xie
2c02f44b26 upgrade DataTables to 1.10.5
need to be able to set $.fn.dataTableExt.errMode = 'none' to fix #561
2015-03-05 21:38:45 -06:00
Joe Cheng
8ae8168252 Merge pull request #754 from rstudio/remove-old-multiinput
Remove old multiInput code
2015-03-05 16:45:33 -06:00
Joe Cheng
c504f0b166 Merge pull request #755 from yihui/mimetype
remove the list of content types and use mime::guess_type()
2015-03-05 09:26:45 -06:00
Winston Chang
23da559d26 Add shiny.port option 2015-03-04 20:15:43 -06:00
Winston Chang
8b3ca12658 Mention app.R in runApp help 2015-03-04 20:11:16 -06:00
Yihui Xie
0f70b5662c remove the list of content types and use mime::guess_type()
also fixes #575
2015-03-04 19:58:37 -06:00
Winston Chang
475541cac0 Re-generate shiny.min.js 2015-03-04 19:43:54 -06:00
Winston Chang
007d6ad9c3 Simplify return value 2015-03-04 19:43:35 -06:00
Winston Chang
79db8d91ab Remove obsolete multiInput code (#206)
This commit removes multiInput code that was used for the HTML structure
generated in Shiny <= 0.5.0, and is now obsolete.
2015-03-04 19:39:53 -06:00
Joe Cheng
a0c6feb386 Merge pull request #753 from rstudio/bugfix/content-type
Fix downloading of files with no extension. Fixes #575
2015-03-04 16:23:30 -06:00
Winston Chang
1c72601123 Fix downloading of files with no extension. Fixes #575 2015-03-04 15:50:51 -06:00
Winston Chang
c6bcdd1ae1 Re-generate shiny.min.js 2015-03-04 15:09:28 -06:00
Winston Chang
e0acdba626 Remove unneeded ID attributes. Fixes #684
The checkboxGroup and radioButtons <input> items had an unneeded ID for the
DOM element, which could conflict with other items in the web page.
2015-03-04 15:07:38 -06:00
Winston Chang
a73e72f267 Add backward compatibility for shinysession$session (Fixes #752) 2015-03-04 11:13:52 -06:00
Joe Cheng
ee6682e7c8 Merge pull request #750 from rstudio/bugfix/nested-uioutput-duplicate-id
Fix issue #749: Nested uiOutputs break outputs
2015-03-04 09:10:56 -06:00
Joe Cheng
6c36ea5753 Fix issue #749: Nested uiOutputs break outputs 2015-03-03 21:28:47 -06:00
Winston Chang
3f798f1843 Update slider example for Shiny 0.11. (Fixes #748) 2015-03-02 16:54:35 -06:00
Winston Chang
4a806db8ae toJSON: special case for length-1 atomic vectors 2015-02-27 21:42:43 -06:00
Winston Chang
9c12125512 Bump version to 0.11.1.9002 2015-02-27 15:53:32 -06:00
Winston Chang
51130793fe Assign request object in self
The session object is now gone, so the appropriate place to assign `request`
is in `self`.
2015-02-27 15:34:55 -06:00
Winston Chang
d39c93ee7e Set up onEnd before calling onStart
This fixes an annoying bug where, if the app crashes while loading (for
example, if you call library() with a missing package), R ends up in the app's
working directory instead of in the original working directory.
2015-02-27 15:25:53 -06:00
Winston Chang
e1cfb29fa0 Update NEWS 2015-02-27 15:12:39 -06:00
Winston Chang
4dde16d836 Merge pull request #746 from rstudio/session-refactor
Refactor ShinySession object
2015-02-27 15:04:50 -06:00
Winston Chang
1c57ef5931 Remove leading dot from private item names 2015-02-27 15:02:09 -06:00
Winston Chang
0f642fe3ad Add class attribute to ShinySession object 2015-02-27 15:02:09 -06:00
Winston Chang
46844b516a Remove unneeded 'session' object
The 'session' object is no longer needed. Now that the ShinySession object
has proper public and private members, that object can be passed directly.
2015-02-27 15:02:09 -06:00
Winston Chang
b9cef228d9 Use explicit 'self', and make ShinySession portable 2015-02-27 15:02:09 -06:00
Winston Chang
fd71d04000 Use explicit 'private' 2015-02-27 15:02:09 -06:00
Winston Chang
bedb811621 Remove leading dots from public methods 2015-02-27 15:02:09 -06:00
Winston Chang
173736fd69 Set message encoding to UTF-8 instead of native (Fixes #742) 2015-02-27 14:55:31 -06:00
Winston Chang
21eea27c4a Remove duplicated 'destdir' documentation 2015-02-27 14:53:50 -06:00
Winston Chang
b39f04fbc3 Use native R config for travis 2015-02-27 11:43:30 -06:00
Winston Chang
04f898be21 Bump version to 0.11.1.9001 2015-02-23 16:43:48 -06:00
Winston Chang
defedda891 Switch from RJSONIO to jsonlite (again) 2015-02-23 16:41:36 -06:00
Winston Chang
bb2c8e5fd2 Clean up observeEvent and eventReactive examples 2015-02-23 15:57:27 -06:00
Winston Chang
7410bb9e9a Re-document 2015-02-23 15:57:06 -06:00
Winston Chang
fd3907596b Restore ability to dynamically set selectInput labels. Closes #741 2015-02-18 14:59:07 -06:00
Winston Chang
221a233ea4 Update NEWS 2015-02-12 13:21:16 -06:00
Winston Chang
389adda8ec Merge pull request #688 from xbhsu/feature/runURL-destination-file
Specifying destination file for runURL, runGist, and runGitHub
2015-02-12 13:11:19 -06:00
bhsu
835b65740b fixed consistency issues 2015-02-12 13:11:00 -05:00
Winston Chang
b24abffd0d Bump version to 0.11.1.9000 for development 2015-02-12 11:39:31 -06:00
Winston Chang
2ddf578f07 Add NEWS item 2015-02-12 11:39:05 -06:00
Yihui Xie
61b83c3e34 replace `` with \code{} in Rd 2015-02-11 18:12:14 +08:00
Winston Chang
3454ddbb2a Merge tag 'v0.11.1'
Shiny 0.11.1 released to CRAN
2015-02-10 19:42:58 -06:00
Winston Chang
194e4ca70d Update cran comments 2015-02-10 13:12:13 -06:00
Winston Chang
074981a709 Update Date in DESCRIPTION 2015-02-10 13:08:44 -06:00
Winston Chang
f157200a9f Fix Bootstrap URL 2015-02-10 10:58:31 -06:00
Winston Chang
f70fcddaad Clarify docs for shinyServer and shinyUI 2015-02-10 10:46:51 -06:00
Winston Chang
aa2129b60e Bump version to 0.11.1 2015-02-06 11:49:49 -06:00
Winston Chang
3794541828 Update gruntfile to watch for changes in DESCRIPTION 2015-02-06 11:49:30 -06:00
Winston Chang
b1a6dc65ba Remove jsonlite NEWS item 2015-02-06 11:23:50 -06:00
Winston Chang
040ae293fb Revert switch to jsonlite
This reverts commits deffc90, ab4dc64, and 0755579, returning to RJSONIO.
The purpose of this is to prepare for a maintenance release for 0.11
without the switch to jsonlite, to reduce the risk of new bugs.
2015-02-06 10:53:54 -06:00
Winston Chang
b74e93f3a4 Update NEWS and bump version 2015-02-05 15:51:01 -06:00
Winston Chang
dd3cc29af1 Merge pull request #728 from rstudio/bugfix/tab-value-with-icon
Fix #725: Tabs with icons give incorrect values
2015-02-05 15:44:02 -06:00
Joe Cheng
72b9a93088 Don't error when tabPanel has value but tabsetPanel doesn't have id
Causes problems now that tabPanel always has a value
2015-02-05 13:38:04 -08:00
Joe Cheng
4446f0a1f3 Merge pull request #729 from wch/feature/select-size
selectInput: add control for size (height)
2015-02-05 13:34:40 -08:00
Winston Chang
35802c12f6 selectInput: add control for size (height) 2015-02-05 15:30:03 -06:00
Winston Chang
f5fd30883a Update NEWS 2015-02-05 15:28:09 -06:00
Winston Chang
f8e720d6dc Fix tests for new HTML structure 2015-02-05 15:25:09 -06:00
Winston Chang
9f8f04caec selectInput: use form-control for multiple and single 2015-02-05 14:51:40 -06:00
Winston Chang
69aec85882 Fix label spacing for inline checkbox and radio 2015-02-05 12:46:54 -06:00
Winston Chang
e84012ec38 Update input docs to explain NULL label (#727) 2015-02-05 12:40:14 -06:00
Joe Cheng
128df6a2bf Fix #725: Tabs with icons give incorrect values
When no explicit value argument was present on tabPanel,
the inner text of the HTML anchor was used. This gave
weird results when an icon was used, since it appears in
the anchor.

The fix is to always use the value parameter, defaulting
it to the title.
2015-02-05 10:23:04 -08:00
Winston Chang
7b76951461 navbarPage: Don't include empty row when header=NULL. Fixes #722 2015-02-05 10:18:24 -06:00
Winston Chang
38d87450e6 Fix typo in docs 2015-02-05 10:17:42 -06:00
Winston Chang
b9c6b84ff5 selectInput: use BS 3 styling when multiple && !selectize. Closes #724 2015-02-04 19:45:04 -06:00
Winston Chang
5ba1d57b1f Update NEWS and bump version 2015-02-04 13:32:27 -06:00
Winston Chang
a4d567e44d Merge pull request #704 from wch/html-replace2
htmlOutput: allow custom container function
2015-02-04 13:30:19 -06:00
Joe Cheng
19a62ba7e9 Merge pull request #723 from rstudio/bugfix/namespace-filtering
Fix oversubscription of shown/hidden events
2015-02-04 10:20:42 -08:00
Winston Chang
65d6c7b558 Minify shiny.js 2015-02-04 12:17:30 -06:00
Winston Chang
8c828e7881 Correct event namespace filtering 2015-02-04 12:15:23 -06:00
Winston Chang
b711780688 Debounce sendImageSize 2015-02-04 12:15:23 -06:00
Joe Cheng
855cdc8eda Fix oversubscription of shown/hidden events
Bootstrap 3 shown/hidden events look like "shown.bs.modal",
"shown.bs.popover", etc. When subscribing to these events, you also
automatically pick up "shown" and "hidden" events. This causes a 6X
oversubscription of hidden and shown events. We fix this by filtering
out these overbroad events.

Also, don't do anything if the show/hide would be a no-op; this
also helps cut down on extraneous events.
2015-02-04 12:15:23 -06:00
Winston Chang
c930cce914 Check for unnamed arguments in ... 2015-02-03 15:55:24 -06:00
Winston Chang
424696cf96 Update NEWS 2015-02-03 10:11:34 -06:00
Joe Cheng
ea4ef45289 Merge pull request #715 from rstudio/bugfix/download-ext
downloadHandler temp files should have same extension as final download
2015-02-02 10:27:07 -08:00
Winston Chang
d2e13e6ac6 Merge pull request #719 from aronatkins/typo_04_mpg
fix "formula" spelling in 04_mpg example
2015-02-02 09:47:19 -06:00
Aron Atkins
70ff6658eb fix spelling 2015-02-02 10:09:08 -05:00
Joe Cheng
3e1732b9c0 downloadHandler temp files should have same extension as final download file 2015-02-01 08:37:44 -08:00
Winston Chang
4eb18dc797 Update NEWS 2015-01-28 15:43:23 -06:00
Winston Chang
6e7adfadb0 Merge pull request #710 from rstudio/bugfix/fixedpanel-cursor
Fix fixedPanel default cursor handling
2015-01-28 14:00:07 -06:00
Winston Chang
a866224f7b Switch to modified ion.rangeSlider 2.0.3. Closes #711
This includes the stopPropagation change, and the Shiny skin.
2015-01-28 13:56:31 -06:00
Winston Chang
77c50d6880 Update shiny.min.js 2015-01-28 11:36:28 -06:00
Winston Chang
4290e2e7b0 Merge pull request #702 from wch/select-width
Allow control over selectize width
2015-01-28 11:17:06 -06:00
Winston Chang
4e8632de73 Better documentation of plotOutput height (#705) 2015-01-28 11:15:08 -06:00
Joe Cheng
2792fe82a3 Fix fixedPanel default cursor handling
Previous to this fix, calling fixedPanel without an
explicit cursor argument would cause an error due to
the vector of possible values being passed as the
actual cursor argument to absolutePanel.
2015-01-27 18:41:29 -08:00
Winston Chang
ab6df9f8a9 Remove unused width control in shiny.js 2015-01-26 22:31:31 -06:00
Winston Chang
425489c74b Control width for non-selectize select inputs 2015-01-26 22:31:30 -06:00
Winston Chang
9f04517801 htmlOutput: allow custom container function 2015-01-26 16:50:09 -06:00
Winston Chang
9954639096 Allow control over selectize width
Previously, you could set the width of a selectInput with a pixel value
like 500px, but it wouldn't respect percent widths like 100%. This
commit makes width control the wrapper container's width, so it will
respect percent values.
2015-01-26 15:35:02 -06:00
Winston Chang
cd78364c17 Merge pull request #698 from daattali/patch-1
parseQueryString returns a list, not a vector
2015-01-25 21:05:17 -06:00
Dean Attali
563b986591 parseQueryString returns a list, not a vector 2015-01-24 20:42:34 -08:00
Winston Chang
fe5552773d sliderInput: use width argument (#675) 2015-01-23 15:30:20 -06:00
Winston Chang
b7acaf9519 Convert donttest examples; check for interactive() instead 2015-01-22 13:21:23 -06:00
Winston Chang
deffc90531 Remove remaining RJSONIO references 2015-01-22 13:15:01 -06:00
Joe Cheng
f54a6e8513 Add IE=edge to X-UA-Compatible header 2015-01-22 10:52:27 -08:00
Winston Chang
ab4dc641af Make jsonlite::toJSON convert all objects
By default, toJSON won't convert objects with classes that aren't registered
explicitly. This caused errors when converting html_dependency objects.
Setting this option causes jsonlite to convert all objects, including
html_dependency objects.
2015-01-21 15:09:12 -06:00
Winston Chang
dfe725dd78 Bump version and update NEWS 2015-01-21 14:16:40 -06:00
Winston Chang
dbe1e24561 Merge pull request #606 from wch/feature/jsonlite
Switch from RJSONIO to jsonlite
2015-01-21 14:14:46 -06:00
Winston Chang
075557929a Switch from RJSONIO to jsonlite 2015-01-21 14:12:53 -06:00
Winston Chang
d994db9c74 Add other authors to DESCRIPTION 2015-01-20 15:19:54 -06:00
Winston Chang
c462c61ac9 Bump version to 0.11.0.9000 for development 2015-01-20 15:19:40 -06:00
Winston Chang
1ef9719059 Merge tag 'v/0/11'
Shiny 0.11 released to CRAN
2015-01-18 22:25:11 -06:00
Winston Chang
3df0e7899c Update cran-comments 2015-01-15 23:49:47 -08:00
Winston Chang
927972d889 More license updates 2015-01-15 23:34:58 -08:00
bhsu
00f409d21d explicit parameter check 2015-01-14 13:34:27 -05:00
bhsu
6aea95b486 fixed application exit
fixed on.exit behavior
2015-01-14 09:59:57 -05:00
bhsu
e4dd78b9a4 renamed to destDir and documentation
fixed typo
2015-01-14 09:59:38 -05:00
B. Hsu
d940d5a597 updated run-url.R
added ability for user to change destination file when using runUrl, runGist or runGitHub

added messages

added messages informing user of final destination of app files
2015-01-13 16:47:53 -05:00
Winston Chang
5f1ea21be1 Add cran-comments file 2015-01-12 12:04:26 -06:00
Winston Chang
278851224d Re-document with roxygen2 4.1.0 2015-01-12 12:02:24 -06:00
Winston Chang
0161bc5a4e Update LICENSE information 2015-01-12 12:02:24 -06:00
Winston Chang
9cf5168d3f Merge branch 'master' into v0.11-rc 2015-01-11 17:54:51 -06:00
Winston Chang
f066a4bdf4 Negative margin for checkboxes/radios only after label (#678) 2015-01-09 14:48:16 -06:00
Winston Chang
0009756ed9 Bump version to 0.11 2015-01-08 14:55:36 -06:00
Winston Chang
481e5437f1 Add CONTRIBUTING.md to .Rbuildignore 2015-01-08 14:55:10 -06:00
Winston Chang
238f54e011 Change name of shinyBootstrap2 package to shinybootstrap2 2015-01-08 14:55:00 -06:00
Winston Chang
180525f538 Merge pull request #685 from rstudio/bugfix/qt-radio-check
Suppress Bootstrap top margin around radios and checkboxes in Qt5
2015-01-08 13:47:56 -06:00
Jonathan McPherson
9a1958d19a restrict changes to Linux (Qt5 on Windows is unaffected) 2015-01-08 11:03:30 -08:00
Jonathan McPherson
e1469a1e44 suppress Bootstrap top margin around radios and checkboxes in Qt5 2015-01-08 10:49:16 -08:00
Winston Chang
85bde2b00d Fix reference to old shiny version number 2015-01-07 22:03:40 -06:00
Winston Chang
b20a15b4ed Fix label class for non-inline checkbox and radios 2015-01-07 21:06:37 -06:00
Yihui Xie
a67161f521 add a pointer to the DT package 2015-01-06 14:26:19 -06:00
Yihui Xie
8d621e87a0 should inherit params from textInput instead of passwordInput 2015-01-06 14:17:57 -06:00
Winston Chang
a560034614 Fix another URL 2015-01-06 13:21:57 -06:00
Winston Chang
b329c1f94c Fix URL 2015-01-06 11:33:07 -06:00
Winston Chang
06459c0f52 Remove duplicate text in reactive domain docs 2015-01-05 11:23:05 -06:00
Winston Chang
2655c2511d Fix docs for slider step size 2015-01-05 11:20:38 -06:00
Winston Chang
fa9fdb01b0 Add info about using shinyApp and runApp together 2015-01-02 11:47:51 -06:00
Winston Chang
4896948d38 Update NEWS 2015-01-02 11:40:36 -06:00
Winston Chang
133a37817e Fix class for radio buttons 2014-12-19 15:18:54 -06:00
Winston Chang
0cdee5ed7a Add staticdocs entry for passwordInput 2014-12-15 13:09:35 -06:00
Winston Chang
2c21989b47 Don't limit width of inline inputs. Fixes #675 2014-12-15 12:22:31 -06:00
Winston Chang
17f796847d Use correct class for inline checkbox/radio label 2014-12-15 12:22:31 -06:00
Joe Cheng
02578dbf3a Fix tabset input; event changed for bootstrap 3 2014-12-14 09:59:23 -08:00
Yihui Xie
9f86e84830 closes #668: emphasize that I() does not work for non-root level elements in the options list in renderDataTable() 2014-12-13 22:52:28 -06:00
Winston Chang
1ae65bb999 Fix URL 2014-12-12 22:35:00 -06:00
Winston Chang
ca72f5fa99 Update devtools install instructions 2014-12-12 17:01:42 -06:00
Winston Chang
bc9b537d84 Merge pull request #673 from wch/handler-domain
Make default reactive domain available in request handlers. Fixes #669
2014-12-12 14:03:24 -06:00
Winston Chang
d9336d0ba2 Make default reactive domain available in request handlers. Fixes #669 2014-12-12 10:19:25 -06:00
Joe Cheng
eb537eaa24 Merge pull request #672 from hadley/input-types
Add support for more html 5 input types
2014-12-11 22:23:05 -08:00
hadley
f1d814ba04 Implement passwordInput in the same style as textInput() 2014-12-11 16:21:34 -06:00
hadley
760d360e96 Listen for events on all html 5 text inputs types 2014-12-11 16:21:11 -06:00
Winston Chang
5431fa1405 Remove unused jslider css entries 2014-12-11 10:24:29 -06:00
Winston Chang
eb809e388b withProgress: check that session is a session object 2014-12-10 15:49:32 -06:00
Winston Chang
0205ad7a4f Fix appearance of download button 2014-12-10 11:01:11 -06:00
Winston Chang
9599b14aa8 Add note about tools in main README 2014-12-09 14:43:28 -06:00
Winston Chang
d72585e3d1 Make JSHint more lenient 2014-12-09 13:38:46 -06:00
Winston Chang
735a15d7c6 Merge tag 'v/0/10/2.2'
Shiny version 0.10.2.2

Conflicts:
	DESCRIPTION
2014-12-08 16:51:37 -06:00
Winston Chang
0984e6ed90 Clean up importBootstrap code 2014-12-08 16:37:39 -06:00
Winston Chang
6004a4250a README edits 2014-12-08 16:29:52 -06:00
Winston Chang
b39fcc75d0 Add minified shiny.js 2014-12-08 16:23:02 -06:00
Winston Chang
a401553c13 Re-minify datepicker 2014-12-08 15:56:19 -06:00
Winston Chang
a312abff31 Don't run shiny.js minification 2014-12-08 15:56:19 -06:00
Winston Chang
92c1722469 Simplify npm install instructions 2014-12-08 15:56:19 -06:00
Winston Chang
e48136d31e Add grunt watch task 2014-12-08 15:56:19 -06:00
Winston Chang
b9d6f6fd9c Update tools/README 2014-12-08 15:56:19 -06:00
Winston Chang
66c8dfe44d Add jshint task 2014-12-08 15:56:19 -06:00
Winston Chang
5910c936b9 Use grunt for minification of datepicker 2014-12-08 15:56:19 -06:00
Winston Chang
a2645061fe Add Gruntfile 2014-12-08 15:56:19 -06:00
Winston Chang
7b887d2fd5 Bump version 2014-12-08 11:34:52 -06:00
Winston Chang
8d2367ed82 Remove use of rstudio::viewer for R CMD check 2014-12-08 11:33:56 -06:00
Joe Cheng
075583f4be Use minified jquery 2014-12-08 09:17:04 -08:00
Winston Chang
ce86e0a54a Re-document 2014-12-08 10:10:17 -06:00
Winston Chang
9308f8ea69 Fix documentation typo 2014-12-08 10:10:09 -06:00
Winston Chang
cc8b425adc Update license information 2014-12-05 14:49:24 -06:00
Winston Chang
25cf7955c9 Bump version to 0.10.2.9006 2014-12-05 14:31:06 -06:00
Winston Chang
d393865efc Update Bootstrap link 2014-12-05 14:30:46 -06:00
Winston Chang
9d877320d8 Merge pull request #658 from wch/feature/ionslider
New sliders
2014-12-05 14:30:07 -06:00
Winston Chang
1f72bef393 Update license information for ion.rangeSlider 2014-12-05 14:28:21 -06:00
Winston Chang
99c1069229 Add instructions for installing old version 2014-12-05 10:33:40 -06:00
Winston Chang
28718429e3 Fix arrows for date inputs. Fixes #663
The date inputs used css classes like icon-arrow-right, which no longer works
with font-awesome 4.x. This change uses glyphicon arrows instead, which are
included with Bootstrap and therefore don't need a separate HTML dependency.
2014-12-02 09:53:11 -06:00
Winston Chang
e145021760 Update to ion.rangeSlider 2.0.2 (with shiny mods) 2014-12-02 09:21:47 -06:00
Winston Chang
b7dd51c594 Fix case of directory 2014-12-02 09:08:29 -06:00
Winston Chang
9ebc3e5eec Fix file input appearance for Bootstrap 3 2014-11-26 19:34:27 -06:00
Winston Chang
4db60d7b27 Merge pull request #655 from wch/showcase-dep
Dynamically get font-awesome dependency from showcase body
2014-11-26 16:57:25 -06:00
Winston Chang
5d85199ae3 Dynamically get font-awesome dependency from showcase body 2014-11-26 16:54:27 -06:00
Winston Chang
088c9e5450 Better help for reactiveValues. Fixes #620 2014-11-26 15:28:16 -06:00
Winston Chang
bd51d1b2a2 Update NEWS 2014-11-26 14:20:25 -06:00
Winston Chang
0de7b6f63a Remove web resources for jslider 2014-11-26 14:20:25 -06:00
Winston Chang
85706eac84 Re-document 2014-11-26 14:20:25 -06:00
Winston Chang
96b646b94a Rename slider2Input to replace sliderInput 2014-11-26 14:20:25 -06:00
Winston Chang
753f6fc671 Update heuristic for step size 2014-11-26 14:19:06 -06:00
Winston Chang
3f186747ed Add keyboard support for sliders 2014-11-26 14:19:06 -06:00
Winston Chang
e6748c0793 Re-document 2014-11-26 14:19:06 -06:00
Winston Chang
2383796c49 Add slider2Input documentation 2014-11-26 14:19:06 -06:00
Winston Chang
fb38ab4ef2 Improve tick and step heuristics 2014-11-26 14:19:06 -06:00
Winston Chang
1242a62bca Set HTML data values to "true" and "false" 2014-11-26 14:19:06 -06:00
Winston Chang
55ceb12277 Simplify label code for slider2Input 2014-11-26 14:19:05 -06:00
Winston Chang
6dd4e7676d Add deprecation message for format argument 2014-11-26 14:19:05 -06:00
Winston Chang
4abb58b239 Add format options to sliders 2014-11-26 14:19:05 -06:00
Winston Chang
385dab6036 Add script for updating ion.rangeSlider 2014-11-26 14:19:05 -06:00
Winston Chang
2e9291decf Add QT-webkit touch detection workaround
This is from commit 813939b of ion.rangeSlider
2014-11-26 14:19:05 -06:00
Winston Chang
623036f03b Add updateSlider2Input 2014-11-26 14:19:05 -06:00
Winston Chang
98075e9d9d Add animation to ionsliders 2014-11-26 14:19:05 -06:00
Winston Chang
b80ce0e222 Add customized ionslider skin for Shiny 2014-11-26 14:19:05 -06:00
Winston Chang
b0162efb1f Add slider2Input 2014-11-26 14:19:05 -06:00
Winston Chang
7b3e9ab031 Limit width of inputs 2014-11-26 14:16:40 -06:00
Winston Chang
b35e866d95 Fix appearance of DataTables examples 2014-11-26 12:49:59 -06:00
Winston Chang
2d273d1550 Merge pull request #646 from yihui/feature/DT-1.10.3
upgrade to DataTables 1.10.4 and use Bootstrap 3
2014-11-26 12:44:39 -06:00
Yihui Xie
6aef3eb879 update the version info of DataTables 2014-11-26 10:15:18 -06:00
Winston Chang
61b0393657 Update tests for new select input structure 2014-11-26 10:09:27 -06:00
Winston Chang
30bf6c0714 Wrap select inputs in div 2014-11-26 09:51:22 -06:00
Winston Chang
fc64b115d3 Fix DOM structure for selectize inputs 2014-11-26 09:42:00 -06:00
Yihui Xie
bdc3f24ca6 the css of the processing indicator seems to be okay with Bootstrap 3 now 2014-11-26 00:13:39 -06:00
Joe Cheng
b28300b184 Merge pull request #660 from wch/body-tag
Allow running apps that have a body tag
2014-11-25 11:49:29 -08:00
Winston Chang
5c1f9d03e4 Update version and NEWS 2014-11-25 13:46:22 -06:00
Winston Chang
ed368a225d Refactor showcase ui code to handle body tags 2014-11-25 13:46:22 -06:00
Winston Chang
2f17f392d5 If UI has body tag, don't wrap in another body 2014-11-25 13:46:21 -06:00
Yihui Xie
b00a6e526e Bootstrap 3 for DataTables 2014-11-25 00:01:13 -06:00
Yihui Xie
75031df45b upgrade to DataTables 1.10.4
need the bugfix DataTables/DataTables#391
2014-11-25 00:00:55 -06:00
Winston Chang
39148a99d0 Make sure progress bars draw above other Bootstrap components 2014-11-24 13:52:08 -06:00
Winston Chang
d72f5ee2ad Better examples and docs for renderTable and renderDataTable 2014-11-24 11:24:26 -06:00
Winston Chang
c6ea459a68 Bump version to 0.10.2.9004 2014-11-21 08:26:05 -06:00
Joe Cheng
e8525e5513 Merge pull request #611 from rstudio/feature/bootstrap3
Switch to Bootstrap 3
2014-11-20 14:38:09 -08:00
Winston Chang
9046b85ca4 Fix appearance of date ranges 2014-11-20 14:50:18 -06:00
Winston Chang
19257b76d2 Fix spacing of checkbox input 2014-11-20 14:27:06 -06:00
Winston Chang
fd8990b294 Fix appearance of labels for checkbox group and radio buttons 2014-11-20 13:55:53 -06:00
Winston Chang
eb34f5e058 Don't limit text/number/select input width 2014-11-20 13:48:19 -06:00
Winston Chang
f8ced7e065 Merge pull request #656 from andeek/master
fixed iconClass function
2014-11-20 13:15:17 -06:00
Winston Chang
bf0a2d3c6c Fixes for progress bars with Bootstrap 3 2014-11-18 21:26:39 -06:00
Winston Chang
f5878326f7 Add CONTRIBUTING file 2014-11-18 10:50:48 -06:00
Winston Chang
1f0b439168 Add meta viewport tag 2014-11-17 16:13:55 -06:00
Winston Chang
3464e11152 Modify HTML5 shims so they are handled by htmlDependency
This adds conditional JS code so that the shim code isn't actually run
in browsers other than IE 8.
2014-11-17 16:13:55 -06:00
Winston Chang
b5f99be635 Add HTML5 shims for Bootstrap 3 to work with IE8 2014-11-17 14:43:35 -06:00
Winston Chang
3153b35c2a icon: add support for glyphicon library 2014-11-17 14:43:35 -06:00
Winston Chang
c450f9abc2 Re-document 2014-11-17 14:43:35 -06:00
Winston Chang
912434b259 Update navlistPanel for Bootstrap 3 2014-11-17 14:43:35 -06:00
Winston Chang
5f61fc658a actionButton: add btn-default class, for Bootstrap 3 2014-11-17 14:43:35 -06:00
Winston Chang
a268b74636 Update navbarPage for Bootstrap 3 2014-11-17 14:43:34 -06:00
Winston Chang
82a1bf7afd Deprecate 'collapsable' in favor of 'collapsible' 2014-11-17 14:43:34 -06:00
Winston Chang
4392676667 Add Bootstrap 3 note to README 2014-11-17 14:43:34 -06:00
Winston Chang
c47ec2c3c0 Register callbacks for each Bootstrap 3 class 2014-11-17 14:43:34 -06:00
Winston Chang
e756fc8daa Update NEWS 2014-11-17 14:43:34 -06:00
Winston Chang
4629262a1a Re-document 2014-11-17 14:43:34 -06:00
Winston Chang
741aec198b Fix inline checkboxGroupInputs and radioButtons 2014-11-17 14:43:34 -06:00
Winston Chang
c3e5b4fa36 Set width of divs inside of flowLayout 2014-11-17 14:43:34 -06:00
Winston Chang
d022907bcd Update showcase CSS classes for Bootstrap 3 2014-11-17 14:43:34 -06:00
Winston Chang
8a7603a45c Update slider animation buttons for Bootstrap 3 2014-11-17 14:43:34 -06:00
Winston Chang
2ade82d883 Fix headerPanel spacing
The titlepanel spacing also is unnecessary now with Bootstrap 3.
2014-11-17 14:43:34 -06:00
Winston Chang
3d8c38b558 Reduce spacing above sliders 2014-11-17 14:43:34 -06:00
Winston Chang
0f2d0a33b4 Adjust CSS for slider and selectize
This makes sliders and selectize inputs have width 100%, just like other
inputs with Bootstrap 3.
2014-11-17 14:43:34 -06:00
Winston Chang
d4ce1499cc Wrap inputs in div with class 'form-group' to maintain bottom margin 2014-11-17 14:43:33 -06:00
Winston Chang
9ab7895772 Fix appearance of date inputs 2014-11-17 14:43:33 -06:00
Winston Chang
ee9f79e287 Update selectize's CSS to use Bootstrap 3 2014-11-17 14:43:33 -06:00
Winston Chang
ad61dafb9a Correctly find checkboxes and radio buttons with Bootstrap 3 2014-11-17 14:43:33 -06:00
Winston Chang
b81361ff6d Update tests for new DOM structure of choices 2014-11-17 14:43:33 -06:00
Winston Chang
52417c0a60 Fix appearance of inputs 2014-11-17 14:43:33 -06:00
Winston Chang
000beeb737 Update tab shown/hidden events for Bootstrap 3 2014-11-17 14:43:33 -06:00
Winston Chang
7cce94000b Switch from Bootstrap 2 to 3 2014-11-17 14:43:33 -06:00
Andee Kaplan
7a4bdb4191 fixed iconClass function 2014-11-17 14:08:04 -06:00
Winston Chang
279a8ff989 Make font-awesome a dependency for icon() 2014-11-13 15:04:30 -06:00
Winston Chang
ed06a05ff0 Update font-awesome to 4.2.0 2014-11-13 14:06:45 -06:00
Joe Cheng
a56ac24cc2 Merge pull request #653 from yihui/bugfix/DT-encoding
encode the JSON response for DataTables/selectize with UTF-8
2014-11-13 09:03:42 -08:00
Yihui Xie
c8efd31d08 encode the JSON response for DataTables/selectize with UTF-8
to make sure multibyte characters in DataTables/selectize work
2014-11-13 10:27:56 -06:00
Winston Chang
d8875151e8 Un-normalize Progress values
This fixes an issue where Progress objects with a min and max other than
0 and 1 would not display properly.
2014-11-12 22:15:24 -06:00
Winston Chang
6082431161 Fixes for jshint 2014-11-03 15:26:59 -06:00
Joe Cheng
846c23a5a2 Merge remote-tracking branch 'origin/feature/event-reactives'
Conflicts:
	inst/tests/test-reactivity.r
2014-10-30 14:52:39 -07:00
Joe Cheng
9a5faa92c4 Refactor for code review feedback 2014-10-30 14:50:30 -07:00
Winston Chang
f149be26ce Add shiny-options to staticdocs index 2014-10-30 11:37:31 -05:00
Yihui Xie
c6d6ca5a5c bump version 2014-10-29 12:34:35 -05:00
Joe Cheng
98dc8069e3 Merge pull request #627 from yihui/bugfix/DT-XSS
escape HTML entities to avoid XSS attacks in DataTables
2014-10-29 10:29:21 -07:00
Winston Chang
32f5d68e51 Merge pull request #638 from wch/option-docs
Add documentation for global options
2014-10-29 11:31:09 -05:00
Winston Chang
855347a5d3 Add documentation for global options 2014-10-29 11:30:28 -05:00
Yihui Xie
78c22cb74a a news item for #630 2014-10-28 16:17:05 -05:00
Yihui Xie
8626a3efea make escape support column names in renderDataTable(), per suggestion of @jcheng5 2014-10-28 16:11:06 -05:00
Yihui Xie
d7e0d64ac2 fix the issue reported by Tareef: dplyr tbl_df objects are also data frames, but the default non-standard evaluation df[, j] will fail in dataTablesJSON(), so we need to coerce such objects to data frames explicitly 2014-10-28 16:11:06 -05:00
Yihui Xie
e26b1e54c8 a news item for #627 [ci skip] 2014-10-28 16:11:06 -05:00
Yihui Xie
594024472d apply escape to column names as well 2014-10-28 16:11:06 -05:00
Yihui Xie
5f60d09d0b per-column escaping 2014-10-28 16:11:06 -05:00
Yihui Xie
a05abda25c escape HTML entities to avoid XSS attacks in DataTables
BTW, per recommendation of http://datatables.net/manual/server-side, the parameter `draw` is coerced to integer
2014-10-28 16:11:06 -05:00
Winston Chang
daa8e44180 Update NEWS 2014-10-28 15:52:13 -05:00
Winston Chang
837a26daee Bump version to 0.10.2.9002 2014-10-28 15:48:47 -05:00
Joe Cheng
1223d3a2b3 Merge pull request #604 from rstudio/bugfix/observer-errors
Better handling of observer errors
2014-10-28 13:12:13 -07:00
Joe Cheng
a4d7eaf709 Merge pull request #630 from yihui/feature/httpuv-encode
use encodeURI[Component]() and decodeURIComponent() from httpuv
2014-10-28 13:08:04 -07:00
Yihui Xie
4b12d5527b increase version requirement of httpuv 2014-10-28 14:13:09 -05:00
Joe Cheng
e7553d6f15 Add observeEvent and eventReactive functions 2014-10-23 12:03:45 -07:00
Yihui Xie
b795d7de4e use encodeURI[Component]() and decodeURIComponent() from httpuv 2014-10-20 18:15:25 -05:00
Joe Cheng
e732afd64c Merge remote-tracking branch 'origin/feature/bootstrap-navbar-pos' 2014-10-20 13:16:42 -07:00
Winston Chang
40b25e3826 Merge pull request #597 from rstudio/selectize-0.11.0
Update to selectize 0.11.0
2014-10-20 15:13:13 -05:00
Winston Chang
b4d80b467a Merge pull request #610 from yihui/bugfix/DT-POST
fixes #605: send DT requests via POST instead of the default GET
2014-10-20 15:11:59 -05:00
Joe Cheng
62ef377dd1 Remove eventFilter for now
After discussing with @trestletech, the semantics are just not right.
When using it with a renderXXX function, it doesn't actually stop
recomputation, so the only reasonable place to use it is in a reactive
expression, but if that's true then this is a terrible looking API.
Will replace soon with something better.
2014-10-14 12:36:03 -07:00
Joe Cheng
b85b1e95b4 Fix documentation bug in ?validate 2014-10-14 12:30:11 -07:00
Joe Cheng
f2ab7001d2 Fix eventFilter logic 2014-10-14 10:10:08 -07:00
Joe Cheng
7fa6a2e9ef Fix action button 2014-10-14 09:25:52 -07:00
Joe Cheng
c499bbaa9f Update NEWS, bump version 2014-10-13 14:28:44 -07:00
Joe Cheng
f2b16c414f Merge remote-tracking branch 'origin/pr/180'
Conflicts:
	NAMESPACE
	R/bootstrap.R
	R/reactives.R
	R/shiny.R
2014-10-13 14:24:44 -07:00
Winston Chang
2a73e28b19 Merge pull request #615 from seanchrismurphy/patch-1
Update shiny.R
2014-10-12 09:21:58 -05:00
Sean Murphy
9252d1290c Update shiny.R
Update link to shiny tutorial (http://shiny.rstudio.com/tutorial/)
2014-10-12 22:16:28 +10:00
Yihui Xie
049bd85b29 fixes #605: send DT requests via POST instead of the default GET 2014-10-07 17:17:48 -05:00
Winston Chang
f95a0fa1d3 Update NEWS 2014-10-07 09:45:27 -05:00
Winston Chang
416466a0e1 Bump version to 0.10.2.9000 2014-10-07 09:44:19 -05:00
Winston Chang
bfd97c5484 Remove explicit dependency install for travis 2014-10-06 13:15:16 -05:00
Winston Chang
9c1badd6aa Fix test to avoid printing message
The recent release of testthat now displays messages in test blocks, which revealed that
this test needed to be updated.
2014-10-06 12:33:09 -05:00
Winston Chang
929cb29c5b Add global option for error handler function 2014-10-06 12:26:03 -05:00
Winston Chang
1e788962ef Merge pull request #607 from saurfang/patch-1
Use ... in actionButton and actionLink
2014-10-06 11:51:52 -05:00
saurfang
26f8c11526 Add ... to actionButton and actionLink 2014-10-04 13:00:29 -04:00
Winston Chang
a9b3922061 Remove unused withCallingHandlers() 2014-10-03 16:19:03 -05:00
Winston Chang
00ebe4fab2 Add test for observer error handling 2014-10-03 16:17:49 -05:00
Joe Cheng
1bee6aece7 Better handling of observer errors
- Unhandled observer error no longer stops flushReact in mid-flush
- Observer errors are now warnings that include the observer label
- Session is explicitly being closed by Shiny instead of by httpuv

Also:
- session$close() is now public and closes the session
2014-10-02 11:13:23 -07:00
Winston Chang
be4eff413d Bump version to 0.10.2.1 2014-10-01 10:44:44 -05:00
Winston Chang
e56571840b Change some examples to donttest, to make CRAN happy 2014-10-01 10:32:10 -05:00
Winston Chang
f931222256 Update NEWS 2014-09-29 15:21:43 -05:00
Winston Chang
25ff7d430d Bump selectize version in html dependencies 2014-09-29 15:21:43 -05:00
Winston Chang
d9cf3ceb9b Update to Selectize 0.11.2 with computedstyle fix
Fixes #596
2014-09-29 15:21:43 -05:00
Winston Chang
c37a84ab4d Bump version to 0.10.2 2014-09-29 12:18:36 -05:00
Winston Chang
cf97fc9b95 Merge pull request #598 from yihui/feature/ie8-uploads
IE8/9 file upload
2014-09-29 10:15:06 -05:00
Yihui Xie
03a8651cfd use typeof(x) === 'undefined' instead of x === undefined 2014-09-26 16:57:57 -05:00
Yihui Xie
b206525f8e add a news item for file uploading in IE8/9 2014-09-25 18:07:58 -05:00
Yihui Xie
443850b778 fileInput() works for IE8/9 now, but they do not support multiple files 2014-09-25 18:04:50 -05:00
Yihui Xie
6962fbf6f7 do not store the FileUploader in el.data('currentUploader') for IE (it does not have the .abort() method) 2014-09-25 17:47:41 -05:00
Yihui Xie
a2a7173e30 use the IE8 file uploader only for IE 2014-09-25 17:17:28 -05:00
Yihui Xie
698ad2b890 I do not see why this needs to be changed 2014-09-25 17:07:22 -05:00
Yihui Xie
dd43a82042 IE8 does not support iframe.onload; we need to use .attachEvent() instead 2014-09-25 17:02:08 -05:00
Yihui Xie
a25515dc2b install mime for travis ci 2014-09-25 14:51:41 -05:00
Yihui Xie
e1a8e119bf Add import for mime 2014-09-25 14:51:34 -05:00
Joe Cheng
4712b72019 Force IE8 uploads to kick off reactive flush 2014-09-25 14:28:42 -05:00
Yihui Xie
2d162b0d4e parse the multipart form data POSTed and save the file info in .input 2014-09-25 14:28:42 -05:00
Yihui Xie
1ea4b4d0b5 the iframe does not need src, and we should attach the onload event after it is appended to body, otherwise it will be destroyed immediately 2014-09-25 14:28:42 -05:00
Yihui Xie
c75c7019a8 the key problem with the form submission was that the name was missing 2014-09-25 14:28:42 -05:00
Yihui Xie
67ab5fbc8a return a valid response temporarily 2014-09-25 14:28:42 -05:00
Yihui Xie
31a5bee228 if evt.target.files is undefined, it is probably IE8; we will use iframe from POST to upload the files later 2014-09-25 14:28:42 -05:00
Yihui Xie
bcd7195bf5 use uploadie instead of upload2 because of regexec("^/([a-z]+)/([^?]*)" earlier ([a-z]+ won't match upload2) 2014-09-25 14:28:42 -05:00
Yihui Xie
322a9d397a config.sessionId is in this.shinyapp instead of this 2014-09-25 14:28:42 -05:00
Yihui Xie
71e6646ea0 use encodeURI() instead of the deprecated escape() 2014-09-25 14:28:42 -05:00
Joe Cheng
b505507c35 file upload via <iframe> for IE8 2014-09-25 14:28:42 -05:00
Winston Chang
76535c1da5 Add missing entries to staticdocs index 2014-09-24 11:21:29 -05:00
Winston Chang
9edd94e1c0 Fix incomplete sentence 2014-09-16 13:59:48 -05:00
Winston Chang
32449b3c55 Re-document with roxygen2 4.0.2 2014-09-16 13:55:16 -05:00
Winston Chang
76c3d38e11 Add inc method to Progress 2014-09-16 13:54:17 -05:00
Winston Chang
0e8ed7d770 Refactor Progress to have private members 2014-09-11 14:22:01 -05:00
Winston Chang
5af4743f2f withProgress: evaluate expression in calling env, not in a child 2014-09-11 13:30:58 -05:00
Joe Cheng
ab86232294 Add position parameter to navbarPage 2014-09-10 22:59:35 -07:00
JJ Allaire
0202daf551 bump version 2014-09-10 14:28:29 -04:00
Winston Chang
3b062de156 Update travis config: htmltools 0.2.6 is on CRAN 2014-09-08 13:49:11 -05:00
Joe Cheng
65786c4d41 Fix off-by-one error in dependency attachments 2014-09-05 14:57:49 -07:00
Yihui Xie
d3bb742308 Merge pull request #586 from trestletech/doc/serverInfo
Added a clarifying comment to serverInfo.
2014-09-04 17:14:41 -05:00
trestletech
f98aa3f12b Added a clarifying comment to serverInfo. 2014-09-04 16:30:35 -05:00
Winston Chang
70881bb367 Update NEWS 2014-09-04 15:54:48 -05:00
Winston Chang
50adb5fdf5 sliderInput: Round using min value as baseline. Fixes #301
This uses jslider commit da06841.
2014-09-04 15:00:19 -05:00
Winston Chang
c05701fc19 sliderInput: fix rounding bug. Fixes #502
This uses jslider from commit 22cd17e
2014-09-04 14:37:11 -05:00
Yihui Xie
5e68b5f3e3 bump version 2014-09-03 17:22:35 -05:00
Yihui Xie
5f46d97409 fixes #306: should use file_test('-d') to check if a directory exists, instead of file.exists(), because file.exists('foo/') is FALSE even if the directory foo exists
I was bitten by this once before: a874ac5b66
2014-09-03 17:21:50 -05:00
Yihui Xie
7f07e47488 update URL in DESCRIPTION 2014-09-03 17:21:50 -05:00
Jeff Allen
3999f4d3a5 Updated external links to the Shiny Dev Center. 2014-09-03 11:18:24 -05:00
Yihui Xie
b3d6220b01 fixes #581: check for undefined instead of null 2014-08-29 15:31:10 -05:00
Winston Chang
7d88775b5a Faster Map implementation 2014-08-28 23:12:09 -05:00
Winston Chang
2ca5d3e0df Restore class attribute for Map
This is because there are S3 methods for Map.
2014-08-28 23:07:46 -05:00
Winston Chang
3f34030a12 Cleaner method of getting execCount 2014-08-28 20:21:45 -05:00
Winston Chang
11dfa3d9aa Remove unneeded @.Data field 2014-08-28 20:21:45 -05:00
Winston Chang
6923a11038 Don't add class attribute for internal-facing classes
The class attribute is unneded for these classes, and this improves
performance.
2014-08-28 20:21:05 -05:00
Winston Chang
33d78fcf29 Update NEWS 2014-08-28 19:44:43 -05:00
Winston Chang
2b3cfdf18b Migrate reactlog to use Stack 2014-08-28 19:20:10 -05:00
Winston Chang
aa7a3f7013 Reverse order of Stack as_list() 2014-08-28 19:14:15 -05:00
Winston Chang
1e1b3c8f5f Faster stack implementation 2014-08-28 17:31:53 -05:00
Yihui Xie
a7cac36974 bump version 2014-08-28 16:58:36 -05:00
Yihui Xie
3af800e522 add the R version requirement to NEWS 2014-08-28 16:57:06 -05:00
Yihui Xie
cf135dd658 Revert "Revert "Remove caTools dependency""
This reverts commit 8d4b9076f7.

The main concern for the previous reversion was the Glimmer/Spark servers (Rcpp requires R >= 3.0.0). We are able to install Rcpp/httpuv under R 2.15.3 (https://gist.github.com/yihui/43a68d811dade1d9e828), so it is possible to upgrade Rcpp/httpuv/shiny on Glimmer/Spark. On the other hand, we are going to shut down Glimmer/Spark by the end of this year anyway, and move to ShinyApps.io, which makes this R 3.x issue even less of concern.
2014-08-28 16:55:03 -05:00
Winston Chang
4e9d113896 Bump version to 0.10.1.9005 2014-08-28 16:31:30 -05:00
Winston Chang
af8e81d208 Update NEWS 2014-08-28 16:31:22 -05:00
Winston Chang
83fa1ea4a6 Merge pull request #580 from wch/r6class
Migrate from reference classes to R6
2014-08-28 16:21:39 -05:00
Winston Chang
a72f8b7b65 Merge pull request #579 from yihui/feature/DT-caseInsensitive
Case insensitive searching in DataTables
2014-08-28 16:21:16 -05:00
Winston Chang
1b940a3117 Install R6 for travis 2014-08-28 16:02:40 -05:00
Winston Chang
5012831e7b Add tests for nested query strings 2014-08-28 15:59:50 -05:00
Winston Chang
85fb08e9a5 Update tests for R6 2014-08-28 15:45:56 -05:00
Winston Chang
7ac84b6a91 Switch from refclasses to R6 2014-08-28 15:45:44 -05:00
Yihui Xie
3a72526016 update news to reflect changes in DataTables 2014-08-28 15:38:55 -05:00
Yihui Xie
c3e78f41b0 implement case-[in]sensitive searching on the server side (#400)
grep2() was invented to deal with these situations:

1. case-insensitive and fixed matching
2. when the regex is incomplete
2014-08-28 15:38:47 -05:00
Yihui Xie
fdea9dddee send search.caseInsensitive to the server to make it possible to do case-insensitve searching 2014-08-28 15:30:43 -05:00
Winston Chang
2d3dd7d91d Field type should be a string 2014-08-27 14:09:39 -05:00
Winston Chang
2487245e94 Replace == with === 2014-08-26 13:23:38 -05:00
Joe Cheng
a4f12691ce Use encodeURI instead of escape 2014-08-26 09:41:00 -07:00
Winston Chang
e7e83eb8bb Merge pull request #576 from yihui/bugfix/DT-searchbox
escape the placeholders of search boxes in DataTables, and strip the HTML tags off
2014-08-26 11:02:14 -05:00
Yihui Xie
e8ffb68c08 escape the placeholders of search boxes in DataTables, and strip the HTML tags off 2014-08-25 16:45:00 -05:00
Yihui Xie
283f69cb65 use the latest version of htmltools 2014-08-22 12:16:45 -05:00
Winston Chang
0fb4ab2dcf Merge pull request #558 from yihui/feature/datatables1.10
DataTables 1.10.2
2014-08-22 12:02:39 -05:00
Yihui Xie
063ac989be closes yihui/shiny#4 after cleaning it up a bit
use [searchField] instead of $.makeArray(), and unlist() it on the R side
2014-08-22 00:11:00 -05:00
Xin Yin
82fb11a7b5 Adopted Yihui's suggestion to use $.makeArray() to fix a bug with searchField option in selectizeInput(), caused by RJSONIO:::fromJSON() 2014-08-21 23:58:50 -05:00
Yihui Xie
d238d61906 need a newer version of htmltools due to 5f4c8cf176 and the bug rstudio/htmltools#7 2014-08-21 15:28:53 -05:00
Yihui Xie
22fdc90159 add instructions for upgrading from DataTables 1.9 to 1.10 2014-08-21 14:24:39 -05:00
Yihui Xie
b6cf4c4375 background color for selected rows 2014-08-21 12:12:34 -05:00
Yihui Xie
8aa32fff34 get rid of the ugly trick eval(parse()), and use a plain loop to create a nested list 2014-08-21 12:10:26 -05:00
Yihui Xie
76d6ffea4a tweak doc and roxygenize 2014-08-21 12:10:26 -05:00
Yihui Xie
ea8ca8ea1e new option names for DataTables from Hungarian to camelCase notations 2014-08-21 12:10:26 -05:00
Yihui Xie
ed9ca04c58 support [] in query strings like $_GET in PHP, because server-side DataTables 1.10 passes parameters as arrays
e.g. columns[0][search][value]=foo&columns[1][search][value]=bar

we need list(columns = list(`0` = list(search = list(value = 'foo')), `1` = ...)
2014-08-21 12:10:26 -05:00
Yihui Xie
093fbaa178 the names of keys and values are useless 2014-08-21 12:10:26 -05:00
Yihui Xie
5f4c8cf176 tweaking the bootstrap style copied from DataTables:
1. sorted columns have different colors;
2. correct position of the processing info;
3. override the width of text input (search fields), otherwise they will be too wide (206px defined in bootstrap.min.css);
2014-08-21 12:10:06 -05:00
Yihui Xie
c7ee37804c fix a bug when the number of rows of data to show is zero
all(logical(0)) == TRUE!
2014-08-21 11:35:37 -05:00
Yihui Xie
e0c31aa5af upgrade DataTables from 1.9.4 to 0.10.2; closes #487 2014-08-21 11:35:37 -05:00
Yihui Xie
ab1494777d fixes #573: use the new MathJax CDN 2014-08-20 16:40:00 -05:00
Winston Chang
c01fafb605 Bump version to 0.10.1.9004 2014-08-20 11:49:47 -05:00
Winston Chang
5be2ffc0b2 Update NEWS 2014-08-20 11:49:37 -05:00
Winston Chang
3ede9396da Merge branch 'progress'
Conflicts:
	NAMESPACE
2014-08-20 11:31:28 -05:00
Winston Chang
e400a7a15e Update progress documentation 2014-08-20 11:25:28 -05:00
Winston Chang
2939006a9a Merge pull request #571 from rstudio/feature/dependency-attachment
Add createWebDependency and renderDependencies functions
2014-08-20 09:48:44 -05:00
Winston Chang
df975a0b6b Add missing semicolon 2014-08-20 09:48:25 -05:00
Joe Cheng
bda86de632 Update metadata 2014-08-19 09:54:32 -07:00
Joe Cheng
5738a4ba48 Add createWebDependency and renderDependencies functions 2014-08-18 13:27:55 -07:00
Joe Cheng
38cfa46131 Roxygenize 2014-08-18 13:27:15 -07:00
Winston Chang
9525df1381 Add missing semicolon 2014-08-15 16:36:45 -05:00
Winston Chang
d393577ba8 uiHttpHandler: return NULL if no ui
This restores missing UI detection for single-file apps, which was lost
in 0f431ed.
2014-08-13 15:39:18 -05:00
Winston Chang
f7c2a07b70 Update NEWS 2014-08-13 15:32:08 -05:00
Winston Chang
adf69b4890 Look for server.R before app.R 2014-08-13 15:30:40 -05:00
Winston Chang
593d22b640 Bump version to 0.10.9002 2014-08-13 14:48:45 -05:00
Winston Chang
7706eebafb Remove single file example
The example will be moved to the gallery.
2014-08-13 14:22:26 -05:00
Joe Cheng
91bd5127fb Merge pull request #563 from rstudio/single-file2
Single-file app support
2014-08-12 19:24:58 -07:00
Winston Chang
b87a0d7f25 Automatically display app.R file in showcase mode 2014-08-12 16:47:41 -05:00
Winston Chang
0f431ed384 Detect showcase mode for single-file apps 2014-08-12 16:36:00 -05:00
Winston Chang
d520921b13 Merge pull request #564 from rstudio/feature/output-resize
Add support for resize(el, width, height) method on output bindings
2014-08-12 15:13:22 -05:00
Joe Cheng
8d4b9076f7 Revert "Remove caTools dependency"
This reverts commit e4239c924b.

I totally forgot the problems this causes with R 2.15 and thus
glimmer/spark. httpuv 1.2.2 requires Rcpp 0.11 which requires
R 3.0. So existing installs (like glimmer/spark) that are
running just fine with httpuv 1.2.0 will be forced to upgrade,
which is hard to do when you don't know the provenance of
all the packages installed by your users.
2014-08-12 10:24:33 -07:00
Joe Cheng
93ebbcaf04 Merge pull request #567 from rstudio/feature/remove-prefix-warning
remove addResourcePath warning for overriding an existing prefix
2014-08-09 12:45:14 -07:00
JJ Allaire
ecde1580fd remove addResourcePath warning for overriding an existing prefix 2014-08-09 06:39:27 -04:00
Joe Cheng
8f73bb222c Add support for resize(el, width, height) method on output bindings 2014-08-08 00:43:02 -04:00
Winston Chang
1108e04eff Update missing-UI web page to include app.R 2014-08-07 13:26:07 -05:00
Winston Chang
0f1a8f3358 Add single-file app example 2014-08-07 13:25:49 -05:00
Winston Chang
77de4df0ff shinyApp: use NULL default for ui and server
This is so that, when a single-file app returns a shinyApp with a blank
`ui` argument, Shiny will not error out, and instead it can search for
a www/ subdirectory.
2014-08-07 13:18:21 -05:00
Winston Chang
0564de37ee Add support for shinyAppDir with single-file app.R 2014-08-06 21:51:36 -05:00
Winston Chang
8c584ae0e0 Refactor file.path.ci, add find.file.ci and file.exists.ci 2014-08-06 21:19:46 -05:00
Winston Chang
30c80279c8 Remove accidental browser() 2014-08-06 21:18:45 -05:00
Winston Chang
3f0ab9a88a Fixes to file.path.ci
There were two bugs, which are fixed:
* It didn't find files starting with '.' because `all.files` defaults to FALSE.
* It was too loose with file matching - the `pattern` argument to list.files
  is a regexp, not string literal.
2014-08-06 12:19:08 -05:00
Winston Chang
6da3fcf446 Add container for all progress items 2014-08-04 16:01:47 -05:00
Winston Chang
26746ca303 Don't use multiline string in JS 2014-08-01 21:11:44 -05:00
Winston Chang
64158eac43 Make progress position more customizable 2014-08-01 21:11:03 -05:00
Yihui Xie
9e3a7f5eda a typo in the news for 0.10.1 2014-08-01 17:16:47 -05:00
Yihui Xie
0a4f3db8ae bump version 2014-08-01 16:37:20 -05:00
Yihui Xie
c095085d84 fixes #557: choicesWithNames() turns a character vector to a list, which is no longer appropriate as a column in data.frame() 2014-08-01 16:37:20 -05:00
Yihui Xie
41cc4e68e3 no need to use wrap = FALSE for roxygen2 now 2014-08-01 16:37:20 -05:00
Winston Chang
21fb7959a5 Fix edge case with nested choices. Fixes #560
When the set of choices is a list containing a named vector of length 1,
choicesWithNames would return the wrong result.
2014-08-01 16:11:51 -05:00
Yihui Xie
3aa22127e0 a consequence of PR #552 is R 3.0.0
those who still wish to install shiny under R 2.15.x may take a look at these instructions: https://gist.github.com/yihui/43a68d811dade1d9e828
2014-08-01 15:28:43 -05:00
Winston Chang
a679a37ffa Make progressHandlers a simple object 2014-08-01 15:16:54 -05:00
Winston Chang
649857ec28 Update NAMESPACE 2014-07-30 14:15:42 -05:00
Winston Chang
4a6136b918 Fade in bars 2014-07-30 14:15:42 -05:00
Winston Chang
6e1c468a80 Simplify R API for progress 2014-07-30 14:15:42 -05:00
Winston Chang
cadcd0c5e8 Export Progress generator 2014-07-30 14:15:42 -05:00
Winston Chang
a531c306f1 Make progress bar show on top 2014-07-30 14:15:42 -05:00
Winston Chang
b0a9449335 Simplify argument handling 2014-07-30 14:15:42 -05:00
Winston Chang
b6deb87cae Unify binding and page-level progress interface 2014-07-30 14:15:41 -05:00
Winston Chang
7319c88674 Use new message format for progress reporting 2014-07-30 14:15:41 -05:00
Winston Chang
d36317c563 Add missing 'var' 2014-07-30 14:15:41 -05:00
Winston Chang
1917202bd0 Improve handling of closed progress 2014-07-30 14:15:41 -05:00
Winston Chang
a8338912e0 Simplify code 2014-07-30 14:15:41 -05:00
Winston Chang
bfea3201e8 Put progress stack in session object 2014-07-30 14:15:41 -05:00
Winston Chang
a9bb440e6c Add Stack ref class 2014-07-30 14:15:41 -05:00
Winston Chang
f0942d58e8 Get session without needing to pass it in 2014-07-30 14:15:40 -05:00
Winston Chang
aa093659a0 Copy over progress code from shinyIncubator 2014-07-30 14:15:40 -05:00
Winston Chang
cccdbc05a5 Bump to development version number 2014-07-27 22:22:22 -05:00
Winston Chang
dfa32b7be4 Merge tag 'v/0/10/1'
Shiny 0.10.1 released to CRAN
2014-07-27 22:19:44 -05:00
Winston Chang
c7e0bd037a Merge pull request #552 from rstudio/no-catools
Remove caTools dependency
2014-07-25 14:43:15 -05:00
Winston Chang
6c711b76b0 Bump version to 0.10.1 2014-07-25 14:20:43 -05:00
Winston Chang
9c914f10c4 Merge pull request #553 from wch/hidden-selectize
Add custom version of selectize.js to work around Firefox bug
2014-07-25 13:37:08 -05:00
Winston Chang
eda56d118a Merge pull request #549 from yihui/bugfix/utf8-bom
warn against the byte order mark if exists; fixes #545
2014-07-24 16:09:56 -05:00
Winston Chang
02c7351c6d Add custom version of selectize.js to work around Firefox bug
This is a workaround for issue #550. This version is based on selectize version 0.9.1.
2014-07-24 15:29:23 -05:00
Yihui Xie
ab618235f1 one more check before we use UTF-8: see if there are embedded nul's 2014-07-24 14:48:23 -05:00
Joe Cheng
e4239c924b Remove caTools dependency
Instead, use base64 encoding function from httpuv
2014-07-24 10:37:14 -07:00
Yihui Xie
ffead9ed70 add explanations of skipping *nix when checking encoding, and point to the shiny dev center article 2014-07-24 11:57:46 -05:00
Winston Chang
36aefadced Merge pull request #550 from rstudio/bugfix/offscreen-shinyapps
Deal gracefully with elements that have no computed style available
2014-07-23 11:55:24 -05:00
Jonathan McPherson
75ccfe38ce update comment with more specific browser notes 2014-07-23 09:43:42 -07:00
Jonathan McPherson
e3cb3fe2e4 deal gracefully with elements that have no computed style available 2014-07-22 14:41:34 -07:00
Yihui Xie
983e7e9b75 warn against the byte order mark if exists; fixes #545 2014-07-22 16:22:50 -05:00
Yihui Xie
3db47c076c a news item for the optgroup feature 2014-07-18 14:40:58 -05:00
Yihui Xie
eeff285b33 add links to examples in shiny dev center 2014-07-18 14:40:31 -05:00
Yihui Xie
029595f8ea an edge case selectInput(choices = NULL)
firstChoice() may fail with an error "subscript out of bounds"
2014-07-17 15:59:33 -05:00
Yihui Xie
ea2ec27724 bump version 2014-07-17 14:52:26 -05:00
Yihui Xie
f6bf4a416f Merge pull request #537 from yihui/bugfix/native-encoding
Use native encoding internally
2014-07-17 14:49:53 -05:00
Yihui Xie
af978a68e3 tweak the warning message
and simply stop() in case the user has set option(encoding = 'UTF-8')
2014-07-17 14:39:21 -05:00
Yihui Xie
89dc1323e1 add a note section about the clickId/hoverId arguments in plotOutput(), since they seem to have been confusing grid graphics users
and re-wrap the roxygen comments
2014-07-16 17:27:00 -05:00
Yihui Xie
a4b5f63deb a single quote ' was omitted here, making the Rd for plotOutput() incomplete since this line was ignored 2014-07-16 17:27:00 -05:00
Winston Chang
feaa6ccff4 Merge pull request #542 from rstudio/feature/select-optgroup
Feature/select optgroup (closes #520)
2014-07-16 17:22:29 -05:00
Winston Chang
7159293337 Use consistent indentation for function definitions 2014-07-16 17:04:22 -05:00
Winston Chang
4a5b31e3a7 Simplify needOptgroup function 2014-07-16 16:57:17 -05:00
Winston Chang
6f1dc89fb3 Enable union merge for NEWS 2014-07-16 16:48:56 -05:00
Yihui Xie
29dd405fe5 the options and ... arguments are no longer needed 2014-07-16 15:50:31 -05:00
Yihui Xie
0f0b0cd3d8 explicitly define updateSelectInput() instead of using the trick to change the options argument of updateInputOptions() 2014-07-16 15:50:08 -05:00
Winston Chang
262528e36a Add tests for deeper nesting with choicesWithNames 2014-07-16 12:07:13 -05:00
Winston Chang
597e86dd57 Make listify work on nested lists of depth > 1 2014-07-16 12:02:55 -05:00
Winston Chang
b604dba948 Add tests for default selected items 2014-07-16 00:52:29 -05:00
Winston Chang
1837a64bd2 Add tests for selectOptions 2014-07-16 00:51:57 -05:00
Winston Chang
9b413de4d8 selectOptions: handle mixed options and optgroups 2014-07-16 00:51:57 -05:00
Winston Chang
3d77cbd677 Slight clarification of comment 2014-07-16 00:51:57 -05:00
Winston Chang
62176c3218 Add tests for choicesWithNames 2014-07-16 00:51:57 -05:00
Winston Chang
d7a01c32cc Always convert choices to a (named) list
Converting it to a list, and ensuring that it's a named list reduces
many checks elsewhere.
2014-07-16 00:51:57 -05:00
Yihui Xie
cc493fd545 fall back to native encoding on Windows if UTF-8 does not work 2014-07-15 16:05:23 -05:00
Yihui Xie
6b8679454d factor out .Platform$OS.type == 'windows' as isWindows() 2014-07-15 16:04:02 -05:00
Yihui Xie
1b68d61e54 R CMD check will warn against the possibly missing variables inline and type 2014-07-11 17:36:37 -05:00
Yihui Xie
418de862e6 rename newOptions to config 2014-07-11 14:17:08 -05:00
Yihui Xie
413653858e inherit doc for updateFooInput() from fooInput() 2014-07-11 14:03:47 -05:00
Yihui Xie
f0886a7556 when we need <optgroup> for the child elements of choices, we just generate it no matter what the child element is
e.g. we use <optgroup> for A even if A only has one element: list(A = 'a', B = c('b1', 'b2'))
2014-07-11 14:03:47 -05:00
Yihui Xie
0e2666948f when choice is not a list, we need to return its first element 2014-07-11 14:03:47 -05:00
Yihui Xie
d2fc851816 make updateSelectInput(), updateCheckboxGroupInput(), and updateRadioButtons() work
now session$sendInputMessage() does not send options as the choices data, but as a pre-generated raw HTML string; in shiny.js, we just receive this string, and .append() it to the input after the input is emptied
2014-07-11 14:03:47 -05:00
Yihui Xie
e1fb29c8c5 factor out the code to generate options from checkboxGrouptInput() and radioButtons(), and use the new generator generateOptions() for them 2014-07-11 14:03:47 -05:00
Yihui Xie
fe3158fdd6 validateSelected() does not validate selected for the optgroup case; this function is only for shiny <= 0.9 2014-07-11 14:03:47 -05:00
Yihui Xie
721b26f80b choicesWithNames() should also consider the optgroup case now: all optgroup nodes must be named 2014-07-11 14:03:47 -05:00
Yihui Xie
d3ecfb22ee closes #326: generate <optgroup> when choices is a named list of choices
note the nested level of optgroup can be greater than one here, however, the HTML4 spec only allows one level, i.e. optgroup must have select as its direct parent http://stackoverflow.com/q/1037732/559676
2014-07-11 14:03:47 -05:00
Yihui Xie
27a98020c9 recursively select the first choice, to make sure selected is a scalar, even when choices is a list of lists (optgroup) 2014-07-11 14:03:47 -05:00
Yihui Xie
ab56b72f39 json2.js modified and uglified from https://github.com/yihui/JSON-js via http://lisperator.net/uglifyjs/
I'm using the date of json2 as its version number, since it does not really have a version number

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

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

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

Too-aggressive capture.output was causing browser() not to work in
renderPlot().
2014-06-24 06:09:36 -07:00
Yihui Xie
27f8909406 bump version 2014-06-19 13:50:39 -05:00
Yihui Xie
9988206911 add news for #512 2014-06-19 13:50:06 -05:00
Joe Cheng
31fe1fdfa6 Merge pull request #523 from rstudio/feature/navbarPage-windowTitle
Add windowTitle parameter to navbarPage
2014-06-19 10:45:01 -07:00
Joe Cheng
77b125ce2d Add windowTitle parameter to navbarPage
Fixes #493
2014-06-19 09:36:50 -07:00
Joe Cheng
6e68e07aa2 Merge pull request #512 from yihui/feature/inline-output
Inline output in R Markdown documents
2014-06-19 09:20:13 -07:00
Yihui Xie
86bb010a93 roxygenize 2014-06-19 00:24:10 -05:00
Yihui Xie
4a623b596b ignore width/height in plotOutput() when inline=TRUE, and document required width/height values in renderPlot() 2014-06-19 00:24:10 -05:00
Yihui Xie
bcf098ea7d merge doc of width and height in renderPlot() and plotOutput() 2014-06-19 00:24:10 -05:00
Yihui Xie
4bfb226fb5 roxygenize 2014-06-19 00:24:10 -05:00
Yihui Xie
691615108b preserve the formal arguments of plotOutput() in outputFunc()
otherwise outputFunc() loses the `inline` argument, and knit_print() won't be able to produce inline plots
2014-06-19 00:24:10 -05:00
Yihui Xie
858ab00e36 closes #501: knit_print() for inline output uses the inline argument passed from knitr 2014-06-19 00:24:10 -05:00
Yihui Xie
7023f5b145 add an inline argument to textOutput(), imageOutput(), plotOutput(), and htmlOutput() 2014-06-19 00:24:10 -05:00
Yihui Xie
eb4fabeac6 fix two more staticdocs errors 2014-06-19 00:17:55 -05:00
Joe Cheng
a5e09f9ce4 Merge tag 'v/0/10/0-staticdocs' 2014-06-18 11:12:40 -07:00
Joe Cheng
c2fe4e8b6d Fix staticdoc errors 2014-06-18 11:11:21 -07:00
Winston Chang
5d22648d34 Merge pull request #513 from rstudio/feature/json-precision
Control precision of JSON numeric representation
2014-06-17 11:51:47 -05:00
Yihui Xie
066fd15184 quiet apt-get and install.packages() 2014-06-16 10:32:04 -05:00
Yihui Xie
fe90c230d5 r-base should just work, since the packages that need to be compiled are installed via apt-get 2014-06-16 10:07:54 -05:00
Yihui Xie
0b5ae92136 shiny 0.10.0 is on CRAN now, so the dependencies knitr and htmltools should be automatically detected 2014-06-16 10:05:33 -05:00
Yihui Xie
1c5565aaee a news item for #427 2014-06-16 09:59:32 -05:00
Yihui Xie
69c177a3ec a news item for #516 2014-06-16 09:50:59 -05:00
Joe Cheng
0645b3f65b Merge pull request #507 from yihui/doc/runUrl
Merge doc for runUrl(), runGist(), and runGitHub()
2014-06-16 01:19:52 -07:00
Joe Cheng
9e7471fcc0 Merge pull request #516 from yihui/bugfix/windows-encoding
Fixes #136: I18N support for Windows
2014-06-16 01:17:31 -07:00
Joe Cheng
c520f53799 Bump to development version number 2014-06-16 01:13:33 -07:00
Yihui Xie
0bf1386802 UTF8 encoding for runApp(list(ui, server)) as well 2014-06-13 18:53:36 -05:00
Yihui Xie
b2ab3797aa the cachedSource() function is not used anywhere, so perhaps we can remove it 2014-06-13 18:08:16 -05:00
Yihui Xie
ede0ca8bd1 make sure JSON messages are always encoded and decoded with UTF8
- per @jcheng5's suggestion, RJSONIO::fromJSON(encoding = 'UTF-8') actually works (no longer need my markUTF8 function)
- removed the global option 'shiny.transcode.json'
2014-06-13 18:07:01 -05:00
Yihui Xie
81e35f0cc3 make sure the HTML content is encoded in UTF8 2014-06-13 18:02:20 -05:00
Yihui Xie
237522a1f7 assuming all the input R scripts are UTF8 encoded
ui.R, server.R, and global.R
2014-06-13 18:00:46 -05:00
Joe Cheng
2f94e1d2c9 Fix timing issue with random seed test on windows 2014-06-13 14:40:19 -07:00
Joe Cheng
2689dd32bb Bump version to 0.10.0 2014-06-13 09:41:45 -07:00
Winston Chang
ad5e703b8f Merge pull request #514 from yihui/doc/news-flowLayout
typo: flowPanel --> flowLayout
2014-06-13 11:12:07 -05:00
Yihui Xie
d3bc2e9279 typo: flowPanel --> flowLayout 2014-06-13 11:05:36 -05:00
Joe Cheng
0cd1644cf1 Control precision of JSON numeric representation
Uses 16 digits by default, set shiny.json.digits option to customize
2014-06-10 15:02:45 -07:00
Winston Chang
f02b405c12 Merge pull request #508 from yihui/bugfix/large-margin
set the margin to 0 before plot.new()
2014-06-10 11:57:07 -05:00
Yihui Xie
baa7036799 explain why par(mar = rep(0, 4)) is necessary before plot.new(), per @wch's suggestion 2014-06-10 11:50:49 -05:00
Yihui Xie
431aecaf00 set the margin to 0 before plot.new()
otherwise users will be unable to draw small plots because of the common error "figure margin too large", e.g. renderPlot(..., width=200, height=100)
2014-06-10 00:46:33 -05:00
Yihui Xie
f31bb56ea6 subdir=NULL is the default of runUrl() 2014-06-09 22:24:51 -05:00
Yihui Xie
cf3b805c46 the message is not very useful, given that download() will emit a message 2014-06-09 22:24:51 -05:00
Yihui Xie
517283ca58 closes #427: runGitHub() can accept "username/repo" in its first argument 2014-06-09 22:24:51 -05:00
Yihui Xie
f416b7ba47 the name variable is not used anywhere 2014-06-09 22:21:29 -05:00
Yihui Xie
973190b7a1 let download() fail in this case (ref=NULL); since ref='master' by default, if the user provides another value, he/she is expected to have read the documentation 2014-06-09 22:21:29 -05:00
Yihui Xie
f536a9d3d3 move runGist() and runGithub() after runUrl(), and merge their descriptions into the description of runUrl() 2014-06-09 22:21:29 -05:00
Yihui Xie
1348ec3bcf closes #213: merge the documentation of runUrl(), runGithub(), and runGist()
removed the port and launch.browser arguments, and used ... instead
2014-06-09 21:45:52 -05:00
Joe Cheng
9a250a4861 Merge pull request #506 from yihui/bugfix/stats
stats may not have been loaded in the event of .onLoad()
2014-06-09 09:09:11 -07:00
Yihui Xie
6450927192 stats may not have been loaded in the event of .onLoad() 2014-06-09 10:56:36 -05:00
Joe Cheng
7c9dbdc802 Merge pull request #504 from rstudio/news-update
Update NEWS
2014-06-07 12:29:04 -07:00
Joe Cheng
8d460afe2d Merge pull request #505 from yihui/doc/splitLayout
there should not be #' before @examples
2014-06-06 23:38:00 -07:00
Yihui Xie
6c44c2cf24 there should not be #' before @examples 2014-06-07 01:00:13 -05:00
Joe Cheng
cea550ebba Update NEWS 2014-06-06 22:41:04 -07:00
Joe Cheng
911a352ee6 Bump version 2014-06-06 22:20:17 -07:00
Joe Cheng
3fadfbe06e Merge pull request #503 from rstudio/bugfix/shinyapps-in-tags-2
Allow shinyApp objects to appear inside tags
2014-06-06 22:16:35 -07:00
Joe Cheng
5bf362927f Allow shinyApp objects to appear inside tags 2014-06-06 15:23:13 -07:00
Yihui Xie
4da5ca5ba9 bump version 2014-06-06 17:07:17 -05:00
Yihui Xie
d747005b30 copy the documentation of knit_print methods from htmltools, too 2014-06-06 17:07:10 -05:00
Yihui Xie
03a395107d export knit_print methods imported from htmltools 2014-06-06 16:59:12 -05:00
Yihui Xie
58ef4ccabf declare the method through @method per @hadley's suggestion at klutometis/roxygen#256 2014-06-04 16:30:12 -05:00
Yihui Xie
71ed082bb5 bump version 2014-06-04 15:41:33 -05:00
Yihui Xie
0819ac8124 no need to assign a copy of these functions in shiny, because we have imported htmltools, and we only need to export the imported functions 2014-06-04 15:38:41 -05:00
Yihui Xie
0cdd223172 cosmetic changes after #481, and roxygenize 2014-06-04 15:30:15 -05:00
Yihui Xie
571393f146 htmltools was in both Depends and Imports, against which R CMD check will warn
I guess it was in Depends because otherwise as.tags could not be treated as an S3 generic; sounds like a bug of roxygen2 or devtools
2014-06-04 15:30:15 -05:00
Yihui Xie
c85868c652 use @export instead of @S3method 2014-06-04 15:10:45 -05:00
Joe Cheng
a7a6f3b020 Merge pull request #499 from yihui/bugfix/456
Bugfix/456
2014-06-03 10:01:44 -07:00
Yihui Xie
3a0a11d55a introduce an equivalent function to achieve set.seed(NULL) in R 2.15.x 2014-06-02 16:14:22 -05:00
Yihui Xie
7eb8ddf372 fixes #456: use .Random.seed only if it exists in the global environment
e.g. the expr may not trigger the creation of .Random.seed, such as set.seed(NULL) under R 2.15.x, which will fail
2014-06-02 16:13:37 -05:00
Yihui Xie
87af63644a bump version 2014-06-02 15:38:40 -05:00
Yihui Xie
0a9dd18070 news for #433 2014-06-02 15:36:36 -05:00
Yihui Xie
f82b061ba7 news for #481 2014-06-02 15:18:54 -05:00
Yihui Xie
c17509e2a0 news for #495 2014-06-02 15:18:54 -05:00
Yihui Xie
cb383d4f62 serverInfo() returns list(shinyServer=FALSE) by default, per suggestion of @trestletech 2014-06-02 15:18:54 -05:00
Yihui Xie
451f950d0d tweak after #492: capture.output() does withVisible() and print() if necessary 2014-06-02 15:18:54 -05:00
Yihui Xie
bd0eae0961 Merge pull request #481 from saurfang/master
Add inline option for RadioButton and checkboxGroupInput
2014-06-02 15:03:40 -05:00
Joe Cheng
53a401f847 Merge pull request #495 from yihui/feature/serverInfo
add functions serverInfo() (exported) and setServerInfo() (not exported)
2014-06-02 09:16:51 -07:00
JJ Allaire
b288f5ca19 bump version 2014-06-02 08:11:02 -04:00
JJ Allaire
7a2fc19c4f bump version 2014-06-01 10:00:40 -04:00
JJ Allaire
046d712d6a Revert "Allow Shiny apps to appear inside other tags"
This reverts commit 9ab2f5338e.
2014-06-01 09:59:50 -04:00
Joe Cheng
e829aaecf1 Install htmltools in travis script 2014-05-31 10:58:54 -07:00
Joe Cheng
9ab2f5338e Allow Shiny apps to appear inside other tags 2014-05-31 09:06:54 -07:00
Joe Cheng
d7bda924be Depend on htmltools, not just Import
This seems to be necessary to get the knit_print.shiny.tags to work
with Rmarkdown without an explicit library(htmltools)
2014-05-31 08:26:09 -07:00
Joe Cheng
07eb2e51b7 Bump version to 0.9.1.9009 2014-05-31 08:08:08 -07:00
Joe Cheng
dfafa7ae40 Merge branch 'htmltools-refactor' 2014-05-31 08:06:56 -07:00
Joe Cheng
dde266768c Restore HTML generating functions
These functions were temporarily ripped out of Shiny and moved
to the htmltools package. We've discovered that it's safe to
keep including them in shiny; as long as the functions in shiny
and the functions in htmltools are identical, the user won't
receive a conflict warning.
2014-05-31 08:06:03 -07:00
Joe Cheng
01c81675f7 Make S3 method consistent with base 2014-05-31 08:06:03 -07:00
Joe Cheng
71972eb362 Update htmltools version 2014-05-31 08:06:03 -07:00
Joe Cheng
eb9f5f9025 Dependency fixes
1) Give bootstrap deps a path so they can be used in static docs
2) Resolve dependencies before rendering page (whoops)
2014-05-31 08:06:03 -07:00
Joe Cheng
eb4d4d7437 Adapt to htmltools 0.2.1 API 2014-05-31 08:06:03 -07:00
Joe Cheng
1cb5e09109 Remove obsolete entry from staticdocs index 2014-05-31 08:06:03 -07:00
Joe Cheng
cc82fff5d3 Add S3 method for turning render function into tags 2014-05-31 08:06:03 -07:00
Joe Cheng
3212e59dcc Fix broken client-side HTML dependency rendering 2014-05-31 08:06:03 -07:00
Joe Cheng
44a795bf18 Extract HTML functionality to htmltools library 2014-05-31 08:06:03 -07:00
Joe Cheng
376e6f35a2 Merge pull request #496 from eiriksm/travis-fix
Use svg version of build status. Only show master build status.
2014-05-31 08:03:16 -07:00
Eirik S. Morland
3b324e9532 Use svg version of build status. Only show master build status. 2014-05-31 12:04:00 +02:00
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
saurfang
063b58eebb Merge remote-tracking branch 'upstream/master' 2014-05-17 16:33:25 -04: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
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
Yihui Xie
01c24a578b add functions serverInfo() (exported) and setServerInfo() (not exported)
we can call shiny:::setServerInfo() in Shiny Server before launching an app, so that the app author can make use of the info to decide the behavior of the app
2014-05-16 13:22:22 -05:00
saurfang
6b82354129 Merge remote-tracking branch 'upstream/master' 2014-05-15 12:30:52 -04:00
Joe Cheng
b00fbda1ae Make sure random bytes are formatted with 2 chars 2014-05-14 17:11:18 -07:00
saurfang
bab200ff03 Merge remote-tracking branch 'upstream/master' 2014-05-14 15:44:23 -04: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
saurfang
b0f95cd9e0 Add inline options
inline options for radiobuttons and checkboxgroupinput to allow choices
rendered horizontally
2014-05-13 17:18:20 -04:00
Winston Chang
ff628ac0b2 Fixes for jshint 2014-05-12 20:46:24 -05:00
Joe Cheng
f21aefe9e9 Merge pull request #467 from yihui/cosmetic
Some cosmetic changes regarding NULL
2014-05-10 02:13:25 -07:00
Joe Cheng
8babbd69d8 Merge branch 'session-documentation'
Conflicts:
	inst/staticdocs/index.r
2014-05-09 19:41:19 -07:00
Joe Cheng
11bf02eb56 Merge pull request #478 from rstudio/remove-literate-programming
Stop using literate programming
2014-05-09 19:39:58 -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
Joe Cheng
e84a76cebd Merge pull request #457 from yihui/feature/unsatisfied-input
A first attempt of the custom error type for unsatisfied input dependencies
2014-05-08 16:12:58 -07:00
Yihui Xie
342265be94 put the custom class(es) in the first as Hadley suggested 2014-05-08 15:04:49 -07:00
Yihui Xie
62ec9291d8 Merge pull request #1 from jcheng5/feature/unsatisfied-input
Refactoring/renaming of validation
2014-05-08 14:57:54 -07:00
Joe Cheng
dee6fbcb8f Stop using literate programming
Couldn't build from source without knitr installed, and knitr
is not a required dependency
2014-05-08 14:54:11 -07:00
JJ Allaire
72fa9a2dcb bump version 2014-05-08 12:54:20 -04:00
Joe Cheng
ca27a9e31a Validation refactoring
- Move validation logic from shinywrappers.R to utils.R
- Don't coerce validation results; fail if not FALSE, NULL, or character
- Reverse order of stopWithCondition args
2014-05-07 16:20:07 -07:00
Joe Cheng
18d0f45cf9 Refactoring/renaming of validation
- validateInput renamed to validate
- validateCondition renamed to need
- Removed ability to provide "bare" conditions. It is
  still possible to fail validation silently by passing
  FALSE as the second argument to need()
- Rather than using a two-element list to convey results,
  use a single result protocol; NULL is success, FALSE is
  silent failure, string is failure with message
- Tweak "missing input" semantics, add tests
2014-05-07 16:09:06 -07:00
Joe Cheng
424fd515a4 Merge pull request #472 from rstudio/bugfix/delayed-assign-2
Remove delayedAssign which causes problems for downstream packages
2014-05-07 09:56:19 -07:00
Joe Cheng
00b40d64a1 Remove delayedAssign which causes problems for downstream packages
See comment on d7eb9b2d18
2014-05-06 20:40:57 -07:00
Joe Cheng
3a7d0a5a9f Document session object
Also allow http handlers to return standard Rook responses instead of
httpResponse objects.
2014-05-06 11:56:23 -07:00
Joe Cheng
57a02318e3 Clearer error message when shinyAppDir is given a nonexistent path 2014-05-05 15:31:21 -07:00
Joe Cheng
8f6d8cf0d6 Slider with label=NULL doesn't have tag classes attached 2014-05-05 14:00:43 -07:00
Joe Cheng
5b6605b296 Add inputPanel to staticdocs index 2014-05-05 13:59:46 -07:00
Joe Cheng
4d83596595 Merge pull request #465 from rstudio/feature/horizontal-layout
New layouts for horizontal placement
2014-05-05 13:10:26 -07:00
Joe Cheng
7e12a281f5 Remove slider from bundled jquery-ui 2014-05-05 12:12:41 -07:00
Joe Cheng
c63c10e48a Merge pull request #466 from rstudio/bugfix/space-urls
Encode pathname when necessary on browsers that supply it decoded
2014-05-05 11:40:06 -07:00
Joe Cheng
155554f0b7 Only double-encode on Qt 2014-05-05 11:36:27 -07:00
Yihui Xie
26b0836756 since NULL in tag() will be dropped, there is no need to check is.null(icon) 2014-05-03 01:11:32 -05:00
Yihui Xie
a87dc9bab2 cosmetic: both if (FALSE) expr and for-loops return NULL 2014-05-03 01:09:51 -05:00
Yihui Xie
9c1555a110 tweak an RStudio project option 2014-05-03 00:54:44 -05:00
Joe Cheng
fbda2db884 Only show special "No UI defined" message for shinyAppDir 2014-05-02 18:52:37 -07:00
Joe Cheng
2a229774ef Merge pull request #463 from jcheng5/bugfix/faster-select
Massively faster selectInput
2014-05-02 17:31:38 -07:00
Joe Cheng
137e5b13ef Update tests 2014-05-02 17:28:01 -07:00
Joe Cheng
7920d66cd0 Separate option tags with newline 2014-05-02 17:26:27 -07:00
Yihui Xie
9f2dae7f3b the logic of the last commit was not correct: we should not stop immediately on a non-condition object; instead, we still need to collect all messages on all conditions before we stop 2014-05-02 18:13:35 -05:00
Yihui Xie
ffde0ad1f5 roxygenize 2014-05-02 17:56:20 -05:00
Yihui Xie
2c2658a8ec rewrite the lapply()/vapply() with a plain dumb for-loop 2014-05-02 17:54:05 -05:00
Yihui Xie
6f2f8f6f7a add a function validateCondition() to avoid ambiguity
two advantages:

1. we no longer need to worry about input$foo being a list;
2. users have to explicitly call validateCondition() when they want error messages, so we know when to silently stop;
2014-05-02 17:33:29 -05:00
Yihui Xie
4b6dcdd1b0 use shiny-output-error as the _prefix_ for CSS classes of error messages 2014-05-02 16:56:43 -05:00
Yihui Xie
de346fd6c3 filter out some common error classes 2014-05-02 16:56:43 -05:00
Yihui Xie
bf9d7c2012 use the classes of the error condition as names of CSS classes in the output 2014-05-02 16:56:43 -05:00
Yihui Xie
143803f86d factor out stop() code to a separate function 2014-05-02 16:56:43 -05:00
Yihui Xie
311143451d condition first, message second 2014-05-02 16:56:43 -05:00
Jonathan McPherson
c9030f401d encode pathname when necessary on browsers that supply it decoded 2014-05-02 14:41:11 -07:00
Joe Cheng
8668ddce74 Tweak padding 2014-05-02 12:21:34 -07:00
Joe Cheng
7a495357f7 Update NEWS, tweak description for flowLayout 2014-05-02 12:06:15 -07:00
Joe Cheng
13864a811d Add inputPanel 2014-05-02 12:06:15 -07:00
Joe Cheng
5b65e4b250 Replace horizontalLayout with flowLayout; add splitLayout 2014-05-02 12:06:15 -07:00
Joe Cheng
dfe4a80501 Update NEWS 2014-05-02 12:06:15 -07:00
Joe Cheng
bf82b9742a Use standardized widths for selectize/jslider
The 100% width worked well inside of a sidebar, but in other situations
like full-width columns or zero-min-width tables a fixed width is better.
If there's demand we can add parameters for setting the width to custom
values including 100%.
2014-05-02 12:06:14 -07:00
Joe Cheng
829a466f72 New horizontalLayout function; put elements in a single table row 2014-05-02 12:06:14 -07:00
Yihui Xie
1206c70c42 we -> you 2014-05-02 12:45:35 -05:00
Joe Cheng
3c32c349b9 Always use Rscript from R_HOME 2014-05-02 09:12:28 -07:00
Yihui Xie
0709f08d65 a custom type of errors for unsatisfied input dependencies 2014-05-01 18:13:56 -05:00
Joe Cheng
50f78c6e40 Make tabsetPanel result visible
Without this, they don't show up in knitr documents
2014-05-01 14:31:25 -07:00
Joe Cheng
7e7afc6d38 Massively faster selectInput 2014-05-01 14:16:27 -07:00
Winston Chang
1130eadac8 Bump version 2014-04-30 14:35:08 -05:00
Winston Chang
959fc2bbb2 Merge pull request #459 from jcheng5/naked-render-in-tags
Allow naked renderXXX functions to be used inside other tags
2014-04-30 13:24:38 -05:00
Joe Cheng
f8ae505011 Change all "is()" calls to "inherits()"
According to ?inherits
2014-04-30 11:19:49 -07:00
Joe Cheng
cd183a1926 Merge branch 'feature/mask-reactive-context'
Conflicts:
	NEWS
2014-04-30 11:14:50 -07:00
Joe Cheng
bb2796fbc3 Add tests 2014-04-30 11:14:20 -07:00
Joe Cheng
5de7103890 Upgrade jqueryui to 1.10.4 and remove datepicker
The jqueryui datepicker collides with our bootstrap datepicker

Reviewed by @wch
2014-04-30 11:07:51 -07:00
Joe Cheng
a78c91ba7e Make renderPlot print result if visible
Reviewed by @wch
2014-04-30 10:10:06 -07:00
Joe Cheng
fca50da57b Fix staticdoc test 2014-04-29 12:09:37 -07:00
Joe Cheng
61f2c908b1 Add maskReactiveContext function 2014-04-29 12:01:03 -07:00
Joe Cheng
4c096ac068 Merge pull request #454 from yihui/feature/selectize-more
Make `selected` work for server-side selectize input
2014-04-28 15:41:19 -07:00
Jonathan
2c95678be1 Merge pull request #451 from jcheng5/suppress-reactlog
Don't send reactlog messages to the client unless showcase mode
2014-04-28 14:52:42 -07:00
Joe Cheng
1a643cecf3 Allow naked renderXXX functions to be used inside other tags 2014-04-28 10:13:16 -07:00
Joe Cheng
aa10b2e8c4 Merge pull request #455 from trestletech/feature/subapp
Added extra query param to identify sub apps.
2014-04-28 09:33:37 -07:00
Joe Cheng
0b9317d047 Merge pull request #453 from yihui/feature/nocache
Prevent caching conditionally
2014-04-28 09:33:03 -07:00
Yihui Xie
4d58f05f38 fix the warning about stats not being imported in namespace
see https://travis-ci.org/rstudio/shiny/builds/23791246

but do we even have to import stats? I guess no; it is part of base R
2014-04-25 18:26:07 -05:00
trestletech
6e879c8156 Added extra query param to identify sub apps. 2014-04-25 11:30:48 -05:00
Yihui Xie
b6ee67aa41 make the selected argument of updateSelectizeInput() work even in the server mode 2014-04-25 02:38:38 -05:00
Yihui Xie
07bed0c7c7 factor out a function columnToRowData() so both updateSelectInput() and selectizeJSON() can use it 2014-04-25 02:37:45 -05:00
Yihui Xie
d2bd59d149 Make meta of length 0 when we are sure there are no dependencies
knitr::asis_output() will decide whether x is cacheable by checking length(meta) == 0. Some shiny tags are cacheable, such as numericInput(), because it is pure HTML without dependencies, whereas selectizeInput() is not cacheable due to the dependency on selectize.js.
2014-04-25 01:14:14 -05:00
Yihui Xie
7bdac5a44e Make sure shiny app objects are not cacheable using asis_output(..., cacheable = FALSE)
This commit reverts d08a2507fa
2014-04-25 01:14:08 -05:00
Joe Cheng
51f5db4374 Bump version 2014-04-24 16:38:07 -07:00
Joe Cheng
e395ae6555 Merge branch 'html-deps'
Code reviewed by @jmcphers

Conflicts:
	DESCRIPTION
	R/bootstrap.R
	R/reactives.R
2014-04-24 16:37:46 -07:00
Joe Cheng
1df9c498cf Ensure dep.meta is an array 2014-04-24 16:32:18 -07:00
Joe Cheng
57b3b919a5 Don't send reactlog messages to the client unless showcase mode 2014-04-24 16:05:54 -07:00
Joe Cheng
00c6bbb297 Merge pull request #449 from rstudio/bugfix/knitr-cached-shiny
Fail when attempting to insert a Shiny app into a cached knitr chunk
2014-04-24 15:50:05 -07:00
Joe Cheng
b6536a0af3 Merge pull request #445 from wch/str
Add str.reactivevalues
2014-04-24 15:49:21 -07:00
Jonathan McPherson
d08a2507fa fail when attempting to insert a shiny app into a cached chunk 2014-04-24 15:28:07 -07:00
Joe Cheng
8bc8829577 Merge pull request #448 from trestletech/rate-element
Add element argument to getRateCallback()
2014-04-24 10:01:42 -07:00
trestletech
c843e6f68c Bump version 2014-04-24 10:58:36 -05:00
trestletech
84583e5501 Add element argument to getRateCallback() 2014-04-24 10:13:06 -05:00
Winston Chang
4548562138 Fix argument name for S3 method 2014-04-23 15:03:49 -05:00
Joe Cheng
32c170b10a Remove Rmd examples 2014-04-23 13:02:40 -07:00
Joe Cheng
97dafa0a55 Include html-preserving comments in knit_print 2014-04-23 12:46:56 -07:00
Yihui Xie
0be1ee46f2 do not ignore the names of choices data 2014-04-22 17:58:19 -05:00
Winston Chang
34c9ab7643 Add str.reactivevalues 2014-04-21 21:59:49 -05:00
Joe Cheng
59dbca250f Fix roxygen 2014-04-21 16:50:06 -07:00
Joe Cheng
4028dbfda1 Do typeset mathjax on initial load
Fixes initial load not being typeset on e.g.:
https://gist.github.com/jcheng5/a0d123d58737590ac21e
2014-04-21 13:59:17 -07:00
Joe Cheng
b9dbf610b0 Fix bootstrap themes 2014-04-21 13:16:34 -07:00
Joe Cheng
d443810520 Use html_dependency for date inputs, datatables 2014-04-21 12:35:12 -07:00
Joe Cheng
fcd941d33d Use html_dependencies for showcase mode
For some reason, showcase mode was breaking sliders without this (e.g. 06_tabsets)
2014-04-21 12:34:54 -07:00
Yihui Xie
9c063fa37c bump version 2014-04-21 01:02:46 -05:00
Yihui Xie
2720cfe346 should use MathJax.Hub.Queue() instead of .Typeset(): finally solved the mysterious race condition issue
http://docs.mathjax.org/en/latest/typeset.html
2014-04-21 01:02:05 -05:00
Joe Cheng
c39e38081e Remove unused class 2014-04-18 16:29:13 -07:00
Joe Cheng
3deb4c3f42 Fix initial dependency handling, fix knit_print 2014-04-18 16:21:13 -07:00
Joe Cheng
6945091238 First attempt at HTML dependency management 2014-04-18 15:18:51 -07:00
JJ Allaire
c758c4785a bump version 2014-04-17 07:38:06 -04:00
Jonathan McPherson
19269a20fb fix subapps on portmapped URLs
Reviewed by @jcheng5
2014-04-16 13:08:57 -07:00
Joe Cheng
45669cacb1 Merge pull request #434 from jcheng5/private-random
Refactor private random seed code
2014-04-15 15:24:41 -07:00
Joe Cheng
840bc52aae Merge pull request #433 from yihui/selectize/server
server-side selectize input
2014-04-15 15:22:11 -07:00
Joe Cheng
bbc36e349f Merge pull request #439 from jcheng5/feature/uiPattern
Add uiPattern param to shinyApp to allow one ui to serve multiple URLs
2014-04-15 15:13:08 -07:00
Joe Cheng
a4325adcdd Add uiPattern param to shinyApp to allow one ui to serve multiple URLs
Reviewed by @jmcphers
2014-04-15 12:53:18 -07:00
Yihui Xie
23f39649d0 Merge pull request #438 from jcheng5/fix-roxygen
Fix PriorityQueue error message during roxygenize
2014-04-15 00:12:43 -05:00
Yihui Xie
87b09a534e Merge pull request #435 from jcheng5/null-input-labels
Allow NULL input labels; add actionLink
2014-04-14 22:59:28 -05:00
Yihui Xie
39f0e5ae0c fix some JShint issues 2014-04-14 22:53:08 -05:00
Yihui Xie
62aaab0926 closes #422: update the selectize options via updateSelectizeInput(options) 2014-04-14 22:34:48 -05:00
Yihui Xie
cddfe999aa cosmetic changes (re-indent code) 2014-04-14 22:28:45 -05:00
Joe Cheng
fcbb658ac2 Fix PriorityQueue error message during roxygenize 2014-04-14 15:37:06 -07:00
Joe Cheng
3bbf06ba49 Don't indent HTML during knit_print 2014-04-14 15:31:45 -07:00
Yihui Xie
d9be6f1d2e implementing the server-side selectize input
also added a new method shinysession$registerDataObj(), which was designed to be a general data retrieval method: we can store arbitrary data objects as "downloads", and return arbitrary http response based on the filter function; see renderDataTable() and updateSelectizeInput() for two examples
2014-04-13 00:02:08 -05:00
Yihui Xie
5d70e68a0b the development version of knitr can be installed from rforge.net 2014-04-12 12:33:42 -05:00
Joe Cheng
529f2325b2 Fix tests 2014-04-11 15:46:32 -07:00
Joe Cheng
314d433f86 Merge pull request #436 from rstudio/feature/shiny-docs
Improved support for R Markdown Shiny documents
2014-04-11 15:43:43 -07:00
Jonathan McPherson
12ea950c5f use more idiomatic syntax for resolving rmarkdown.runtime 2014-04-11 14:41:06 -07:00
Yihui Xie
f4d12220ca Merge pull request #437 from trestletech/winslash
Make normalizePath calls Windows-compatible.
2014-04-11 15:41:54 -05:00
Jonathan McPherson
6a9cba90f4 have validateCssUnit treat unit-free character strings as pixel units 2014-04-11 12:59:15 -07:00
trestletech
6873e1f1cb Make normalizePath calls Windows-compatible. 2014-04-11 14:55:51 -05:00
Joe Cheng
fa0a91a75d Fix createUniqueId logic 2014-04-11 12:06:22 -07:00
Joe Cheng
020bb659c5 Rename tempSet to withTemporary 2014-04-11 12:00:55 -07:00
Joe Cheng
b1d6687fb0 Fix private random seed mechanism
- Introduce randomInt/p_randomInt to generate random integers in a half-open range
- Stop using runif to generate integers
- Explicitly reset the private seed during .onLoad. I was getting the same "random" numbers from Shiny every time I restarted R!
2014-04-11 11:57:39 -07:00
Joe Cheng
f67e17b287 Allow NULL input labels; add actionLink 2014-04-11 11:00:41 -07:00
Jonathan McPherson
81bd57c5ea emit appropriate warnings in R Markdown mode; collect <head> contents 2014-04-11 10:53:25 -07:00
Joe Cheng
d803bae874 Bump ver 2014-04-11 10:17:51 -07:00
Joe Cheng
14606f4087 Remove unnecessary ::: 2014-04-11 10:16:59 -07:00
Joe Cheng
599fdc7ee5 Refactor private random seed code 2014-04-10 15:03:18 -07:00
Joe Cheng
722e205db5 Isolate createUniqueId randomness from rest of R
TODO: Generalize to our own runif

Reviewed by @jmcphers
2014-04-09 17:16:36 -07:00
Joe Cheng
f67849eb47 Doc cleanup 2014-04-09 17:10:37 -07:00
Joe Cheng
662ca4e40a Fix travis? 2014-04-09 16:28:36 -07:00
Joe Cheng
aa61be74d8 Merge pull request #432 from jcheng5/multiple-apps
Support reactive documents and embedded Shiny apps in rmarkdown
2014-04-09 16:23:43 -07:00
Joe Cheng
10296fcd6b Clear handler manager anytime runApp is called 2014-04-09 16:10:43 -07:00
Joe Cheng
f8bf146b6c Render functions can be inserted directly into .Rmd
All render functions need to call markRenderFunction on their
return values for this mechanism to work.

Also:
- Remove runRmdContainer (it's moved to rmarkdown)
- Remove some bad .Rbuildignore entries
- Make height/width in shinyApp respected
2014-04-09 14:53:56 -07:00
Joe Cheng
52f104c517 Automatically remove subapps when their owning session finishes 2014-04-08 16:38:45 -07:00
Joe Cheng
6c1fc224f0 Merge pull request #1 from jcheng5/reactive-domains
Reactive domains
2014-04-08 15:44:51 -07:00
Joe Cheng
6b9ae3a8b3 Move "@include globals.R" directives to top; slight doc fixes 2014-04-08 15:39:57 -07:00
Joe Cheng
07f73030c6 More reactive domain work
- observers' autodestroy behavior is now optional
- tests
2014-04-08 14:47:32 -07:00
Joe Cheng
47130c79ee Code review feedback 2014-04-08 11:16:42 -07:00
Joe Cheng
f3a3bdfe4f Port showcase mode execution highlighting to domains 2014-04-07 21:59:16 -07:00
Joe Cheng
e5e54fe4c1 Implement reactive domains 2014-04-07 21:55:05 -07:00
Joe Cheng
29c0f9a43a Ignore additional knit_print parameters 2014-04-07 17:10:44 -07:00
Joe Cheng
0b78229c77 Travis!! *shakes fist* 2014-04-07 11:45:46 -07:00
Joe Cheng
c2a1d70070 Fix travis 2014-04-07 10:54:21 -07:00
Joe Cheng
260ecd1d9f Travis: Install latest knitr master 2014-04-07 09:24:51 -07:00
Joe Cheng
3dce2e761a Fix debugging of server files
.global$server becomes appvars$server
2014-04-04 10:30:42 -07:00
Joe Cheng
80a54200ce Comment tweaks 2014-04-03 23:45:08 -07:00
Joe Cheng
51227d438a Get rid of "incomplete final line" warnings in showcase code 2014-04-03 21:33:40 -07:00
Joe Cheng
6fb4199d37 Make the worker ID global across all sub apps 2014-04-03 21:30:56 -07:00
Joe Cheng
6ba46aff6b Fix gitignores for literate 2014-04-03 21:02:18 -07:00
Joe Cheng
5da34d0646 Fix makefile on windows 2014-04-03 20:43:55 -07:00
Joe Cheng
f215088939 Update staticdocs index, tests pass 2014-04-03 19:43:11 -07:00
Joe Cheng
df34dcdb0c Pass R CMD check 2014-04-03 19:37:45 -07:00
Joe Cheng
89f464af99 Fix Rmd build tooling 2014-04-03 15:31:49 -07:00
Joe Cheng
3f6f02f7d2 More docs 2014-04-03 14:41:59 -07:00
Joe Cheng
0d861e5389 Add documentation for handlers/middleware 2014-04-03 14:24:55 -07:00
Joe Cheng
b290c8700c Allow the use of .Rmd files for shiny impl scripts 2014-04-03 11:12:16 -07:00
Joe Cheng
81b6fbe263 Remove obsolete print.shiny.appdir 2014-04-03 01:51:30 -07:00
Joe Cheng
b3af293f66 Fix scoping bug 2014-04-03 01:49:36 -07:00
Joe Cheng
b187485172 Major refactor of runApp/addSubApp pipeline
- shinyUI and shinyServer calls are no longer required in ui.R and server.R
- shinyAppObj renamed to shinyApp
- runApp can take pathname, list(ui=..., server=...), shinyApp, and shinyAppDir
  as appDir argument
- Unify all Shiny app representations around shiny.appobj
- BREAKING CHANGE: shinyUI no longer has a "path" argument
- Instead of returning UI, ui.R can return a function that returns UI; it will
  be invoked each time the page is requested. (Note that this is NOT the same
  as saying ui.R will be run each time the page is requested.) The function can
  take either no args or a single "req" arg which is the request.
2014-04-03 01:42:01 -07:00
Joe Cheng
b449d9759c Minor doc updates 2014-04-01 23:02:22 -07:00
Joe Cheng
d9d63a3a2e Painful refactoring of server.R
This refactor changes the level of abstraction where sub-apps are implemented.
Sub-apps can basically be thought of as routing (previously called "proxying"
which was way too confusing). A call comes in to /1e8f937a8934/ and it matches
a sub-app path--we need to change the path from /1e8f937a8934/ to / for the
duration of the sub-app's handling of the request.

We used to do routing (nee proxying) at the httpuvCallback level, which added
a lot of complexity because it meant we were compositing HTTP handlers at both
the httpHandler level, and then again at the httpuvCallback level. This
refactor changes it so nobody speaks the language of httpuv except at the very
boundary of Shiny (webserver$createHttpuvApp), everything inside is either an
httpHandler or a wsHandler. So whether you're combining or routing or whatever,
everything now works the same way.
2014-04-01 22:55:56 -07:00
Joe Cheng
fd7b54fb77 Clean up exports, examples 2014-03-31 16:40:17 -07:00
Joe Cheng
887f8a606d Restore index.r entries for app obj 2014-03-31 12:11:16 -07:00
Joe Cheng
7e3717243f Merge remote-tracking branch 'origin/master' into multiple-apps
Conflicts:
	staticdocs/index.r
2014-03-31 12:08:59 -07:00
Joe Cheng
221849aa3a More-correct impl of %OR% 2014-03-31 12:07:57 -07:00
Joe Cheng
b52d40ab28 Merge pull request #430 from rstudio/v0.10
V0.10
2014-03-31 11:55:29 -07:00
Joe Cheng
3ed68ffd92 knit_print tags and tagLists 2014-03-31 11:17:24 -07:00
Joe Cheng
cc3cd2c141 Implement Shiny apps embedded as iframes in knitr 2014-03-31 10:03:22 -07:00
Winston Chang
5e30f7efc4 Merge pull request #424 from rstudio/bugfix/zero-arg-sourcerefs
Handle zero-argument outputs gracefully
2014-03-27 12:48:41 -05:00
Yihui Xie
35090251ef basically library(pkg) = if (!require(pkg)) stop() 2014-03-24 23:49:34 -05:00
Yihui Xie
338afb4893 change the deprecated @S3method to @export 2014-03-24 23:46:46 -05:00
Yihui Xie
194d8a05f8 using the latest master of klutometis/roxygen (d823c3a088b20ea5e38a60d78d42ccbe9f1e1eec)
Rd text for arguments is no longer wrapped by default
2014-03-24 23:46:46 -05:00
Winston Chang
93e276bd9b Fix capitalization of markdown package 2014-03-24 12:35:12 -05:00
Winston Chang
a69517519c Add more information to selectInput docs 2014-03-21 16:30:25 -05:00
Winston Chang
f646b1efb4 Bump version to 0.9.1.9000 for development 2014-03-21 16:16:53 -05:00
Jonathan McPherson
fc9bedacc0 guard against null source references 2014-03-20 16:00:51 -07:00
Jonathan McPherson
795eeee809 handle no-argument output calls gracefully 2014-03-20 15:46:25 -07:00
Joe Cheng
6d7818962e Redirect on no trailing slash 2014-03-20 10:14:02 -07:00
Joe Cheng
068517c933 Prevent multiple apps from stomping on server func 2014-03-20 09:09:54 -07:00
Joe Cheng
5b030200df initial prototyping of subapps 2014-03-20 08:49:18 -07:00
Joe Cheng
c732122966 Merge pull request #421 from jcheng5/bugfix/context-new
Fix 'Error in Context$new : could not find function "loadMethod"'
2014-03-19 11:40:19 -07:00
Joe Cheng
d7eb9b2d18 Fix 'Error in Context$new : could not find function "loadMethod"'
This warning was happening to dependent packages on R CMD check.

The problem is due to delayedAssign; it appears this can't be used safely, at least not to define package-level symbols that contain S4 or reference class objects.

If you call this in a package's .R file:

`delayedAssign("hello", stop("boom"))`

but don't refer to "hello" anywhere, when you run R CMD check on a dependent package you'll see the error.

If the expression needs the methods package (like Context$new()), you'll get an error unless the dependent package itself depends on methods.
2014-03-19 09:49:33 -07:00
Yihui Xie
b8b09adda1 submit shiny 0.9.0 to CRAN 2014-03-18 14:32:46 -05:00
Yihui Xie
07c8f0c4b7 use skipStartupTypeset: true for MathJax config, and call MathJax.Hub.Typeset() later
setTimeout() is necessary for uiOutput(); we need to wait for a short while before typesetting math, otherwise two bad things can happen:

1. a math expression may be rendered twice (static output)
2. it is not rendered at all (dynamic ui output)

so the compromise is to typeset math after a short while when the document is ready; 200 ms is an arbitrary choice here
2014-03-18 14:24:23 -05:00
Joe Cheng
2bd201de63 Refactor server logic into separate file 2014-03-17 16:08:59 -07:00
Joe Cheng
0b7e118a37 Merge branch 'staticdocs-0.9.0' into v0.10
Conflicts:
	staticdocs/index.r
2014-03-17 14:40:45 -07:00
Joe Cheng
a546769225 Use new staticdocs packaging standards 2014-03-17 14:37:38 -07:00
Joe Cheng
81745f932d Include withMathJax in staticdocs; improve test 2014-03-17 14:07:05 -07:00
Joe Cheng
4415bf31d2 Mention showcase mode and allow-dots in NEWS 2014-03-13 14:33:25 -07:00
Joe Cheng
5c1bcb41d8 Merge pull request #418 from jcheng5/allow-dots
Allow '.' character in input/output IDs

Fixes #358
2014-03-13 14:25:56 -07:00
Joe Cheng
b659c4c2bb Proper escaping of name, value, and type queries 2014-03-13 12:18:21 -07:00
Joe Cheng
65adc8a405 Wrap for= value in double quotes 2014-03-13 10:16:07 -07:00
Joe Cheng
4141f78717 It's important to return values in JS. heh. 2014-03-13 10:13:26 -07:00
Joe Cheng
80cb02d206 Allow '.' character in input/output IDs
I always thought dots and colons were illegal in HTML ID attributes,
but I was wrong. They are legal and because they are commonly used
in identifier names in R, Shiny users often like to use them. Worse,
Shiny gave no warnings when using dots and only a pretty advanced
subset of functionality would NOT work when using dots, causing
everyone to think they were fully supported in Shiny.

This commit ought to bring reality in line with perception. It turns
out that jQuery has an escaping scheme in its queries that allow us
to support dots after all. As long as we are always careful to
surround IDs with $escape when putting them in a query, we'll be in
good shape.

Colons will probably still cause problems at the moment because we
use colons internally to separate input type from input name. But
we've never seen users try to use colon in IDs before, so we can
wait to fix it until that becomes a problem.
2014-03-12 17:39:05 -07:00
Joe Cheng
a5a4510a1e Merge pull request #417 from yihui/bugfix/showcase-escape
fixes #416: use tags$code() to escape the code in showcase mode
2014-03-11 21:09:48 -07:00
Yihui Xie
95c30649d3 fixes #416: use tags$code() to escape the code in showcase mode
and format(..., indent = FALSE) to prevent indentation of <code>
2014-03-11 22:40:16 -05:00
Joe Cheng
8e5cbde08c Change example licenses to MIT 2014-03-11 10:49:32 -07:00
Yihui Xie
6df8632e29 Merge pull request #414 from jcheng5/bugfix/selectize-order
Fix selectize misordering on updateSelectInput
2014-03-11 11:55:26 -05:00
Jonathan
3c1218fff1 Merge pull request #415 from jcheng5/bugfix/showcase-case
Make showcase mode work with .r files
2014-03-11 09:13:04 -07:00
Joe Cheng
69c0414791 Make showcase mode work with .r files 2014-03-11 09:08:20 -07:00
Joe Cheng
d63f83fcbb Fix selectize misordering on updateSelectInput
Repro case at https://gist.github.com/jcheng5/9403917
2014-03-06 18:27:02 -08:00
Joe Cheng
75c3bf0c2f Change version to 0.9.0 2014-03-06 10:20:25 -08:00
Joe Cheng
c9a8ab2389 Merge pull request #411 from yihui/selectize/backspace
Selectize backspace issue
2014-03-05 00:29:44 -08:00
Yihui Xie
2c467c00e1 10px bottom margin for selectize input 2014-03-04 16:53:29 -08:00
Yihui Xie
c63ec5a1f2 update the test for selectInput() accordingly 2014-03-03 12:02:39 -08:00
Yihui Xie
e886558cbb roxygenize 2014-03-03 12:02:39 -08:00
Yihui Xie
8dd6dabe50 add selectize=TRUE to selectInput(), but disable deletion for single input
hopefully this is a good compromise for #404
2014-03-03 12:02:39 -08:00
Joe Cheng
c090c6adf9 Merge pull request #410 from wch/faster-tags-2
Faster tags
2014-02-28 09:43:57 -08:00
Yihui Xie
84da0befcd fixes #306: remove the possible trailing slash under Windows
the cause:

normalize('foo',  '/') => C:/foo
normalize('foo/', '/') => C:/foo/

under Windows. For unix, the trailing slash will always be removed in normalizePath()
2014-02-27 18:17:50 -06:00
Yihui Xie
267751c8b9 we have specified winslash='/' before, so it is impossible that this char is \ 2014-02-27 17:59:14 -06:00
Winston Chang
8add9f7188 Restructure logic and simplify 2014-02-27 16:02:30 -06:00
Yihui Xie
a100b0991b closes #119: we do not have to do this special treatment to the label for sliderInput, and no other inputs do as.character() for their labels
if users pass an HTML() object to the label argument, the HTML will be preserved instead of being escaped
2014-02-25 23:58:59 -06:00
Winston Chang
9ce9c5e535 More tag writing tweaks 2014-02-25 23:16:50 -06:00
Yihui Xie
b2d004ca1a closes #31: try to avoid scientific notation of numbers 2014-02-25 22:58:08 -06:00
Yihui Xie
657d50f9a3 add the missing Readme's and DESCRIPTION's for the examples 2014-02-25 21:18:16 -06:00
Joe Cheng
60e355c4f5 Faster singleton detection 2014-02-25 18:56:47 -08:00
Yihui Xie
adb444a60f the original hello-world example makes little practical sense -- it is unclear what really changed when moving the slider, especially when obs is large (we always see a "bell-shaped" histogram)
let's make the number of bins reactive instead; now it is very clear what the slider really controls

a histogram with different number of bins also serves as a good demo of the property of histograms (small bins --> small variance + large bias)
2014-02-25 20:44:19 -06:00
Yihui Xie
e7e13ff70d document the new features of DataTables in NEWS 2014-02-25 19:48:46 -06:00
Yihui Xie
a1e81db597 roxygenize 2014-02-25 19:25:48 -06:00
Yihui Xie
f23f2ff0a0 the url of selectiz.js is already in Details 2014-02-25 19:25:48 -06:00
Yihui Xie
c1b18098f1 Revert "add selectize=TRUE to selectInput(), instead of adding a separate function selectizeInput(), per suggestion of @jjallaire"
This reverts commit d3115a3bf3 and closes #404
2014-02-25 19:25:33 -06:00
Joe Cheng
31c39592e3 Faster tag rendering 2014-02-25 16:37:54 -08:00
Yihui Xie
82a1dad22a roxygenize 2014-02-25 15:45:59 -06:00
Yihui Xie
1ecec24727 add a callback argument in renderDataTable() so that users can have access to the DT object 2014-02-25 15:44:00 -06:00
Yihui Xie
607841e947 cosmetic changes 2014-02-25 15:42:36 -06:00
Yihui Xie
e234b403ae when the options is null, also show the search boxes 2014-02-25 00:41:57 -06:00
Yihui Xie
80ce7a36f8 make it possible to filter numeric columns based on the specified range of the form "lower,upper" 2014-02-24 23:59:12 -06:00
Yihui Xie
705a8666be iDisplayLength == -1 means "display all data" (#400)
we can use this feature via several ways, e.g.

- renderDataTable(..., options = list(bPaginate = FALSE))
- iDisplayLength = -1
- aLengthMenu = list(c(10, 30, -1), list(10, 30, 'All'))
2014-02-24 23:31:28 -06:00
Yihui Xie
9167905118 respect the bRegex option (as well as bRegex_j for individual columns)
however, this option is not part of the initialization options, so actually users can never use it...

#400
2014-02-24 23:29:10 -06:00
Yihui Xie
bdeb6734d8 data.options is null by default 2014-02-24 21:46:50 -06:00
Yihui Xie
9a7b042594 respect the individual bSearchable_j options in datatables 2014-02-24 21:02:25 -06:00
Winston Chang
7aea256fd8 Use YYYY/MM/DD format only as a fallback 2014-02-24 16:43:49 -06:00
Yihui Xie
857b5e6932 Merge pull request #406 from wch/date-ie8
Add function for handling date strings in IE8
2014-02-24 16:24:35 -06:00
Winston Chang
1a2d675439 Add function for handling date strings in IE8 2014-02-24 16:02:57 -06:00
Yihui Xie
0c749643de Merge pull request #405 from jcheng5/bugfix/ie8-debounce
Fix debounce error in IE8
2014-02-24 15:46:03 -06:00
Winston Chang
09bb1548f9 Fixes for jshint 2014-02-24 15:35:01 -06:00
Joe Cheng
5ffe531844 Fix debounce error in IE8
In the repo https://github.com/rstudio/shiny-testapp/ the test app
called "setinput" threw errors in IE8 due to the debouncer getting
triggered incorrectly. Essentially Debouncer.$invoke was being
called twice without an intervening normalCall or immediateCall,
which caused apply to be called with this.args === null. Upon
careful inspection/debugging it seems like this may be a bug in the
IE8 implementation of setTimeout/clearTimeout:
http://stackoverflow.com/questions/5853571/clarifying-cleartimeout-behavior-in-ie

In any case, the workaround is to check for a null timer id, which
means we tried to clear the timer at least.
2014-02-24 13:14:17 -08:00
Yihui Xie
fab24a3200 httpuv 1.2.3 is in marutter precise ppa now
hopefully this can save some time for travis ci
2014-02-23 11:09:54 -06:00
Yihui Xie
899d5e9d1d spent two hours on this weird issue of disappearing checkboxes and radio buttons, just to find two missing backslashes for <label>
http://api.jquery.com/jQuery/#creating-new-elements
2014-02-22 01:01:49 -06:00
Joe Cheng
ba510884f2 Avoid using browser URL with host of 0.0.0.0
(reviewed by @jmcphers)
2014-02-21 14:58:19 -08:00
Joe Cheng
78e8df8e17 Fix tags$head + renderUI in IE8, which was broken
Repro case: https://github.com/rstudio/shiny-testapp/tree/master/dynamic_singletons

Reviewed by @jmcphers
2014-02-21 10:15:03 -08:00
Yihui Xie
deba1609c3 implement bSearchable for individual columns (#400)
if a column is not searchable, hide its search box
2014-02-20 18:29:44 -06:00
Yihui Xie
88d2425ca3 respect the bFilter option: when it is false, do not show the search boxes 2014-02-20 18:21:36 -06:00
Yihui Xie
7117f9e058 closes #392: options in renderDataTable() can also take a function to return a list 2014-02-20 16:55:44 -06:00
Yihui Xie
c21c407416 a few cosmetic changes
= to <-, and camelCase instead of under_score
2014-02-20 16:44:09 -06:00
Yihui Xie
4b4ad42063 xtable was built from R < 3.0.0 in the official ubuntu repo hence fails to load 2014-02-20 15:09:42 -06:00
Yihui Xie
474d514c7d the httpuv binary is not in the marutter/c2d4u PPA yet
we can wait for a couple of days and revert this commit
2014-02-20 14:48:08 -06:00
Yihui Xie
6239466da8 klutometis/roxygen#191 has been fixed, so no longer need explicit @usage 2014-02-20 14:30:51 -06:00
Yihui Xie
7746d75582 bug fix: when evalOptions is of length 1, toJSON() converts it to a scalar; we need to use I() to make sure it is always a vector so that we can later $.each() 2014-02-20 14:24:51 -06:00
Yihui Xie
642c9ded08 install some R package dependencies through apt-get instead of R to save time 2014-02-20 13:42:39 -06:00
Joe Cheng
e0ae931ddd Merge pull request #402 from rstudio/bugfix/ie8-compatibility
Bugfix/ie8 compatibility
2014-02-20 10:24:10 -08:00
Jonathan McPherson
0d7727a405 fix Markdown content extraction on IE8 2014-02-20 10:22:43 -08:00
Joe Cheng
28f689498a fix browser height detection and CSS on IE8 2014-02-20 09:16:18 -08:00
Yihui Xie
eb8fec7f2d when searching is turned on, we need to make sure the filtering indices i are smaller than nrow(filtered data) instead of original data
this fixes the bug reported at https://groups.google.com/forum/#!topic/shiny-discuss/xk2Gh7KJQBM
2014-02-19 23:09:25 -06:00
Yihui Xie
2e16fa1d70 fixes #401: pass numbers as character strings in updateNumericInput() to preserver numeric precision when possible 2014-02-19 22:11:39 -06:00
Jonathan McPherson
1b856c4909 use IE8-compatible events; turn off highlighting in IE8 2014-02-19 16:45:58 -08:00
Jonathan
585ad30af1 Merge pull request #396 from jcheng5/bugfix/395-monospace-fonts-qt
Fix issue #395: Monospace fonts broken on QtWebKit
2014-02-19 16:32:38 -08:00
Joe Cheng
c0cdc4083c Merge pull request #397 from yihui/select2
Selectize.js
2014-02-19 15:45:56 -08:00
Joe Cheng
9b9db4f161 Merge pull request #398 from jcheng5/feature/suppress-tag-indent
Add indent argument to format.shiny.tag
2014-02-19 15:21:51 -08:00
Joe Cheng
84a1d8d25e Add comment about format.shiny.tag's indent param 2014-02-19 15:21:28 -08:00
Yihui Xie
d3115a3bf3 add selectize=TRUE to selectInput(), instead of adding a separate function selectizeInput(), per suggestion of @jjallaire 2014-02-19 12:04:23 -06:00
Yihui Xie
964789e9a6 add a note in the NEWS that DataTables also works for IE8 now 2014-02-19 11:58:34 -06:00
Yihui Xie
eeded51ff8 IE8 does not have map() and forEach() methods
use $.each() and $.map() instead
2014-02-19 11:58:34 -06:00
Yihui Xie
8f24f1b4d6 localize es5-shim.js 2014-02-19 11:58:34 -06:00
Yihui Xie
ad910a295a For IE8, $.text() does not work on <script>, so use $.html() instead 2014-02-19 11:58:34 -06:00
Yihui Xie
cf14c6b1e9 add es5-shim.js for IE8 2014-02-19 11:58:34 -06:00
Yihui Xie
49da114caa add a note about the I() options in selectizeInput() 2014-02-19 11:58:34 -06:00
Yihui Xie
b8376ebbf7 it is safer to evaluate the string inside ()
e.g. one cannot directly evaluate {a: 1, b: 2}, although it is legitimate JSON; eval("({a: 1, b: 2})") always works
2014-02-19 11:58:33 -06:00
Yihui Xie
29701d7295 apply checkAsIs() to selectizeInput(), and store the names in data-eval in the script
note we switched the order of {} and config.text() in $.extend(), so that users can overwrite the default options like labelField, valueField, ...
2014-02-19 11:58:33 -06:00
Yihui Xie
16279695a9 factor out the code to determine which options should be evaluated into a utility function checkAsIs(), so that it can be applied to selectizeInput() as well 2014-02-19 11:58:33 -06:00
Yihui Xie
999fc86bc6 news for selectizeInput() 2014-02-19 11:58:33 -06:00
Yihui Xie
0276d533fb the search field must be renamed accordingly 2014-02-19 11:58:33 -06:00
Yihui Xie
b77fc34a7b new function selectizeInput() to use selectize.js
closes #287
2014-02-18 23:25:25 -06:00
Joe Cheng
60c450d57e Add indent argument to format.shiny.tag 2014-02-18 12:55:11 -08:00
Joe Cheng
73411c75db Fix staticdocs test on Linux 2014-02-18 12:52:59 -08:00
Yihui Xie
8d146f7dff Revert "math expressions may come in through renderUI()/uiOutput(), in which case we have to re-typeset the math expressions"
This reverts commit 58471c6971.
2014-02-17 18:52:25 -06:00
Yihui Xie
5c34aa0bb5 remove includeMathJax() and use withMathJax() instead, per suggestion of @jcheng5 2014-02-17 18:52:25 -06:00
Joe Cheng
2b2ed8162d Staticdocs prefers lower-case .r on linux 2014-02-17 16:40:08 -08:00
Joe Cheng
9770bd8005 Tweak two Rd titles 2014-02-17 16:01:57 -08:00
Yihui Xie
4e020818ae white spaces 2014-02-17 14:43:33 -06:00
Yihui Xie
58471c6971 math expressions may come in through renderUI()/uiOutput(), in which case we have to re-typeset the math expressions 2014-02-17 14:43:33 -06:00
Joe Cheng
2a2e02bf56 Remove border radius on showcase well 2014-02-17 11:34:07 -08:00
Joe Cheng
75d8cee766 Fix issue #395: Monospace fonts broken on QtWebKit 2014-02-17 11:31:39 -08:00
Joe Cheng
1aed36bd16 Revert "Merge pull request #298 from jcheng5/remove-catools"
This reverts commit 0ad9a5f9c6, reversing
changes made to c31d91668a.
2014-02-14 13:35:41 -08:00
Joe Cheng
00ce58ed18 Merge pull request #390 from dmbates/patch-2
Update server.R
2014-02-12 13:50:49 -08:00
Douglas Bates
d11aa1a61c Update server.R
Minor typo
2014-02-12 15:25:30 -06:00
Yihui Xie
56a62d3b4d Merge pull request #356 from yihui/feature/datatables-options
To be able to evaluate options passed to DataTables
2014-02-11 23:19:13 -06:00
Yihui Xie
e6dd668657 news for #356 2014-02-11 23:18:32 -06:00
Yihui Xie
f60a64c8db instead of assuming fnFooBar should be evaluated, let's use I() explicitly 2014-02-11 23:12:19 -06:00
Yihui Xie
eff1c298c9 it is okay to include README.md in an R package on CRAN now 2014-02-11 22:59:37 -06:00
Yihui Xie
358b0a122b ignore staticdocs/ when building the source package 2014-02-11 22:59:37 -06:00
Yihui Xie
c0f7ba9d46 use Rd2roxygen to convert the two manually written Rd files to roxygen comments, so that all Rd files are automatically generated from roxygen2 now 2014-02-11 22:59:37 -06:00
Yihui Xie
c4edae8196 using roxygen2 4.0.0: the spurious changes are due to klutometis/roxygen#184 (text in Rd is no longer wrapped by default) 2014-02-11 22:59:37 -06:00
Yihui Xie
398dab808c use @include to make sure the Collate field is correctly generated 2014-02-11 22:59:37 -06:00
Yihui Xie
3530871560 strip white spaces 2014-02-11 22:59:37 -06:00
Yihui Xie
1ba26fdb98 tweak news 2014-02-11 22:31:21 -06:00
Joe Cheng
a3b85b4e3e Add index entry for absolutePanel 2014-02-11 14:19:04 -08:00
Joe Cheng
e37a5d0394 Merge remote-tracking branch 'jcheng5/feature/absolute-panel'
Conflicts:
	NEWS
	man/validateCssUnit.Rd
2014-02-11 14:17:58 -08:00
Yihui Xie
e5a8e77e2a Merge pull request #364 from yihui/feature/mathjax
closes #25: a new function includeMathJax()
2014-02-11 16:06:48 -06:00
Yihui Xie
314b59798f a news item for includeMathjax() 2014-02-11 16:06:20 -06:00
Yihui Xie
e9ae16e534 closes #25: a new function includeMathJax() 2014-02-11 15:59:23 -06:00
Joe Cheng
c971ca0ce2 Merge pull request #388 from rstudio/feature/example-display-mode
Allow display.mode to be provided for examples
2014-02-11 12:45:11 -08:00
Joe Cheng
0ad9a5f9c6 Merge pull request #298 from jcheng5/remove-catools
Remove caTools dependency
2014-02-11 12:40:09 -08:00
Joe Cheng
c31d91668a Suppress staticdocs test when run on a built package 2014-02-10 11:58:40 -08:00
Jonathan McPherson
f5c196d717 allow display.mode to be provided for examples 2014-02-10 10:40:34 -08:00
Joe Cheng
3b90eed89f Add check for staticdocs index correctness 2014-02-05 13:45:25 -08:00
Joe Cheng
9828c8b787 Minor doc tweaks
- Combine sliderInput and animationOptions topics
- Provide better staticdoc index descriptions

Sorry for the big diff, that's due to using a newer version of roxygen.
2014-02-05 13:23:57 -08:00
Winston Chang
b3e997134f Merge branch 'bugfix/381-sendOutputHiddenState' 2014-02-05 12:30:39 -06:00
Winston Chang
f560baa69b Add comments about debouncing 2014-02-05 12:30:25 -06:00
Winston Chang
8cf5f00c87 Remove console logging code 2014-02-05 12:12:38 -06:00
Winston Chang
482c3895d3 Udpate to jQuery 1.11.0
This makes the following JS console message (as noted in #271) go away:
event.returnValue is deprecated. Please use the standard event.preventDefault() instead.
2014-02-05 12:07:28 -06:00
Joe Cheng
fc0d4bde35 Staticdocs index info 2014-02-04 16:13:37 -08:00
Joe Cheng
33ed89a036 Merge pull request #363 from yihui/text-output-container
fixes #90: textOuput() can be put in any tag now
2014-02-03 16:44:08 -08:00
Joe Cheng
0a5953c104 Remove caTools dependency 2014-02-03 16:41:28 -08:00
Joe Cheng
77f6be1a8b Fix URL for slider number format details
Fixes issue #384
2014-02-03 16:37:22 -08:00
Yihui Xie
5bd3f9a571 just to avoid the spurious warning in R CMD check "doRenderTags: no visible binding for global variable 'htmlResult'" 2014-01-30 21:27:43 -06:00
Yihui Xie
ef59119663 Merge pull request #383 from jcheng5/bugfix/broken-image
Don't show broken image when plot is empty
2014-01-30 19:09:08 -08:00
Joe Cheng
45baca7018 Don't show broken image when plot is empty
Repro case:

shiny::runApp(list(
  ui=basicPage(plotOutput('foo')),
  server=function(input, output, session) {
    output$foo <- renderPlot({})
  }
))
2014-01-30 16:46:07 -08:00
Joe Cheng
9b1edb7a97 Fix issue #381: sendOutputHiddenState is called too many times 2014-01-30 10:18:43 -08:00
Yihui Xie
31c071d086 use values instead of names for radioButtons due to #340
the problem was revealed from #377
2014-01-27 22:55:37 -06:00
Joe Cheng
ecf4c5c104 Merge pull request #376 from wch/singleton
Add exports.renderHtml function
2014-01-22 14:35:23 -08:00
Winston Chang
35fbfece0d Export renderHtml function and un-export singletons object 2014-01-21 13:14:21 -06:00
Winston Chang
b7721e42d3 Fixes for jshint 2014-01-21 10:19:50 -06:00
Winston Chang
386346cee9 Add new object for handling singletons 2014-01-21 10:19:50 -06:00
Winston Chang
bbecccc45e Missing semicolon 2014-01-21 10:02:52 -06:00
Yihui Xie
1a8f84c134 and reactive({}) also works; closes #366 2014-01-17 22:41:00 -06:00
Yihui Xie
66181fdcdf reactive(NULL) works now 2014-01-17 22:40:13 -06:00
Winston Chang
b9c05e8a9c Bind both mouse and touch events for jslider
This brings in commit 468002a for jslider. It fixes the problem where
dragging the slider didn't work in the RStudio viewer pane.
2014-01-17 09:36:31 -06:00
Joe Cheng
9c22d6c12a Merge pull request #371 from trestletech/no-write-closed
Don't attempt to write if the connection is closed.
2014-01-16 16:41:23 -08:00
trestletech
f3cedbbd6f Don't attempt to write if the connection is closed. 2014-01-16 14:34:55 -06:00
Joe Cheng
3f3a660ca1 Merge pull request #369 from trestletech/input-handler-patch
Define a non-S3 input registry.
2014-01-16 11:37:28 -08:00
Joe Cheng
1c6ded8416 Merge pull request #370 from trestletech/flush-on-session-end
Flush react/output onSessionEnd
2014-01-16 11:13:16 -08:00
trestletech
aa63fdb26f Flush react/output onSessionEnd 2014-01-16 12:26:29 -06:00
trestletech
3932330ce6 Added tests, stop converting NULLs to NA. 2014-01-15 14:24:13 -06:00
trestletech
3b946b1c69 Removed deprecated function documentation. 2014-01-14 21:26:04 -06:00
trestletech
14df829f18 Update inputHandler docs, revamped tests. 2014-01-14 21:19:12 -06:00
trestletech
788d024be6 Define a non-S3 input registry.
Revises the approach taken in #233.

!! No longer casts NULLs in incoming JSON to NA.
2014-01-14 18:02:19 -06:00
Joe Cheng
c20b56e089 Merge pull request #367 from jcheng5/bugfix/dynamic-singleton
Better handling of dynamically generated singletons
2014-01-14 10:41:10 -08:00
Joe Cheng
287f4f239e Better handling of dynamically generated singletons
Ref:
https://groups.google.com/d/msg/shiny-discuss/cgSHsM1FCjY/vgU1-jmkGjkJ

The user reported that on a page with multiple uiOutputs whose corresponding
renderUI calls all returned sliderInputs (but no sliderInput was present in
ui.R), some but not all of the sliders were initialized correctly; the ones
that were not didn't receive the jquery-slider treatment and just looked like
text boxes.

This was caused by a fundamental flaw in our handling of singletons in
renderUI. The implicit assumption in the old renderUI code was that:

1) Any HTML we generate in renderUI would be rendered in the client
2) Given multiple calls to renderUI, the HTML we return will be rendered in
   the client in the order that we generated it

Both assumptions are incorrect. #1 would be incorrect in cases where an output
is rendered twice before flushOutput is called (this is possible when using an
observer to modify a reactive input, for example), and #2 is incorrect when
output is flushed with multiple values (very common, and exactly what was
happening to the user scenario linked above).

This commit fixes the problem by deferring singleton-handling for uiOutput to
the client. We don't assume that a singleton has been rendered until right
before we render it. The implementation uses a surroundSingletons function on
the server side to surround all singletons with <!--SHINY.SINGLETON[sig]-->
and <!--/SHINY.SINGLETON[sig]-->, which will then be parsed and removed in
the htmlOutputBinding in shiny.js. (And because singletons may contain <head>
elements, we also need to defer <head> hoisting to htmlOutputBinding as well.)

The context$filter mechanism previously used in tagWrite was not flexible
enough to handle this kind of singleton processing. The new rewriteTags
function does tag walking and rewriting much more robustly and flexibly than
context$filter, so I also refactored renderTags to use it instead.

One unrelated problem I noticed was that singleton only worked reliably on
tags, possibly on characters and definitely not on list() or tagList(). This
is because list flattening was happening at tag construction time, which
can cause singleton objects to be trampled. (Among other reasons, such as
context$filter not being called on list objects.) I changed tags.R to not do
any flattening or NULL dropping at tag construction time, but instead to do
it at the last minute during tagWrite.
2014-01-13 17:04:30 -08:00
Joe Cheng
dce66945ec Merge pull request #340 from yihui/bug/null-choices
fix the bug when choices=NULL in updateCheckboxGroupInput()
2014-01-11 13:43:05 -08:00
Yihui Xie
92bd1d5200 Merge pull request #360 from jcheng5/bugfix/359-factors-as-numbers
Fix issue #359: Factors in HTML attributes are being converted to their numeric, not character, equivalent
2014-01-10 19:30:33 -08:00
Yihui Xie
06d2df8211 fixes #90: textOuput() can be put in any tag now
for the example, we use <span>, which is allowed in <h3>
2014-01-10 20:54:28 -06:00
Joe Cheng
36256856b5 Fix issue #359: Factors in HTML attributes are being converted to their numeric, not character, equivalent
This bug was introduced in 3fc1410. Essentially it boils down to the difference between stringifying a factor, and stringifying a list containing a factor:

> as.character(factor('a'))
[1] "a"
> as.character(list(factor('a')))
[1] "1"
The call to split that was introduced in this commit ends up generating lists of factors, not vectors of them.

The best fix I could find was to convert all the attribute values to character before doing the split.
2014-01-10 01:48:02 -08:00
Joe Cheng
a771ae853c Remove extraneous library calls 2014-01-09 10:44:50 -08:00
Yihui Xie
ef4e10bbb1 Merge pull request #355 from jcheng5/bugfix/null-children
Ignore NULL tag elements
2014-01-08 18:51:20 -08:00
Yihui Xie
0dbe4d936e cosmetic changes, just because Github is not aware of my new commits for the PR after it was down 2014-01-08 16:23:23 -06:00
Yihui Xie
731fee11d4 a missing space 2014-01-08 15:54:05 -06:00
Yihui Xie
6759df52c3 show the log files after R CMD check failures 2014-01-08 15:18:01 -06:00
Yihui Xie
914b997076 need to run roxygen2 2014-01-08 15:18:01 -06:00
Yihui Xie
0b8a2fea72 and a missing ) 2014-01-08 14:47:40 -06:00
Yihui Xie
fb2538135c an extra ) 2014-01-08 14:46:57 -06:00
Yihui Xie
b4c547c278 move assignments out, per suggestion of @hadley 2014-01-08 14:22:38 -06:00
Yihui Xie
b243bc846b also include input ID in the warning message, per suggestion of @jcheng5 2014-01-08 14:21:41 -06:00
Joe Cheng
6b8f6162b6 Unify jqueryui copies 2014-01-08 09:41:38 -08:00
Joe Cheng
158db1532b Merge remote-tracking branch 'origin/master' into feature/absolute-panel
Conflicts:
	DESCRIPTION
2014-01-08 09:32:14 -08:00
Jonathan
6abfdb59c6 Merge pull request #352 from rstudio/feature/showcase-mode
Add Shiny Showcase mode
2014-01-08 09:11:24 -08:00
Jonathan McPherson
009d1f9ced make runApp arg take precedence over DESCRIPTION for setting showcase mode 2014-01-08 08:55:30 -08:00
Yihui Xie
555fba6598 Merge pull request #348 from rstudio/feature/navbar-input-binding
add id parameter to navbarPage (support for tab input binding)
2014-01-07 20:47:44 -08:00
Jonathan McPherson
f9017b72a7 remove extraneous parameter to startAppDir 2014-01-07 16:17:16 -08:00
Joe Cheng
99c3c2fc80 Ignore NULL tag elements
We already do the right thing for NULL tag attributes
2014-01-07 15:59:42 -08:00
Jonathan McPherson
32381679f2 update display.mode parameter and width for inputs 2014-01-07 15:50:43 -08:00
Jonathan McPherson
3d031265d1 satisfy R CMD CHECK: validate srcfile, use with(tags rather than withTags 2014-01-07 12:51:03 -08:00
Jonathan McPherson
026cda0071 change DESCRIPTION Type field from ShinyShowcase to Shiny 2014-01-07 11:16:46 -08:00
Jonathan McPherson
fb41ed5a86 make display.mode symmetric with DisplayMode in DESCRIPTION 2014-01-06 15:56:53 -08:00
Jonathan McPherson
8a08468a73 improve code density and zoomed display of inputs 2014-01-06 14:45:05 -08:00
Jonathan McPherson
f600cb4f2c allow source highlighting in files other than server.R 2014-01-06 14:33:31 -08:00
Jonathan McPherson
f754f028dc simplify showcase mode setting in DESCRIPTION 2014-01-06 13:43:02 -08:00
Jonathan McPherson
41b292b45b complete refactoring of raw text output to tags$... methods 2014-01-06 13:19:07 -08:00
Jonathan McPherson
af9be9cae8 use tags functions for writing app info block 2014-01-06 11:03:53 -08:00
Jonathan McPherson
ccfaea64c5 simplify & clean up construction of markdown content 2014-01-06 10:38:05 -08:00
Yihui Xie
a86fc96730 yes, it is weird to select by names instead of values; now the weirdness has gone 2013-12-31 17:03:43 -06:00
Yihui Xie
cf51af17fd news for #340 2013-12-31 16:50:07 -06:00
Yihui Xie
8c1b6a5cf0 update JS tests accordingly
note that getState() no longer includes state.options.selected/checked, which is actually redundant since there is state.value
2013-12-31 16:49:48 -06:00
Yihui Xie
bcecb8cd76 roxygenize 2013-12-31 16:48:17 -06:00
Yihui Xie
557790b0e5 selected refers to values instead of labels/names of choices
added validateSelected() for backward compatibility
2013-12-31 16:48:04 -06:00
Yihui Xie
8eb5a45718 per suggestion of @wch, we do not pass the selected/checked status in the message; the selected values are in message$value, and they will be set via this.setValue(el, data.value) in receiveMessage() in shiny.js
also note that updateSelectInput() is essentially the same as updateCheckboxGroupInput() now, because it does not matter if the attribute name is 'selected' or 'checked'
2013-12-31 15:06:17 -06:00
Yihui Xie
7b64cef73b fixes #176: the problem of choices=NULL also affects selectInput() 2013-12-31 15:06:17 -06:00
Yihui Xie
106203170e pass the selected value(s) to checkbox/radio group 2013-12-31 15:06:17 -06:00
Yihui Xie
174d2bfc11 only do mapply() when length(choices) > 0, otherwise options = list(), and this will lead to an empty checkbox/radio group 2013-12-31 15:06:17 -06:00
Yihui Xie
abda9c7f97 it is not possible to do names(NULL) <- value, so return early when choices is NULL
https://groups.google.com/forum/?pli=1#!topic/shiny-discuss/K7chwrMCvkU
2013-12-31 15:06:17 -06:00
Yihui Xie
8e95260df9 for select input, setValue() with a nonexistent value turns its value to null 2013-12-31 15:05:22 -06:00
Jonathan McPherson
5af1ae1920 reflow comments (and a handful of code lines) to 65 characters 2013-12-30 15:18:21 -08:00
Jonathan McPherson
f0eb9d48c9 show license beneath code 2013-12-30 14:31:45 -08:00
Jonathan McPherson
0ac284009e add Readme.md files to most examples 2013-12-30 13:05:54 -08:00
Winston Chang
fcf963639e Update to Cairo 1.5-5
This version of Cairo properly uses the res argument, so it works with
resolutions higher than 72.
2013-12-27 21:41:34 -06:00
JJ Allaire
ba8c0fb1d5 change name of app start hook to be more consistent with app stop hook 2013-12-26 19:01:45 -05:00
JJ Allaire
08fe74675b update docs on updateTabsetPanel to reflect it's applicablity to navbarPage and navlistPanel 2013-12-25 15:16:52 -05:00
JJ Allaire
f5e7fdf8aa simplify handling of nested menus in tabInputBinding 2013-12-25 15:16:13 -05:00
Joe Cheng
f6e447d049 Merge pull request #349 from rstudio/feature/run-hook
add application run and stop hooks
2013-12-24 09:54:14 -08:00
JJ Allaire
531b21c012 add application run and stop hooks 2013-12-24 10:40:10 -05:00
JJ Allaire
a057456d5a add docs for icon argument to navbarMenu 2013-12-24 09:31:24 -05:00
JJ Allaire
0f043b39f5 add id parameter to navbarPage (support for tab input binding) 2013-12-24 09:12:41 -05:00
Jonathan McPherson
dc0701e21d update DESCRIPTION files and a Readme; tweak spacing 2013-12-23 16:23:33 -08:00
Jonathan McPherson
712f18f4e8 clean up some comments and accidentally introduced whitespace changes 2013-12-23 15:04:05 -08:00
Jonathan McPherson
e0a82b4aaf Merge remote-tracking branch 'origin/master' into feature/showcase-mode 2013-12-23 14:46:48 -08:00
JJ Allaire
a7f238ae0b use correct selector for navbar menu auto-collapse 2013-12-21 17:44:07 -05:00
Yihui Xie
0d99b6de7a Merge pull request #345 from jcheng5/print-html
Nicer printing of HTML tags at console
2013-12-21 11:51:20 -08:00
Joe Cheng
6f627fca96 Minor doc tweak 2013-12-21 11:01:10 -08:00
Joe Cheng
339fbc482b Smarter cursor choosing for absolutePanel 2013-12-21 10:53:23 -08:00
Joe Cheng
72e3ee1d77 Nicer printing of HTML tags at console 2013-12-21 10:26:45 -08:00
Joe Cheng
a9750fb088 Add absolutePanel and fixedPanel (and jquery-ui)
jQueryUI is needed for draggable functionality.
2013-12-20 14:53:11 -08:00
JJ Allaire
d80e3b0824 don't auto-hide when collapased navbar submenu is clicked 2013-12-20 17:06:42 -05:00
Jonathan McPherson
46df7a9ea0 make jshint happy (avoid leaking globals) 2013-12-20 12:23:05 -08:00
Joe Cheng
b851ce49f7 Forgot to roxygenize a previous doc change 2013-12-20 11:54:22 -08:00
Winston Chang
d9afde3e15 Merge pull request #342 from trestletech/master
Unlist dates to properly handle date ranges.
2013-12-19 20:34:43 -08:00
trestletech
b38c57f308 Unlist dates to properly handle date ranges. 2013-12-19 17:58:17 -06:00
Jonathan McPherson
93e7e2e06e set height of code window based on height of surrounding window 2013-12-19 15:08:27 -08:00
Jonathan McPherson
5ac09180a5 don't emit superfluous newline at beginning of .R files 2013-12-19 14:03:07 -08:00
JJ Allaire
3819ca3a62 add descriptions for examples 2013-12-19 16:59:26 -05:00
Jonathan McPherson
00426b4c9b fix incorrect character accounting with newlines 2013-12-19 13:39:36 -08:00
Jonathan McPherson
58d8cefcc0 set sxs mode on load if browser is wide enough 2013-12-19 12:51:08 -08:00
Jonathan McPherson
c8bb122557 hide entire well when app doens't have metadata in sxs mode 2013-12-19 12:21:17 -08:00
Jonathan McPherson
bcef603a36 new layout: remove top bar, show app info by readme 2013-12-19 11:35:27 -08:00
Jonathan McPherson
639b4d392a coerce strings from DESCRIPTION to correct types 2013-12-19 10:18:57 -08:00
Jonathan McPherson
6d5f06a61d initial support for showcase mode from DESCRIPTION (not complete) 2013-12-18 17:06:31 -08:00
Jonathan McPherson
3e00e2ad58 show contents of global.R if it exists 2013-12-18 15:13:11 -08:00
Jonathan McPherson
cad2be5e53 always use tabs to show code; show readme alongside code 2013-12-18 13:41:15 -08:00
Jonathan McPherson
58fe5f263f nicer code tabs in code-alongside mode 2013-12-17 20:18:22 -08:00
Jonathan McPherson
79ec6845f8 use more bootstrap-flavored styles 2013-12-17 16:10:53 -08:00
Jonathan McPherson
0f81ba8307 use minified jquery ui 2013-12-17 15:09:26 -08:00
Jonathan McPherson
a30543b035 use rstudio fork of highlight.js 2013-12-17 14:51:44 -08:00
Jonathan McPherson
5c4473a1d9 use side-by-side code and app instead of a popup window 2013-12-17 14:07:22 -08:00
Jonathan McPherson
7ff47c8c51 use rstudio default highlight colors 2013-12-17 13:52:17 -08:00
Jonathan McPherson
2544e29be3 use show with app / show below buttons to toggle 2013-12-17 13:16:23 -08:00
Jonathan McPherson
d7bf564e8f make initial transition a little smoother 2013-12-17 11:15:11 -08:00
Jonathan McPherson
0f135f881a make code position toggleable 2013-12-17 10:56:40 -08:00
Jonathan McPherson
2f1bb5e1c0 begin restricting code height and scrolling relevant portion into view 2013-12-17 10:23:27 -08:00
Jonathan McPherson
02b5f96eee move from popup window model to side-by-side model 2013-12-17 09:00:27 -08:00
JJ Allaire
3e77871539 move shinyapps gitignore to root 2013-12-16 17:38:57 -05:00
Jonathan McPherson
676affdd03 add new header-free showcase mode (use showcase=2 on query string) 2013-12-16 14:12:13 -08:00
Jonathan McPherson
5caf41c067 Merge remote-tracking branch 'origin/master' into feature/showcase-mode 2013-12-16 13:21:59 -08:00
Jonathan McPherson
58f9e89fab restore javascript markdown formatter 2013-12-16 13:15:11 -08:00
JJ Allaire
8776f0f4a5 Merge branch 'feature/showcase-mode' of github.com:rstudio/shiny into feature/showcase-mode 2013-12-16 15:19:47 -05:00
JJ Allaire
84a8c27926 gitignore for artifacts of deploying to shinyapps 2013-12-16 15:17:13 -05:00
Jonathan McPherson
f061e3486e move showcase-specific css to its own file 2013-12-16 09:52:58 -08:00
Jonathan McPherson
da23995343 make jshint happy 2013-12-16 09:35:31 -08:00
Yihui Xie
4e0a61bd9b Merge pull request #319 from jcheng5/feature/console-reactivity
Features for easier explaining of reactivity
2013-12-16 09:28:14 -08:00
Yihui Xie
d3e2fa5df5 Merge pull request #336 from jcheng5/bugfix/335-singleton-observer
Fix #335: Singleton observer shows up in reactlog
2013-12-16 09:25:50 -08:00
Joe Cheng
00b111c974 Merge remote-tracking branch 'origin/master' into feature/console-reactivity
Conflicts:
	NAMESPACE
	NEWS
2013-12-16 09:25:45 -08:00
Jonathan McPherson
bd265c00a0 add documentation for showcase mode parameter to runApp 2013-12-16 09:25:02 -08:00
Joe Cheng
ef53a63766 Merge pull request #327 from rstudio/feature/bootstrap-layout
fluidPage and fixedPage and related bootstrap layout functions
2013-12-16 09:18:35 -08:00
JJ Allaire
688c7f1a1c improve docs on theme parameter 2013-12-16 12:01:22 -05:00
Winston Chang
2989922253 Bump Cairo to 1.5-4
This is to avoid a bug in 1.5-3, where plots wouldn't appear properly.
2013-12-16 10:36:12 -06:00
JJ Allaire
6f6619a5ab Add type parameter to tabsetPanel to enable the use of pill style tabs 2013-12-16 10:20:34 -05:00
JJ Allaire
1594c228e8 re-roxygenize 2013-12-16 10:18:08 -05:00
JJ Allaire
fb44f52aa9 add navlistPanel function 2013-12-16 10:09:38 -05:00
JJ Allaire
045ead1728 re-roxygenzie 2013-12-16 09:58:31 -05:00
JJ Allaire
4404463e53 tweak news linebreak 2013-12-16 08:27:15 -05:00
JJ Allaire
b79b61c8c8 merge from master
Merge remote-tracking branch 'origin/master' into feature/bootstrap-layout

Conflicts:
	NEWS
	R/bootstrap.R
2013-12-16 08:26:22 -05:00
Joe Cheng
467048a0fc Fix erroneous comments in 03_reactivity 2013-12-15 15:15:16 -08:00
Joe Cheng
2a1edffce3 Fix #335: Singleton observer shows up in reactlog 2013-12-15 01:00:16 -08:00
Joe Cheng
ce833c39d5 setAutoflush refactor for clarity 2013-12-15 00:21:49 -08:00
Joe Cheng
721a74eee6 Fix example 2013-12-14 23:35:32 -08:00
Joe Cheng
8f9f4f894c Incorporate code review feedback from @yihui 2013-12-14 23:35:32 -08:00
Joe Cheng
842765dad0 Features for easier explaining of reactivity
- makeReactiveBinding: Turns a "regular" variable into a reactive.
  No need to use reactiveValues() for simple reactivity.
- setAutoflush (not exported): Causes flushReact() to be called
  each time something is executed at the R console top-level.
- options(shiny.suppressMissingContextError=TRUE): Prevents the
  "Operation not allowed without an active reactive context" error
  when attempting to read a reactive value or expression from the
  console.
2013-12-14 23:35:32 -08:00
Joe Cheng
b23cc47d95 Merge pull request #334 from rstudio/feature/font-awesome
icon function for embedding icons from the font-awesome icon library
2013-12-14 21:47:52 -08:00
JJ Allaire
85baa596d0 remove widths parameter from columnLayout; add width parameter to sidebarPanel and mainPanel 2013-12-14 17:26:08 -05:00
JJ Allaire
e371fff110 update NEWS 2013-12-14 10:17:33 -05:00
JJ Allaire
dffe6b4f39 Merge remote-tracking branch 'origin/master' into feature/font-awesome 2013-12-14 09:46:59 -05:00
JJ Allaire
dbf684f385 merge origin/master 2013-12-14 09:46:37 -05:00
JJ Allaire
7b20fd91ef fix R CMD check documentation errors 2013-12-14 09:44:54 -05:00
JJ Allaire
300c25ded1 re-roxygenize 2013-12-14 09:07:37 -05:00
JJ Allaire
284e814d2a integrate icons into the rest of the ui 2013-12-14 09:02:11 -05:00
Jonathan McPherson
d5cdaddeea use markdown package instead of client-side md renderer 2013-12-13 16:15:10 -08:00
JJ Allaire
8635b395a1 Merge remote-tracking branch 'origin/master' into feature/bootstrap-layout 2013-12-13 17:55:59 -05:00
Jonathan McPherson
c2cf4e72f8 decouple showcase mode from app boot; factor out of shiny.js 2013-12-13 14:46:31 -08:00
Yihui Xie
92def0f71d Merge pull request #332 from jcheng5/bugfix/no-html-class
Fix test breakage due to HTML() missing from rendered output
2013-12-13 14:27:36 -08:00
Joe Cheng
bccae9d71c Fix test breakage due to HTML() missing from rendered output 2013-12-13 14:18:06 -08:00
JJ Allaire
90b6a2f82b add documentation on host parameter to runExample 2013-12-13 15:59:46 -05:00
JJ Allaire
0462df7de2 fix documentation error in sidebarLayout 2013-12-13 15:57:40 -05:00
JJ Allaire
d4b29ab08d initial font-awesome import 2013-12-13 15:56:18 -05:00
JJ Allaire
09f2dfe181 Merge remote-tracking branch 'origin/master' into feature/bootstrap-layout 2013-12-13 15:47:37 -05:00
Yihui Xie
317d013a0b Merge pull request #330 from yihui/travis
Travis CI
2013-12-13 12:41:04 -08:00
JJ Allaire
e26b2dcd43 refer to application layout guide 2013-12-13 14:37:49 -05:00
JJ Allaire
4676dbc740 update link to component layout guide 2013-12-13 14:33:10 -05:00
JJ Allaire
778f869ddb all functions now work with fluid or fixed layouts 2013-12-13 13:57:37 -05:00
JJ Allaire
a7e9b1f76d eliminate columnLayout (just use fluidRow) 2013-12-13 13:40:36 -05:00
JJ Allaire
096e56aaa8 eliminate horizontalPanel and pull left/right functions 2013-12-13 13:30:52 -05:00
Jonathan McPherson
d1bcc557f0 move showcase js to its own file; fix cross-document bug on firefox 2013-12-13 10:20:50 -08:00
JJ Allaire
e041fab319 Merge remote-tracking branch 'origin/master' into feature/bootstrap-layout 2013-12-13 09:38:48 -05:00
JJ Allaire
3394e36325 cross reference component and grid layout guides from help topics 2013-12-13 09:19:02 -05:00
JJ Allaire
a501458e5a Refer to Bootstrap without Twitter preface; link explicitly to v2.3.2 documentation 2013-12-13 08:24:11 -05:00
JJ Allaire
da08eef5ef add title parameter to top level page functions 2013-12-13 08:19:44 -05:00
JJ Allaire
0ea714552a update examples to use sidebarLayout rather than pageWithSidebar 2013-12-13 07:52:47 -05:00
JJ Allaire
8cba584e52 deprecation notices 2013-12-13 06:32:49 -05:00
JJ Allaire
878f07d2cf tweak docs for theme parameter 2013-12-13 06:29:29 -05:00
Yihui Xie
d297de732f ignore travis.yml in .Rbuildignore 2013-12-13 00:52:46 -06:00
Yihui Xie
c41d4d32b9 enable Travis CI
YAML copied from https://github.com/yihui/highr/blob/master/.travis.yml
2013-12-13 00:31:31 -06:00
JJ Allaire
5d34134888 update NEWS for theme parameter 2013-12-12 22:47:16 -05:00
Jonathan McPherson
f968ec4cac fix node cloning on IE browsers 2013-12-12 17:03:21 -08:00
Jonathan McPherson
fdb256a534 fix some animation and margin problems 2013-12-12 16:16:04 -08:00
Jonathan McPherson
62a2b57613 clarify regions of app UI vs. showcase UI 2013-12-12 15:45:39 -08:00
JJ Allaire
90f5ebfa58 add support for specifying an alternative bootstrap theme 2013-12-12 17:56:07 -05:00
Jonathan McPherson
66aecee519 fix highlighting for text points inside <SPAN>s 2013-12-12 14:02:53 -08:00
JJ Allaire
f0c661d6e2 enable shiny applications to opt out of bootstrap responsive css 2013-12-12 16:23:26 -05:00
JJ Allaire
a27f5b4c15 make default arguments of navbar page header and footer NULL 2013-12-12 15:58:00 -05:00
Jonathan McPherson
95b69f0003 initial support for sending source refs for reactives (not wired) 2013-12-12 12:57:04 -08:00
JJ Allaire
6925f0bf7a remove head paramter from page functions
tags$head can just be included inline as one of the elements passed to the function at the top-level
2013-12-12 15:48:35 -05:00
Jonathan McPherson
6c1a9ed83b add showdown dependency 2013-12-12 12:18:57 -08:00
Jonathan McPherson
3ebef79313 refactor showcase outputs from renderPage 2013-12-12 12:16:01 -08:00
Jonathan McPherson
57393806b0 initial support for Readme.md 2013-12-12 11:47:04 -08:00
JJ Allaire
721d8cfa49 enhance docs 2013-12-12 14:28:21 -05:00
JJ Allaire
9e5b68444f add support for menus on navbars (navbarMenu function) 2013-12-12 13:41:32 -05:00
Jonathan McPherson
9f6c619401 initial support for header generated from DESCRIPTION 2013-12-12 10:28:38 -08:00
Yihui Xie
1b47e40a3a Merge pull request #328 from rstudio/feature/rproj-changes
Rproj changes: don't roxygenize; use --as-cran for test
2013-12-12 09:44:58 -08:00
JJ Allaire
3fc14102e5 concatenate duplicate attributes in tag definitions 2013-12-12 08:41:53 -05:00
JJ Allaire
d907992c39 Automatically concatenate multiple class attributes in tag definitions 2013-12-12 08:06:20 -05:00
JJ Allaire
ae2f35c6c5 Rproj changes: don't roxygenize; use --as-cran for test 2013-12-12 06:20:35 -05:00
JJ Allaire
ddd804041d Rd changes for R CMD check 2013-12-12 06:16:51 -05:00
JJ Allaire
2478cbdb6f prevent long line lengths for links to bootstrap docs 2013-12-12 06:08:29 -05:00
JJ Allaire
80e992a9fc allow pullLeft/Right functions to take tags or lists of tags; validate that all inputs are tags 2013-12-12 06:02:31 -05:00
JJ Allaire
e4b8e08e89 use paste0 where appropriate 2013-12-12 05:51:12 -05:00
Jonathan McPherson
6c556b8a72 improve style and behavior of code popout window 2013-12-11 17:38:02 -08:00
Jonathan McPherson
9659c19b23 initial support for code pop-out 2013-12-11 17:03:27 -08:00
Jonathan McPherson
aa6e9d9bf2 find column by sibling nodes 2013-12-11 15:07:30 -08:00
Jonathan McPherson
812f0ac32c refine source ref location (columns still need work) 2013-12-11 14:06:12 -08:00
Jonathan McPherson
296b312950 scaffolding for flashing executing outputs 2013-12-11 13:22:00 -08:00
JJ Allaire
29a06406ea Merge remote-tracking branch 'origin/master' into feature/bootstrap-layout 2013-12-11 15:47:01 -05:00
JJ Allaire
261cb7d3cd fix incorrect ellipses arg in hr function 2013-12-11 15:46:38 -05:00
JJ Allaire
ba5a57ac07 fix columnLayout function 2013-12-11 13:38:50 -05:00
JJ Allaire
c0ebe9d7a1 allow row functions to take a class 2013-12-11 13:07:35 -05:00
JJ Allaire
2b83012786 update roxygen docs for navbarPage fluid argument 2013-12-11 13:04:59 -05:00
Jonathan McPherson
b9761288bd send reactive log information to the client 2013-12-11 09:48:37 -08:00
JJ Allaire
a711e83398 Merge remote-tracking branch 'origin/master' into feature/bootstrap-layout 2013-12-11 12:43:21 -05:00
Yihui Xie
2705385681 Merge pull request #320 from rstudio/feature/layout-cleanup
misc cleanup of new layout functions
2013-12-11 09:11:42 -08:00
JJ Allaire
4b2f3dd070 merge from master
Merge remote-tracking branch 'origin/master' into feature/bootstrap-layout

Conflicts:
	NAMESPACE
	NEWS
2013-12-11 06:05:22 -05:00
JJ Allaire
876acf2839 Merge remote-tracking branch 'origin/master' into feature/layout-cleanup 2013-12-11 06:00:43 -05:00
JJ Allaire
d0446f068c Merge remote-tracking branch 'origin/master' into feature/layout-cleanup 2013-12-11 05:59:02 -05:00
Yihui Xie
a9396d1e2f Merge pull request #324 from rstudio/feature/hr-tag
add hr tag to exported html builder tags
2013-12-10 21:01:28 -08:00
JJ Allaire
e87102e586 update NEWS 2013-12-10 20:41:17 -05:00
JJ Allaire
8b213f8d7c update NEWS 2013-12-10 20:40:21 -05:00
JJ Allaire
9a7dc5ba86 add hr tag to exported html builder tags 2013-12-10 20:20:16 -05:00
JJ Allaire
9acb3f83f8 add fluid parameter to navbarPage to specify fluid vs. fixed layout 2013-12-10 20:04:57 -05:00
JJ Allaire
1c676211ee more revisions to layout functions -- go back to page level constructs for fixed and fluid 2013-12-10 16:15:17 -05:00
Jonathan McPherson
89728164eb highlight code with highlight.js 2013-12-10 12:11:40 -08:00
Jonathan McPherson
d0c4093f5a use built-in parseQueryString 2013-12-10 10:46:03 -08:00
Jonathan McPherson
d7f680fb19 show ui.R and server.R files in showcase mode 2013-12-10 10:20:50 -08:00
JJ Allaire
48279e060c add validation of layout function inputs 2013-12-10 12:57:56 -05:00
Jonathan McPherson
10dd0d07dc showcase mode stub controlled by showcase=1 parameter 2013-12-10 09:50:51 -08:00
JJ Allaire
d82dc4cf77 introduce more layout functions 2013-12-10 12:02:59 -05:00
JJ Allaire
2b9553e4da refactor functions to use fixed and fluid explicitly and to introduce the notion of "layout" functions 2013-12-10 11:35:56 -05:00
Joe Cheng
ac112ea287 Race condition where clientData$singletons can be NULL
Reproduced in Shiny Server load testing.

Code reviewed by @trestletech
2013-12-09 15:51:45 -08:00
JJ Allaire
4f6b099615 move page functions to the top of the bootstrap-layout file 2013-12-09 16:43:55 -05:00
JJ Allaire
d4dcb162d0 functions for creating lower-level bootstrap layouts 2013-12-09 14:35:49 -05:00
Yihui Xie
46054f513b fixes #314: the data passed to htmlOutputBinding could be null 2013-12-08 17:55:49 -06:00
JJ Allaire
261f67df50 update NAMESPACE For removed panelWithSidebar 2013-12-08 09:14:36 -05:00
JJ Allaire
22f9b2affe rename tabsPosition to position 2013-12-08 09:10:50 -05:00
JJ Allaire
06c392c066 remove panelWithSidebar (this scenario will be handled by more composable top-level pages) 2013-12-08 09:10:28 -05:00
JJ Allaire
3d67b3bc17 Merge branch 'feature/remove-tab-condition' into feature/layout-cleanup 2013-12-08 09:06:47 -05:00
JJ Allaire
6cefab5d8a Merge branch 'feature/navbar-header-footer' into feature/layout-cleanup 2013-12-08 09:06:35 -05:00
JJ Allaire
cc261de37b remove condition attribute from tabPanel
the tab content visibility needs to be the union of data-display-if and whether the tab is active (the currenty implementation makes it always visible when data-display-if evaluates to true)
2013-12-07 17:16:02 -05:00
JJ Allaire
20712641a7 re-roxygenize for tabsetPanel position argument 2013-12-07 17:09:53 -05:00
JJ Allaire
e4d0b16fd5 add header and footer arguments to navbarPage 2013-12-07 17:09:26 -05:00
JJ Allaire
f8c25791e9 Merge pull request #318 from rstudio/feature/tabs-position
Add position parameter to tabsetPanel
2013-12-06 12:31:50 -08:00
JJ Allaire
704aa433d4 use match.arg for tabsPosition 2013-12-06 15:30:23 -05:00
Joe Cheng
3bd1003164 Merge pull request #316 from rstudio/feature/conditional-tabs
conditional expression to determine visibility of tabPanel
2013-12-06 11:21:58 -08:00
JJ Allaire
8dd55d7506 always assign data-display-if (it will be dropped if it's NULL) 2013-12-06 13:04:56 -06:00
Joe Cheng
6252d778c1 Merge pull request #317 from rstudio/feature/head-param
add optional head parameter to top-level page functions
2013-12-06 10:58:26 -08:00
Joe Cheng
942248b9e6 Merge pull request #315 from rstudio/feature/navbar-page
navbarPage and panelWithSidebar
2013-12-06 10:51:07 -08:00
Winston Chang
4793449105 Add example for actionButton 2013-12-06 12:13:31 -06:00
JJ Allaire
428e3bc0fc forward head parameter in pageWithSidebar 2013-12-06 12:09:35 -06:00
Winston Chang
bf2c80cfcf Improvements to invalidateLater docs 2013-12-06 12:09:23 -06:00
JJ Allaire
06b0685a57 change name of position parameter to tabsPosition 2013-12-06 11:33:49 -06:00
JJ Allaire
231ea25968 Add position paramter to tabsetPanel to enable positioning of tabs above, below, left, or right of tab content 2013-12-06 10:34:04 -06:00
JJ Allaire
8658eeddb2 update NEWS 2013-12-06 09:10:38 -06:00
JJ Allaire
d0769eed97 add optional head parameter to top-level page functions 2013-12-06 08:56:20 -06:00
JJ Allaire
b1fcd1f7c8 conditional expression to determine visibility of tabPanel 2013-12-06 08:12:26 -06:00
JJ Allaire
db1259b3e0 docs for collapsable and re-roxygenize 2013-12-05 10:31:03 -06:00
JJ Allaire
1a5f42b753 auto collapse navbar menu on click 2013-12-05 10:12:39 -06:00
JJ Allaire
75d061a7fa support optional collablable navbar 2013-12-05 09:17:57 -06:00
JJ Allaire
9fb4c4140b navbarPage and panelWithSidebar 2013-12-05 07:09:46 -05:00
JJ Allaire
0306877fb9 re-roxygenize for host parameter 2013-12-04 13:07:06 -05:00
Winston Chang
86e3b05a3f Merge pull request #233 from trestletech/input-registry
Create a user-extensible registry of custom Shiny Input handlers.
2013-12-03 14:19:05 -08:00
trestletech
a4e8907c95 Merged rstudio/master into branch. 2013-12-03 15:15:14 -06:00
Yihui Xie
916ad6535a fixes #299: RJSONIO is unable to convert a matrix of 0 row to [], in which case we have to use an empty list() instead
toJSON(list(x = matrix(nrow = 0, ncol = 3))) gives '{\n "x":  \n}', which is an invalid JSON expression
2013-12-03 15:03:39 -06:00
Yihui Xie
c129309937 Merge pull request #310 from yihui/master
closes #277: implement actionButton.setValue()
2013-12-03 12:55:46 -08:00
trestletech
0088e9ae77 Preface shiny input classes with shiny. Refine tests to use S3 dispatch. 2013-11-30 15:19:21 -06:00
Yihui Xie
79806b5ad5 closes #277: implement actionButton.setValue() 2013-11-26 23:51:35 -06:00
Winston Chang
7d59fbfc36 Merge pull request #302 from wch/jshint
Fixes to make JSHint happy
2013-11-22 12:11:07 -08:00
Winston Chang
e645bdf249 Add jshint options to suppress warnings 2013-11-22 13:51:52 -06:00
Winston Chang
0bedf26849 Check for own properties 2013-11-22 13:36:18 -06:00
Winston Chang
a153c5b4ce Change function defs to vars
This makes the scoping clearer.
2013-11-22 13:32:54 -06:00
Winston Chang
44f1f3e9ae Fixes for jshint 2013-11-21 17:07:47 -06:00
Winston Chang
8c82fa86c6 Update NEWS 2013-11-21 16:42:56 -06:00
Winston Chang
d4da934d6a Merge branch 'renderui-head-singleton'
Conflicts:
	NEWS
2013-11-21 16:42:42 -06:00
Winston Chang
56cc664c26 Use === 2013-11-21 16:37:16 -06:00
Joe Cheng
eaa0bdfc62 Merge pull request #278 from yihui/changeset/source
use sys.source() and keep.source=TRUE
2013-11-21 13:34:08 -08:00
Yihui Xie
c538e9c6d4 use globalenv() instead of .Globalenv; remove local() 2013-11-20 18:00:24 -06:00
Winston Chang
54b9af0299 Merge branch 'localhost-only'
Conflicts:
	NEWS
2013-11-20 13:54:47 -06:00
Winston Chang
c7d5b9211c Merge pull request #271 from wch/bootstrap
Update to Bootstrap 2.3.2 and jQuery 1.10.2
2013-11-19 20:15:20 -08:00
Winston Chang
7ca22a8718 Add updated version of jslider
This adds compatibility with jQuery 1.9+
2013-11-19 21:47:39 -06:00
trestletech
4e37b32976 Enumerate function variables, setup Roxygen to pass R CMD CHECK, added tests. 2013-11-19 20:46:51 -06:00
Winston Chang
9725b23db1 Update NEWS 2013-11-19 14:36:21 -06:00
Winston Chang
2e60f2b2ce Update to jQuery 1.10.2 2013-11-19 14:35:53 -06:00
Winston Chang
004776a522 Fix dateinput docs for pt-BR language 2013-11-19 11:19:12 -06:00
Joe Cheng
92fa1dde79 Fix #21: singleton and tags$head are not really compatible with reactiveUI
This commit fixes two problems:

- tags$head content was not properly hoisted into the head
  of the document when UI was reactively rendered
- singletons were not respected in renderUI

This makes it possible for input/output components that rely
on JavaScript libraries to simply put their script/style
dependencies in their input/output methods. This is contrary
to previous versions of Shiny where that approach would work
unless the component only appeared in renderUI/uiOutput and
not as part of the initial page render.
2013-11-09 15:11:22 -08:00
Joe Cheng
464821c4e2 Only allow access via localhost by default
This can be overridden via the "shiny.host" option or by explicitly
passing the host parameter to runApp/runExample.
2013-11-08 23:26:59 -08:00
Joe Cheng
e95483236a Merge pull request #295 from wch/quiet
Add quiet option to runApp
2013-11-08 22:03:42 -08:00
Winston Chang
a9b97a85ad Add quiet option to runApp 2013-11-07 11:26:27 -06:00
Yihui Xie
6170befc90 Merge pull request #289 from wch/methods
Move methods package to Depends
2013-11-01 12:30:39 -07:00
Winston Chang
5ecb85cb6d Bump version to .99 for development 2013-10-30 10:34:50 -05:00
Winston Chang
d2fc04f45d Merge branch 'v0.8.0-rc' 2013-10-30 10:33:27 -05:00
Joe Cheng
fb4da933d4 Update version number in NEWS 2013-10-29 12:31:58 -07:00
Yihui Xie
7483900db2 fixes #288: moving shinyCallingHandlers() to a lower-level so that the shiny.error handler can be applied to observe() and isolate() as well 2013-10-28 23:17:02 -05:00
Winston Chang
9f78dbf200 Move methods package to Depends 2013-10-26 12:05:12 -05:00
Yihui Xie
ef9b9bdd6d prepare the v0.8 release in the RC branch 2013-10-24 23:48:48 -05:00
Yihui Xie
1937aa43ba Ah, brain poisoned by R's return() syntax; check if data is empty, then check data.colnames to make sure column names are passed in 2013-10-23 21:26:47 -05:00
Yihui Xie
293ea66784 fixes #286: if the data passed to renderDataTable() does not have dim==2, return an empty object 2013-10-23 21:14:18 -05:00
Yihui Xie
e98d8f4ced Merge pull request #284 from jcheng5/shiny-server-creds
Make Shiny Server credentials available on session object
2013-10-22 11:35:20 -07:00
Joe Cheng
418d2afb2a Make Shiny Server credentials available on session object 2013-10-22 10:42:29 -07:00
Yihui Xie
a4c1a6187f roxygenize and sync doc 2013-10-22 12:33:07 -05:00
Yihui Xie
123ca34040 tweak the roxygen doc for installExprFunction() (otherwise the second paragraph is treated as \description{}) 2013-10-22 12:33:07 -05:00
Joe Cheng
6b3224116c Merge pull request #279 from yihui/datatables
DataTables
2013-10-22 09:43:13 -07:00
Yihui Xie
635e0c9788 news for shiny v0.8 2013-10-22 10:40:29 -05:00
Yihui Xie
dd33a0e0ec the error object may not be interesting at all; just call the handler without arguments
this makes it easier to set options(shiny.error = browser/recover/traceback/...), otherwise will have to do options(shiny.error = function(e) traceback()), which seems awkward
2013-10-22 10:33:01 -05:00
Yihui Xie
191deeaba6 a hack to remove the scrollbars in tab panels 2013-10-22 02:07:06 -05:00
Yihui Xie
245072f7a2 make sure colnames is an array, even when there is only one column in the data 2013-10-22 02:07:06 -05:00
Yihui Xie
6b858512b6 must empty the data table first 2013-10-22 02:07:06 -05:00
Yihui Xie
b857a01c30 save $(el) in $el 2013-10-22 02:07:06 -05:00
Yihui Xie
94c9a3e05b should not have assigned installExprFunction() to func 2013-10-22 02:07:06 -05:00
Yihui Xie
8928d2c488 use the new installExprFunction() instead of exprToFunction() 2013-10-22 02:07:06 -05:00
Yihui Xie
25bd5654aa display 25 rows by default, again per suggestion of JJ 2013-10-22 02:07:06 -05:00
Yihui Xie
83d5b96adf no CSS classes for sorted columns, per suggestion of JJ 2013-10-22 02:07:06 -05:00
Yihui Xie
7eb90c5718 roxygenize 2013-10-22 02:07:06 -05:00
Yihui Xie
4b1af75724 debouncing is done single-handedly, thanks to Joe's smart debounce() function 2013-10-22 02:07:06 -05:00
Yihui Xie
8d07ab6527 roxygenize 2013-10-22 02:07:06 -05:00
Yihui Xie
ce4ea7e7a9 allow users to pass initialization options to datatables 2013-10-22 02:07:06 -05:00
Yihui Xie
50ab5e7517 BSD license for DataTables 2013-10-22 02:07:06 -05:00
Yihui Xie
431c1d7f66 css for the processing indicator 2013-10-22 02:07:06 -05:00
Yihui Xie
a55090dc2f the searching should use intersection instead of union 2013-10-22 02:07:06 -05:00
Yihui Xie
d76cdb73b0 remove the ColumnFilter plugin; it is too heavy, and I just added the <input> by myself and implemented searching by individual columns 2013-10-22 02:07:05 -05:00
Yihui Xie
2594664330 use the nicer bootstrap style 2013-10-22 02:07:05 -05:00
Yihui Xie
f9ed075db6 write a datatable output binding; the column names and action url are passed from renderDataTable() to the output binding 2013-10-22 02:07:05 -05:00
Yihui Xie
099ced4f94 implement searching by columns 2013-10-22 02:07:05 -05:00
Yihui Xie
13d2513930 index from 0, sigh 2013-10-22 02:07:05 -05:00
Yihui Xie
2211b1c65e now we can sort multiple columns: press Shift and click the column headers 2013-10-22 02:07:05 -05:00
Yihui Xie
1fd37ca2b2 implement sorting; the very basic features are there now, but this still needs a lot of improvement in terms of details 2013-10-22 02:07:05 -05:00
Yihui Xie
7070e3748d disable default sorting 2013-10-22 02:07:05 -05:00
Yihui Xie
dfaef908c2 make sure the data has two dimensions 2013-10-22 02:07:05 -05:00
Yihui Xie
67540c763b a simple implementation of global searching 2013-10-22 02:07:05 -05:00
Yihui Xie
14269bd4d9 document renderDataTable() and dataTableOutput() 2013-10-22 02:07:05 -05:00
Yihui Xie
131663032c the ... argument is not really used 2013-10-22 02:07:05 -05:00
Yihui Xie
8ac71165e9 add dataTableOutput() and renderDataTable() for the DataTables library
not yet done, but at least paging is working now
2013-10-22 02:07:05 -05:00
Yihui Xie
346758d3f0 white spaces 2013-10-21 21:40:28 -05:00
trestletech
d3e7f130fb Parse incoming NULLs as NA. 2013-10-21 21:33:25 -05:00
Yihui Xie
aef8837b5d add .csv to fileInput() to make it consistent with the tutorial (#280) 2013-10-21 21:25:42 -05:00
Yihui Xie
dc0832adba should pass a session object to invalidateLater() 2013-10-21 21:20:41 -05:00
trestletech
c0cd269322 Revert "Customize dispatch for NULL objects."
This reverts commit f4ada70e56.
2013-10-21 20:43:02 -05:00
Joe Cheng
0ad3ff655e Merge remote-tracking branch 'origin/pr/276'
Conflicts:
	R/shiny.R
2013-10-21 10:11:05 -07:00
Yihui Xie
ef45a62cc9 Merge pull request #282 from rstudio/feature/httpuv-version
bump the required version of httpuv to v1.2
2013-10-20 09:56:17 -07:00
JJ Allaire
b79abbdea9 bump the required version of httpuv to v1.2
this is to pull the changes to httpuv that enable shiny applications to run inside the rstudio viewer pane
2013-10-20 06:34:52 -04:00
Yihui Xie
a9e4ce005d closes #238: use keep.source() for sys.source() 2013-10-18 22:38:32 -05:00
Yihui Xie
987f2b2a55 closes #236: use sys.source(envir=) instead of source(local=) 2013-10-18 22:19:25 -05:00
Yihui Xie
930e2d1d9d closes #272: the argument ws_env was not used anywhere 2013-10-18 22:01:17 -05:00
trestletech
f4ada70e56 Customize dispatch for NULL objects.
Don't provide class for input objects based on `type` field. Provide real NULLs to dispatched functions rather than empty lists.
2013-10-18 17:27:28 -05:00
trestletech
97e658709d Added S3-dispatched input parsers. 2013-10-18 17:20:24 -05:00
Joe Cheng
ec2992cd2d Merge pull request #264 from rstudio/feature/debug-hooks
Export installExprFunction and add supporting documentation
2013-10-17 09:44:03 -07:00
Joe Cheng
619208565b Merge pull request #273 from yihui/feature/callinghandlers
use withCallingHandlers() so that users can do error handling like recover()
2013-10-17 09:39:01 -07:00
Joe Cheng
dcd689d2ea Don't clear timers when runApp returns
The lifetimes of reactive expressions and observers can span multiple
runApp calls, so timers should as well.
2013-10-16 15:34:25 -07:00
Yihui Xie
e94de15f83 well, we still have to use do.call($) on .self; closes #274
Winston reported the issue at https://stat.ethz.ch/pipermail/r-devel/2013-October/067744.html

partially reverted 86d61e0b44
2013-10-16 15:42:36 -05:00
Yihui Xie
6af7de51a5 another attempt to close #249, using withCallingHandlers() instead of modifying tryCatch()
also closes #217 if everyone agrees with this approach
2013-10-16 00:57:54 -05:00
Winston Chang
559c6722ff Update NEWS 2013-10-15 15:24:02 -05:00
Winston Chang
aab2cce978 Update to Bootstrap 2.3.2 2013-10-15 12:13:34 -05:00
Joe Cheng
f4a4af0fa4 Merge pull request #265 from yihui/bug/offset
a more reliable solution for e.offsetX/Y in Firefox
2013-10-14 11:02:20 -07:00
Joe Cheng
6934838974 Merge pull request #268 from rstudio/feature/parent-notify-disconnected
send disconnected message to parent frame when running on localhost
2013-10-11 07:51:34 -07:00
JJ Allaire
1aadd25cb5 notify iframe parent of disconnect when on the same domain 2013-10-10 06:20:26 -04:00
Winston Chang
0caf944668 Fix typo 2013-10-09 16:04:14 -05:00
Jonathan McPherson
6452f62b88 use a check hint (globalVariables()) in favor of modifying code in renderImage 2013-10-08 23:24:27 -07:00
Yihui Xie
e061dfd808 roxygenize 2013-10-08 23:42:19 -05:00
Yihui Xie
4da53ef219 a better solution for e.offsetX/Y in Firefox based on http://stackoverflow.com/q/12704686/559676
which fixes the bug reported by Greg D: https://groups.google.com/forum/#!topic/shiny-discuss/E6oYvyvx0oU
2013-10-08 23:34:34 -05:00
Jonathan McPherson
347e44f04d look up function by name (for R CMD check --as-cran) 2013-10-08 15:29:35 -07:00
Joe Cheng
8997fa7242 Merge pull request #252 from jcheng5/random-ports2
Try up to 20 random ports if necessary
2013-10-08 13:58:17 -07:00
JJ Allaire
19ba6efb82 allow a custom function for the launch.browser parameter 2013-10-08 13:56:14 -07:00
Jonathan McPherson
d10cbc9984 export and add docs for installExprFunction 2013-10-08 10:36:31 -07:00
Jonathan McPherson
6c7d9ded00 simplify syntax for creating new debuggable expressions 2013-10-07 11:11:59 -07:00
Yihui Xie
6d04e89d7d Merge pull request #262 from yihui/r-check
synchronize doc
2013-10-06 15:50:01 -07:00
Yihui Xie
2beb24147d roxygenize 2013-10-06 17:47:09 -05:00
Yihui Xie
16c5f4e377 no need to expose the documentation to users; expose registerShinyDebugHook to R so that R CMD check does not complain
per discussion in #258, and closes #259
2013-10-06 17:46:45 -05:00
Joe Cheng
03a6f1753c Merge pull request #258 from rstudio/feature/debug-hooks
Add debug hook (when present) for functions generated by exprToFunction
2013-10-02 20:06:46 -07:00
Jonathan McPherson
9fb61d8446 tag Shiny server function for special debug treatment if needed 2013-10-02 12:27:44 -07:00
Jonathan McPherson
bc3322d3c9 allow debugging Shiny server function itself 2013-10-02 10:47:38 -07:00
Jonathan McPherson
06c7bf7514 invoke debug hook function if present after instantiating app functions 2013-10-02 08:53:45 -07:00
Yihui Xie
4c89a000e4 Merge pull request #257 from yihui/trycatch
rewrite some instances of do.call()
2013-10-01 23:33:44 -07:00
Yihui Xie
86d61e0b44 we do not really need do.call() in these cases 2013-10-02 01:30:31 -05:00
Joe Cheng
6407390d72 Try up to 20 random ports if necessary 2013-09-30 16:13:46 -07:00
Yihui Xie
648120cabf Merge pull request #243 from jcheng5/master
Conditional panel expressions were broken for typed inputs
2013-09-28 21:30:42 -07:00
Joe Cheng
ce5b3f290a Merge pull request #245 from rstudio/feature/random-port
choose a random port for runApp
2013-09-27 12:36:49 -07:00
JJ Allaire
5308ca1806 use .globals rather than .runContext 2013-09-27 15:36:02 -04:00
JJ Allaire
6df6d408d2 choose a random port for runApp and continue to use it for the duration of the session unless explicitly overridden 2013-09-27 07:59:44 -04:00
Joe Cheng
b60d6ccdd8 Conditional panel expressions were broken for typed inputs 2013-09-26 15:31:14 -07:00
Joe Cheng
de01c9685e Merge pull request #235 from crtahlin/patch-2
Typo fix.
2013-09-26 10:37:56 -07:00
Joe Cheng
31d2ecc9fd Merge pull request #234 from crtahlin/patch-1
Typo fix.
2013-09-26 10:37:31 -07:00
Yihui Xie
2f8502aec6 save coordmap in $el.data() so it can be dynamically retrieved
6161eaa was an inappropriate fix

(jcheng: cherry-picked from @yihui/master)
2013-09-26 10:33:37 -07:00
Joe Cheng
d377b04dad Make websocket path relative to Shiny page path
This is necessary for proxy situations that don't override the
Shiny.createSocket function (so, not including Shiny Server,
but more like Nginx, HAProxy, and a future version of RStudio
Server).

Without the path being preserved, it's impossible for these
proxies to know that the URL should be forwarded to the host
and port that belongs to Shiny.
2013-09-19 22:53:11 -07:00
crtahlin
40cc78ae1e Typo fix. 2013-09-14 23:12:45 +02:00
crtahlin
268f1e8472 Typo fix. 2013-09-14 22:54:20 +02:00
Winston Chang
004b7c782d Add mailing list information to README 2013-09-11 11:09:18 -05:00
Winston Chang
33b293f0aa Merge pull request #226 from crtahlin/patch-2
Fixed typo.
2013-09-05 17:53:51 -07:00
crtahlin
ad584a98ad Fixed typo. 2013-09-05 17:25:27 +02:00
Jeff Allen
e2509eddb2 Merge pull request #225 from crtahlin/patch-1
Fixed typo.
2013-09-05 08:09:03 -07:00
crtahlin
b9f72d0e78 Fixed typo. 2013-09-05 16:35:04 +02:00
Joe Cheng
c839bb2db3 Merge pull request #224 from yihui/patch-1
websockets has been changed to httpuv
2013-09-04 10:38:04 -07:00
Yihui Xie
30161369a8 websockets has been changed to httpuv 2013-09-03 17:24:05 -05:00
Winston Chang
c65aa9732e Bump version to 0.7.0.99 for development 2013-08-29 11:44:30 -05:00
Joe Cheng
bc72b8fd1c Merge pull request #214 from hadley/doc-tweaks
Doc tweaks
2013-08-27 16:50:00 -07:00
Winston Chang
f089531bd1 Put man-roxygen in .Rbuildignore 2013-08-27 10:08:03 -05:00
Winston Chang
8d8ea53804 Fixes to imports for R-devel 2013-08-26 14:19:50 -05:00
Winston Chang
89e405e927 Bump version to 0.7.0 2013-08-26 12:03:02 -05:00
Joe Cheng
ca984a6630 Implement shiny.sharedSecret option 2013-08-25 22:20:38 -07:00
Joe Cheng
fa39a55eca Wow, IE10 is *really* picky about websocket URLs 2013-08-23 15:42:19 -07:00
Joe Cheng
c3a1ba2f2d Make websocket URL work with IE10
See https://github.com/einaros/ws/issues/131#issuecomment-15715373
2013-08-23 15:38:12 -07:00
Joe Cheng
86e291f250 Add docs for showReactLog. Un-export writeReactLog. 2013-08-23 13:11:04 -07:00
Jeff Allen
dd1d4439a9 Merge pull request #218 from wch/fix-log
Cleanups to reactive logging code for R CMD check
2013-08-23 12:16:23 -07:00
Joe Cheng
cbfde18f8c More updates to NEWS 2013-08-23 12:03:11 -07:00
Winston Chang
e2c2e23d2a Cleanups to reactive logging code for R CMD check
* Fix 'env' partial argument match for get().
* Fix unbound variable access of .shiny__stdout.
* Restructure if statement so test is only done once.
2013-08-23 12:16:18 -05:00
Winston Chang
40cc5d5242 Doc fixes for R CMD check 2013-08-23 12:07:34 -05:00
Winston Chang
9765194ace Bump httpuv version dependency to 1.1.0 2013-08-23 10:16:47 -05:00
Winston Chang
628465e6b5 Update NEWS 2013-08-23 10:16:12 -05:00
Winston Chang
58706df120 Update sliderInput docs 2013-08-23 10:16:05 -05:00
Joe Cheng
b19225c747 Don't send websocket subprotocol
Some time recently, Google Chrome started actually caring what the
client sends for this and what the server replies with. httpuv
doesn't currently have any logic for subprotocol selection, so
it always replies with no Sec-WebSocket-Protocol header, which
now Google Chrome reacts to by closing the websocket connection.

This problem goes away if we just don't send a subprotocol at all.
2013-08-23 02:15:54 -07:00
Joe Cheng
c304889e61 Merge pull request #208 from trestletech/master
Add reactive timing logging, if the necessary variables are available.
2013-08-22 13:55:11 -07:00
trestletech
05a9204678 Added timestamp to reactive log. 2013-08-22 11:20:26 -05:00
hadley
ed8537bb0b Redue duplication in docs betwee date/dateRange 2013-08-14 13:37:14 -05:00
hadley
6a9ae10fcf Add cross-references between input types 2013-08-14 13:33:44 -05:00
hadley
05358904bf Re-document 2013-08-14 13:31:16 -05:00
hadley wickham
1a6901c3e3 Document range slider 2013-08-14 13:25:42 -05:00
Winston Chang
7aaba8244b Add is.reactivevalues function 2013-08-05 14:02:50 -05:00
Winston Chang
8c45dcde88 Merge pull request #205 from hadley/master
Class output of reactive.
2013-08-05 12:02:14 -07:00
Winston Chang
6c155b04b2 Merge pull request #197 from wch/fix-style
Add compatibility wrapper for getComputedStyle in IE8
2013-07-27 17:43:01 -07:00
Winston Chang
cd8ad9a2ec Add compatibility wrapper for getComputedStyle in IE8 2013-07-27 19:41:56 -05:00
hadley
a5db7d0246 Class output of reactive.
Also add print method and test
2013-07-27 11:06:35 -05:00
trestletech
b84b467b96 Added logging of start/stop flushing of reactives using a param provided via HTTP headers. 2013-07-24 17:40:24 -04:00
trestletech
0812aaac88 Merge remote-tracking branch 'rstudio/master' 2013-07-24 08:59:34 -04:00
Joe Cheng
194d2f911e Changes to public-facing session object
- Change from list to environment. This enables the next feature:
- Make $request a promise. websocket$request breaks on some (earlier?) versions
  of httpuv. I'm not sure why this is but in the few hours since I submitted
  the websocket$request change we've had a number of complaints. This way the
  error only occurs if the app actually asks for session$request.
- Make the private session object accessible via `.impl`. Obviously any data or
  methods on the private session object are unsupported but they are there if
  you are desperate and don't mind possible future breakage.
2013-07-23 15:39:27 -07:00
Joe Cheng
e360b36b8a Make WS request available on session object 2013-07-22 15:15:27 -07:00
trestletech
b6f66dd287 Moved print out so we can put it where it belongs. 2013-07-16 08:01:22 -07:00
trestletech
0a4bb48cd3 Added output of process ID on app start. 2013-07-15 14:26:25 -07:00
Joe Cheng
15d62d4a91 Add instructions for installing from GitHub 2013-07-12 01:32:49 +02:00
Joe Cheng
5b13c44ef9 Fix isolate return value bug (issue #200) 2013-07-12 01:30:07 +02:00
Joe Cheng
0a4250f3b4 Merge pull request #193 from jcheng5/reactlog
React log
2013-07-09 00:58:53 -07:00
Joe Cheng
f79223ed58 Merge remote-tracking branch 'origin/master' into reactlog 2013-07-07 01:20:59 -07:00
Joe Cheng
2d28218a2a Allow Cmd+F3 to launch reactlog 2013-07-07 01:20:40 -07:00
Joe Cheng
35974f2ee1 Firefox scrubbing fix 2013-07-06 23:13:25 -07:00
Joe Cheng
1f73323fb9 reactlog: Support arbitrary temporal movement 2013-07-06 23:06:38 -07:00
Joe Cheng
a3d0736eec Use more obscure keyboard shortcut for reactlog 2013-07-06 18:27:10 -07:00
Joe Cheng
4bdd486c00 reactlog: Firefox compatibility; visual tweaks 2013-07-06 18:22:40 -07:00
Joe Cheng
c3895c9bd7 Configurable hover delay type (debounce/throttle) 2013-07-05 17:29:57 -07:00
Joe Cheng
e9ddd89b32 Simpler math 2013-07-05 15:08:42 -07:00
Joe Cheng
88a8f2d609 Fix locator Retina compatibility. Again.
Was working locally on Macs but not on spark.rstudio.com accessed via rMBP.
2013-07-05 13:52:56 -07:00
Joe Cheng
a5dc5c89e8 Firefox locator compat 2013-07-05 12:30:14 -07:00
Joe Cheng
3a15a35137 Merge pull request #192 from jcheng5/flush-callbacks
Add session$onFlush and session$onFlushed
2013-07-05 02:10:02 -07:00
Joe Cheng
b644640804 Add session$onFlush and session$onFlushed 2013-07-05 02:07:51 -07:00
Joe Cheng
aaa4f66671 Merge pull request #183 from jcheng5/plot-mouse-events
Click and hover on static plots. Also, fix retina compatibility and make hover delay configurable
2013-07-04 23:43:54 -07:00
Joe Cheng
07e021199e Use crosshair cursor when plot supports hover/click 2013-07-04 23:42:44 -07:00
Joe Cheng
6b2ca7dc80 Merge pull request #182 from jcheng5/reactive-poll
Implement reactivePoll and reactiveFileReader
2013-07-04 23:31:16 -07:00
Joe Cheng
091d62803e Merge pull request #191 from trestletech/master
Restrict the number of observations to a valid, positive number.
2013-07-04 12:15:57 -07:00
trestletech
547999bae0 Restrict the number of observations to a valid, positive number. 2013-07-03 23:06:42 -05:00
Joe Cheng
99013f7998 Launch reactlog from Shiny app with F3 2013-07-03 12:17:36 -07:00
Joe Cheng
fc396800db reactlog: Automatically run first step 2013-07-03 08:56:28 -07:00
Joe Cheng
6d03ae57ac reactlog: Show value changes 2013-07-03 00:05:28 -07:00
Joe Cheng
4a0aa57355 reactlog node shapes, visible labels 2013-07-02 17:48:09 -07:00
Joe Cheng
7db737494c Reverse reactlog arrow orientation 2013-07-02 13:21:39 -07:00
Joe Cheng
b285501c44 reactlog code cleanup 2013-07-02 08:38:24 -07:00
Joe Cheng
2f9b29994f Add showReactLog function 2013-07-02 03:17:30 -07:00
Joe Cheng
917434cb6b Introduce shiny.reactlog function 2013-07-02 03:03:29 -07:00
Joe Cheng
28a52bb658 More visual improvements to reactlog 2013-07-02 02:59:37 -07:00
Joe Cheng
82bc19374c Improve appearance of reactlog 2013-07-02 02:12:07 -07:00
Joe Cheng
0b23f30bb7 Work in progress 2013-07-02 01:29:33 -07:00
Joe Cheng
64a62d7aed Add doc for workerId param 2013-06-28 13:55:45 -07:00
Joe Cheng
de31cf8e7d Merge pull request #175 from trestletech/master
Add workerID to upload, download, and file URLs.
2013-06-28 13:52:38 -07:00
Winston Chang
3484f9afb3 Merge pull request #179 from wch/faster-tags
Faster tags
2013-06-25 09:57:34 -07:00
Winston Chang
81df0ff390 Fix typo 2013-06-25 11:40:54 -05:00
Winston Chang
d403ec7399 Make hover delay configurable 2013-06-24 16:39:04 -05:00
Winston Chang
6ac77835df Fix Retina compatibility (revert b113119) 2013-06-24 16:31:43 -05:00
Joe Cheng
b113119a9a Retina display compatibility 2013-06-21 21:38:23 -07:00
Joe Cheng
b713057614 Implement click and hover events on static plots
plotOutput now takes clickId and hoverId params that tell Shiny
where to send click and hover events for that plot. The server.R
file can listen on input$<clickId> and/or input$<hoverId>. In
both cases, the resulting value will have numeric x and y elements
that indicate the mouse position in user coordinates. In the case
of hover events, it's also possible to have a NULL value which
means the mouse is not currently hovering over the plot.
2013-06-21 16:58:43 -07:00
Winston Chang
4268570166 Add tests for escaping in tags 2013-06-20 14:13:11 -05:00
Winston Chang
ead508c0d0 Preserve attributes in child tags 2013-06-20 12:16:51 -05:00
Joe Cheng
f8e1be8565 Update shiny-package 2013-06-19 13:09:48 -07:00
Winston Chang
360f1af32f Export tagSetChildren and tagAppendChildren 2013-06-19 15:01:45 -05:00
Joe Cheng
49a08d14c3 Code review feedback, part 1 2013-06-19 11:39:09 -07:00
Joe Cheng
d897df6a30 Implement reactivePoll and reactiveFileReader 2013-06-19 09:16:04 -07:00
Winston Chang
ba4f3a1553 Speed up input update functions 2013-06-19 00:34:57 -05:00
Winston Chang
6ba9534da4 In tag functions, drop NULL attributes 2013-06-19 00:25:46 -05:00
Winston Chang
c16ef96754 Don't use named list items for selectInput and radioButtons
The names aren't used anyway, and this matches previous behavior (Shiny 0.6.0)
2013-06-18 23:53:30 -05:00
Winston Chang
e728491aa2 Refactor checkboxGroupInput 2013-06-18 23:52:41 -05:00
Winston Chang
ce356fa266 Fix handling of empty tags 2013-06-18 23:52:13 -05:00
Winston Chang
5e46323ca3 Refactor tag()
This is much faster when there are large lists of children (and the code is
much simpler!)
2013-06-18 23:33:28 -05:00
Winston Chang
0a7d047246 Add tests for creating nested tags 2013-06-18 22:40:17 -05:00
Winston Chang
3fa534a3eb Add tests for adding children 2013-06-18 22:39:34 -05:00
Joe Cheng
25990f59d8 Add observeEvent and eventFilter functions for handling events 2013-06-18 18:42:00 -07:00
Winston Chang
c6405f70d3 Add tagSetChildren() and tagAppendChildren() 2013-06-18 20:12:04 -05:00
Joe Cheng
acae6c2c49 Expose session$input and session$output
This makes it possible for packaged Shiny components to only ask
for the session variable to get access to all inputs and outputs
(along with the other good stuff on session).
2013-06-18 17:08:48 -07:00
Joe Cheng
141fdc2197 Do away with dependsOnFile error
This error is causing more problems than it solves.
2013-06-18 17:07:42 -07:00
Joe Cheng
a7ed8a006f includeText should be HTML escaped 2013-06-18 17:07:08 -07:00
Joe Cheng
b1a0ebd531 Add includeCSS and includeScript functions 2013-06-18 17:06:34 -07:00
Winston Chang
e8021acccd Speed up radioButtons when there are many choices 2013-06-17 23:49:50 -05:00
Winston Chang
39b0da2a3f Speed up selectInput when there are many choices 2013-06-17 23:44:13 -05:00
Joe Cheng
fd3d18f6c5 Add stopApp function, for returning a value from runApp 2013-06-14 22:27:58 -07:00
trestletech
ecc27d1674 Incorporated a worker ID specification.
Accept this as a parameter from the runApp() function and pass it through into the shinysession object so that it can be used in file uploads, downloads, and HTTP image fallbacks on non-websocket browsers.
2013-06-13 21:34:10 -07:00
Joe Cheng
7d0514ab36 Merge pull request #172 from wch/cairo-option
Add option for not using Cairo
2013-06-12 10:10:14 -07:00
Winston Chang
44c3024c00 Add option for not using Cairo 2013-06-12 10:56:21 -05:00
Winston Chang
253c92bab7 Bump version to 0.6.0.99 for development 2013-06-12 10:53:51 -05:00
Joe Cheng
c10850118d Merge pull request #170 from hadley/master
Fix typo
2013-06-11 13:26:14 -07:00
Joe Cheng
4f017e9173 Remove annoying title="foo" tooltip on all tabset tabs 2013-06-11 09:19:49 -07:00
Joe Cheng
5ed46c82cb Document observer methods 2013-06-11 09:18:57 -07:00
hadley wickham
64391e906d Update reactives.R
Add newline (guessing that's how it's supposed to be)
2013-06-11 10:37:02 -05:00
Joe Cheng
47b4ee07ab Merge pull request #165 from trestletech/master
Export validateCSSUnit function
2013-06-10 11:32:01 -07:00
trestletech
3000cbf763 Reorder namespace using latest roxygen2 code. 2013-06-07 16:33:19 -05:00
trestletech
76b3d314a8 Exported validateCSSUnit function. 2013-06-05 15:15:54 -05:00
1073 changed files with 160509 additions and 34731 deletions

View File

@@ -1,11 +1,37 @@
^\.Rproj\.user$
^\.git$
^examples$
^README\.md$
^shiny\.Rproj$
^shiny\.sh$
^shiny\.cmd$
^run\.R$
^\.gitignore$
^smoketests$
^res$
^man-roxygen$
^\.travis\.yml$
^staticdocs$
^tools$
^srcts$
^CONTRIBUTING.md$
^cran-comments.md$
^.*\.o$
^appveyor\.yml$
^revdep$
^TODO-promises.md$
^manualtests$
^\.github$
^\.vscode$
^\.madgerc$
^package\.json$
^tsconfig\.json$
^package-lock\.json$
^node_modules$
^coverage$
^.ignore$
^eslint\.config\.mjs$
^_dev$
^.claude$
^README-npm\.md$
^CRAN-SUBMISSION$
^LICENSE\.md$

2
.Rinstignore Normal file
View File

@@ -0,0 +1,2 @@
^tools$
^Rmd$

6
.gitattributes vendored Normal file
View File

@@ -0,0 +1,6 @@
/NEWS merge=union
/inst/www/shared/shiny.js -merge -diff
/inst/www/shared/shiny-*.js -merge -diff
/inst/www/shared/shiny*.css -merge -diff
*.min.js -merge -diff
*.js.map -merge -diff

40
.github/CONTRIBUTING.md vendored Normal file
View File

@@ -0,0 +1,40 @@
We welcome contributions to the **shiny** package. To submit a contribution:
1. [Fork](https://github.com/rstudio/shiny/fork) the repository and make your changes.
2. Submit a [pull request](https://help.github.com/articles/using-pull-requests).
3. Ensure that you have signed the contributor license agreement. It will appear as a "Check"
on your PR and a comment from "CLAassistant" will also appear explaining whether you have
yet to sign. After you sign, you can click the "Recheck" link in that comment and the check
will flip to reflect that you've signed.
We generally do not merge pull requests that update included web libraries (such as Bootstrap or jQuery) because it is difficult for us to verify that the update is done correctly; we prefer to update these libraries ourselves.
## How to make changes
Before you submit a pull request, please do the following:
* Add an entry to NEWS.md concisely describing what you changed.
* If appropriate, add unit tests in the tests/ directory.
* If you made any changes to the JavaScript files in the srcjs/ directory, make sure you build the output JavaScript files. See tools/README.md file for information on using the build system.
* Run Build->Check Package in the RStudio IDE, or `devtools::check()`, to make sure your change did not add any messages, warnings, or errors.
Doing these things will make it easier for the Shiny development team to evaluate your pull request. Even so, we may still decide to modify your code or even not merge it at all. Factors that may prevent us from merging the pull request include:
* breaking backward compatibility
* adding a feature that we do not consider relevant for Shiny
* is hard to understand
* is hard to maintain in the future
* is computationally expensive
* is not intuitive for people to use
We will try to be responsive and provide feedback in case we decide not to merge your pull request.
## Filing issues
If you find a bug in Shiny, you can also [file an issue](https://github.com/rstudio/shiny/issues/new). Please provide as much relevant information as you can, and include a minimal reproducible example if possible.

40
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@@ -0,0 +1,40 @@
---
name : Bug report
about : Report a bug in Shiny.
---
<!--
This issue tracker is for bugs and feature requests in the Shiny package. If you're having trouble with Shiny Server or a related package, please file an issue in the appropriate repository.
If you're having trouble with shinyapps.io, and you have a paid account (Starter, Basic, Standard, or Pro), please file a support ticket via https://support.rstudio.com. If you have a Free account, please post to the RStudio Community with the shinyappsio tag: https://community.rstudio.com/tags/shinyappsio.
Finally, if you are an RStudio customer and are having trouble with one of our Pro products, get in touch with our support team at support@rstudio.com.
Before you file an issue, please upgrade to the latest version of Shiny from CRAN and confirm that the problem persists.
# First, restart R.
# To install latest shiny from CRAN:
install.packages("shiny")
See our guide to writing good bug reports for further guidance: https://github.com/rstudio/shiny/wiki/Writing-Good-Bug-Reports. The better your report is, the likelier we are to be able to reproduce and ultimately solve it.
-->
### System details
Browser Version: <!-- If applicable -->
Output of `sessionInfo()`:
```
# sessionInfo() output goes here
```
### Example application *or* steps to reproduce the problem
<!-- If you're able to create one, a reproducible example is extremely helpful to us. For instructions on how to create one, please see: https://github.com/rstudio/shiny/wiki/Creating-a-Reproducible-Example -->
```R
# Minimal, self-contained example app code goes here
```
### Describe the problem in detail

View File

@@ -0,0 +1,17 @@
---
name : Feature request
about : Request a new feature.
---
<!--
Thanks for taking the time to file a feature request! Please take the time to search for an existing feature request, to avoid creating duplicate requests. If you find an existing feature request, please give it a thumbs-up reaction, as we'll use these reactions to help prioritize the implementation of these features in the future.
If the feature has not yet been filed, then please describe the feature you'd like to see become a part of Shiny. See:
https://github.com/rstudio/shiny/wiki/Writing-Good-Feature-Requests
for a guide on how to write good feature requests.
-->

7
.github/ISSUE_TEMPLATE/question.md vendored Normal file
View File

@@ -0,0 +1,7 @@
---
name : Ask a Question
about : The issue tracker is not for questions -- please ask questions at https://forum.posit.co/tags/shiny.
---
The issue tracker is not for questions. If you have a question, please feel free to ask it on our community site, at https://forum.posit.co/c/shiny.

13
.github/shiny-workflows/routine.sh vendored Normal file
View File

@@ -0,0 +1,13 @@
#!/bin/bash -e
. ./tools/documentation/checkDocsCurrent.sh
echo "Updating package.json version to match DESCRIPTION Version"
Rscript ./tools/updatePackageJsonVersion.R
if [ -n "$(git status --porcelain package.json)" ]
then
echo "package.json has changed after running ./tools/updatePackageJsonVersion.R. Re-running 'npm run build'"
npm run build
git add ./inst package.json && git commit -m 'Sync package version (GitHub Actions)' || echo "No package version to commit"
else
echo "No package version difference detected; package.json is current."
fi

25
.github/workflows/R-CMD-check.yaml vendored Normal file
View File

@@ -0,0 +1,25 @@
# Workflow derived from https://github.com/rstudio/shiny-workflows
#
# NOTE: This Shiny team GHA workflow is overkill for most R packages.
# For most R packages it is better to use https://github.com/r-lib/actions
on:
push:
branches: [main, rc-**]
pull_request:
branches:
schedule:
- cron: "0 5 * * 1" # every monday
name: Package checks
jobs:
website:
uses: rstudio/shiny-workflows/.github/workflows/website.yaml@v1
routine:
uses: rstudio/shiny-workflows/.github/workflows/routine.yaml@v1
R-CMD-check:
uses: rstudio/shiny-workflows/.github/workflows/R-CMD-check.yaml@v1
with:
# On R 4.2, Cairo has difficulty installing
# Remove this line when https://github.com/s-u/Cairo/issues/52 is merged
extra-packages: Cairo=?ignore

15
.gitignore vendored
View File

@@ -6,4 +6,19 @@
*.so
/src-i386/
/src-x86_64/
shinyapps/
README.html
.*.Rnb.cached
/_dev/
.sass_cache_keys
# TypeScript
/node_modules/
.cache
coverage/
madge.svg
# GHA remotes installation
.github/r-depends.rds
.claude/settings.local.json

7
.madgerc Normal file
View File

@@ -0,0 +1,7 @@
{
"detectiveOptions": {
"ts": {
"skipTypeImports": true
}
}
}

6
.vscode/extensions.json vendored Normal file
View File

@@ -0,0 +1,6 @@
{
"recommendations": [
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode"
]
}

23
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,23 @@
{
"search.exclude": {
},
"prettier.prettierPath": "./node_modules/prettier",
"typescript.enablePromptUseWorkspaceTsdk": true,
"[r]": {
"files.trimTrailingWhitespace": true,
"files.insertFinalNewline": true,
"editor.formatOnSave": false,
},
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true,
"files.trimTrailingWhitespace": true,
"files.insertFinalNewline": true,
},
"[json]": {
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"files.trimTrailingWhitespace": true,
"files.insertFinalNewline": true,
},
}

View File

@@ -1,50 +1,229 @@
Package: shiny
Type: Package
Package: shiny
Title: Web Application Framework for R
Version: 0.6.0
Date: 2013-01-23
Author: RStudio, Inc.
Maintainer: Winston Chang <winston@rstudio.com>
Description: Shiny makes it incredibly easy to build interactive web
Version: 1.12.1.9000
Authors@R: c(
person("Winston", "Chang", , "winston@posit.co", role = "aut",
comment = c(ORCID = "0000-0002-1576-2126")),
person("Joe", "Cheng", , "joe@posit.co", role = "aut"),
person("JJ", "Allaire", , "jj@posit.co", role = "aut"),
person("Carson", "Sievert", , "carson@posit.co", role = c("aut", "cre"),
comment = c(ORCID = "0000-0002-4958-2844")),
person("Barret", "Schloerke", , "barret@posit.co", role = "aut",
comment = c(ORCID = "0000-0001-9986-114X")),
person("Garrick", "Aden-Buie", , "garrick@adenbuie.com", role = "aut",
comment = c(ORCID = "0000-0002-7111-0077")),
person("Yihui", "Xie", , "yihui@posit.co", role = "aut"),
person("Jeff", "Allen", role = "aut"),
person("Jonathan", "McPherson", , "jonathan@posit.co", role = "aut"),
person("Alan", "Dipert", role = "aut"),
person("Barbara", "Borges", role = "aut"),
person("Posit Software, PBC", role = c("cph", "fnd"),
comment = c(ROR = "03wc8by49")),
person(, "jQuery Foundation", role = "cph",
comment = "jQuery library and jQuery UI library"),
person(, "jQuery contributors", role = c("ctb", "cph"),
comment = "jQuery library; authors listed in inst/www/shared/jquery-AUTHORS.txt"),
person(, "jQuery UI contributors", role = c("ctb", "cph"),
comment = "jQuery UI library; authors listed in inst/www/shared/jqueryui/AUTHORS.txt"),
person("Mark", "Otto", role = "ctb",
comment = "Bootstrap library"),
person("Jacob", "Thornton", role = "ctb",
comment = "Bootstrap library"),
person(, "Bootstrap contributors", role = "ctb",
comment = "Bootstrap library"),
person(, "Twitter, Inc", role = "cph",
comment = "Bootstrap library"),
person("Prem Nawaz", "Khan", role = "ctb",
comment = "Bootstrap accessibility plugin"),
person("Victor", "Tsaran", role = "ctb",
comment = "Bootstrap accessibility plugin"),
person("Dennis", "Lembree", role = "ctb",
comment = "Bootstrap accessibility plugin"),
person("Srinivasu", "Chakravarthula", role = "ctb",
comment = "Bootstrap accessibility plugin"),
person("Cathy", "O'Connor", role = "ctb",
comment = "Bootstrap accessibility plugin"),
person(, "PayPal, Inc", role = "cph",
comment = "Bootstrap accessibility plugin"),
person("Stefan", "Petre", role = c("ctb", "cph"),
comment = "Bootstrap-datepicker library"),
person("Andrew", "Rowls", role = c("ctb", "cph"),
comment = "Bootstrap-datepicker library"),
person("Brian", "Reavis", role = c("ctb", "cph"),
comment = "selectize.js library"),
person("Salmen", "Bejaoui", role = c("ctb", "cph"),
comment = "selectize-plugin-a11y library"),
person("Denis", "Ineshin", role = c("ctb", "cph"),
comment = "ion.rangeSlider library"),
person("Sami", "Samhuri", role = c("ctb", "cph"),
comment = "Javascript strftime library"),
person(, "SpryMedia Limited", role = c("ctb", "cph"),
comment = "DataTables library"),
person("Ivan", "Sagalaev", role = c("ctb", "cph"),
comment = "highlight.js library"),
person("R Core Team", role = c("ctb", "cph"),
comment = "tar implementation from R")
)
Description: Makes it incredibly easy to build interactive web
applications with R. Automatic "reactive" binding between inputs and
outputs and extensive pre-built widgets make it possible to build
outputs and extensive prebuilt widgets make it possible to build
beautiful, responsive, and powerful applications with minimal effort.
License: GPL-3
License: MIT + file LICENSE
URL: https://shiny.posit.co/, https://github.com/rstudio/shiny
BugReports: https://github.com/rstudio/shiny/issues
Depends:
R (>= 2.14.1)
methods,
R (>= 3.0.2)
Imports:
stats,
bslib (>= 0.6.0),
cachem (>= 1.1.0),
cli,
commonmark (>= 2.0.0),
fastmap (>= 1.1.1),
fontawesome (>= 0.4.0),
glue (>= 1.3.2),
grDevices,
htmltools (>= 0.5.4),
httpuv (>= 1.5.2),
jsonlite (>= 0.9.16),
later (>= 1.0.0),
lifecycle (>= 0.2.0),
mime (>= 0.3),
otel,
promises (>= 1.5.0),
R6 (>= 2.0),
rlang (>= 0.4.10),
sourcetools,
tools,
utils,
datasets,
methods,
httpuv (>= 1.0.6.2),
caTools,
RJSONIO,
xtable,
digest
withr,
xtable
Suggests:
Cairo (>= 1.5-5),
coro (>= 1.1.0),
datasets,
DT,
dygraphs,
future,
ggplot2,
knitr (>= 1.6),
magrittr,
markdown,
Cairo,
testthat
URL: http://www.rstudio.com/shiny/
BugReports: https://github.com/rstudio/shiny/issues
mirai,
otelsdk (>= 0.2.0),
ragg,
reactlog (>= 1.0.0),
rmarkdown,
sass,
showtext,
testthat (>= 3.2.1),
watcher,
yaml
Config/Needs/check: shinytest2
Config/testthat/edition: 3
Encoding: UTF-8
Roxygen: list(markdown = TRUE)
RoxygenNote: 7.3.3
Collate:
'globals.R'
'app-state.R'
'app_template.R'
'bind-cache.R'
'bind-event.R'
'bookmark-state-local.R'
'bookmark-state.R'
'bootstrap-deprecated.R'
'bootstrap-layout.R'
'conditions.R'
'map.R'
'priorityqueue.R'
'utils.R'
'tar.R'
'timer.R'
'tags.R'
'cache.R'
'react.R'
'reactives.R'
'fileupload.R'
'shiny.R'
'shinywrappers.R'
'shinyui.R'
'slider.R'
'bootstrap.R'
'run-url.R'
'busy-indicators-spinners.R'
'busy-indicators.R'
'cache-utils.R'
'deprecated.R'
'devmode.R'
'diagnose.R'
'extended-task.R'
'fileupload.R'
'graph.R'
'reactives.R'
'reactive-domains.R'
'history.R'
'hooks.R'
'html-deps.R'
'image-interact-opts.R'
'image-interact.R'
'imageutils.R'
'input-action.R'
'input-checkbox.R'
'input-checkboxgroup.R'
'input-date.R'
'input-daterange.R'
'input-file.R'
'input-numeric.R'
'input-password.R'
'input-radiobuttons.R'
'input-select.R'
'input-slider.R'
'input-submit.R'
'input-text.R'
'input-textarea.R'
'input-utils.R'
'insert-tab.R'
'insert-ui.R'
'jqueryui.R'
'knitr.R'
'middleware-shiny.R'
'middleware.R'
'timer.R'
'shiny.R'
'mock-session.R'
'modal.R'
'modules.R'
'notifications.R'
'otel-attr-srcref.R'
'otel-collect.R'
'otel-enable.R'
'otel-error.R'
'otel-label.R'
'otel-reactive-update.R'
'otel-session.R'
'otel-shiny.R'
'otel-with.R'
'priorityqueue.R'
'progress.R'
'react.R'
'reexports.R'
'render-cached-plot.R'
'render-plot.R'
'render-table.R'
'run-url.R'
'runapp.R'
'serializers.R'
'server-input-handlers.R'
'server-resource-paths.R'
'server.R'
'shiny-options.R'
'shiny-package.R'
'shinyapp.R'
'shinyui.R'
'shinywrappers.R'
'showcase.R'
'snapshot.R'
'staticimports.R'
'tar.R'
'test-export.R'
'test-server.R'
'test.R'
'update-input.R'
'utils-lang.R'
'utils-tags.R'
'version_bs_date_picker.R'
'version_ion_range_slider.R'
'version_jquery.R'
'version_jqueryui.R'
'version_selectize.R'
'version_strftime.R'
'viewer.R'

2
LICENSE Normal file
View File

@@ -0,0 +1,2 @@
YEAR: 2012-2025
COPYRIGHT HOLDER: Posit Software, PBC

21
LICENSE.md Normal file
View File

@@ -0,0 +1,21 @@
# MIT License
Copyright (c) 2025 shiny authors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

1011
LICENSE.note Normal file

File diff suppressed because it is too large Load Diff

333
NAMESPACE
View File

@@ -1,45 +1,131 @@
# Generated by roxygen2: do not edit by hand
S3method("$",mockclientdata)
S3method("$",reactivevalues)
S3method("$",session_proxy)
S3method("$",shinyoutput)
S3method("$<-",reactivevalues)
S3method("$<-",session_proxy)
S3method("$<-",shinyoutput)
S3method("[",mockclientdata)
S3method("[",reactivevalues)
S3method("[",shinyoutput)
S3method("[<-",reactivevalues)
S3method("[<-",shinyoutput)
S3method("[[",mockclientdata)
S3method("[[",reactivevalues)
S3method("[[",session_proxy)
S3method("[[",shinyoutput)
S3method("[[<-",reactivevalues)
S3method("[[<-",shinyoutput)
S3method("names<-",reactivevalues)
S3method(as.character,shiny.tag)
S3method(as.character,shiny.tag.list)
S3method(as.list,Map)
S3method(as.list,reactivevalues)
S3method(format,shiny.tag)
S3method(format,shiny.tag.list)
S3method(as.shiny.appobj,character)
S3method(as.shiny.appobj,list)
S3method(as.shiny.appobj,shiny.appobj)
S3method(as.tags,shiny.appobj)
S3method(as.tags,shiny.render.function)
S3method(bindCache,"function")
S3method(bindCache,Observer)
S3method(bindCache,default)
S3method(bindCache,reactive.cache)
S3method(bindCache,reactive.event)
S3method(bindCache,reactiveExpr)
S3method(bindCache,shiny.render.function)
S3method(bindCache,shiny.render.function.cache)
S3method(bindCache,shiny.render.function.event)
S3method(bindCache,shiny.renderPlot)
S3method(bindEvent,Observer)
S3method(bindEvent,Observer.event)
S3method(bindEvent,default)
S3method(bindEvent,reactive.event)
S3method(bindEvent,reactiveExpr)
S3method(bindEvent,shiny.render.function)
S3method(format,reactiveExpr)
S3method(format,reactiveVal)
S3method(length,Map)
S3method(names,reactivevalues)
S3method(print,shiny.tag)
S3method(print,shiny.tag.list)
S3method(print,reactive)
S3method(print,reactivevalues)
S3method(print,shiny.appobj)
S3method(print,shiny.render.function)
S3method(print,shiny_runtests)
S3method(str,reactivevalues)
export("conditionStackTrace<-")
export(..stacktraceoff..)
export(..stacktraceon..)
export(ExtendedTask)
export(HTML)
export(MockShinySession)
export(NS)
export(Progress)
export(a)
export(absolutePanel)
export(actionButton)
export(actionLink)
export(addResourcePath)
export(animationOptions)
export(appendTab)
export(as.shiny.appobj)
export(basicPage)
export(bindCache)
export(bindEvent)
export(bookmarkButton)
export(bootstrapLib)
export(bootstrapPage)
export(br)
export(browserViewer)
export(brushOpts)
export(brushedPoints)
export(busyIndicatorOptions)
export(callModule)
export(captureStackTraces)
export(checkboxGroupInput)
export(checkboxInput)
export(clickOpts)
export(code)
export(column)
export(conditionStackTrace)
export(conditionalPanel)
export(createRenderFunction)
export(createWebDependency)
export(dataTableOutput)
export(dateInput)
export(dateRangeInput)
export(dblclickOpts)
export(debounce)
export(devmode)
export(dialogViewer)
export(diskCache)
export(div)
export(downloadButton)
export(downloadHandler)
export(downloadLink)
export(em)
export(enableBookmarking)
export(eventReactive)
export(exportTestValues)
export(exprToFunction)
export(fileInput)
export(fillCol)
export(fillPage)
export(fillRow)
export(fixedPage)
export(fixedPanel)
export(fixedRow)
export(flowLayout)
export(fluidPage)
export(fluidRow)
export(freezeReactiveVal)
export(freezeReactiveValue)
export(getCurrentOutputInfo)
export(getCurrentTheme)
export(getDefaultReactiveDomain)
export(getQueryString)
export(getShinyOption)
export(getUrlHash)
export(get_devmode_option)
export(h1)
export(h2)
export(h3)
@@ -48,34 +134,103 @@ export(h5)
export(h6)
export(headerPanel)
export(helpText)
export(hideTab)
export(hoverOpts)
export(hr)
export(htmlOutput)
export(htmlTemplate)
export(httpResponse)
export(icon)
export(imageOutput)
export(img)
export(in_devmode)
export(incProgress)
export(includeCSS)
export(includeHTML)
export(includeMarkdown)
export(includeScript)
export(includeText)
export(inputPanel)
export(insertTab)
export(insertUI)
export(installExprFunction)
export(invalidateLater)
export(is.key_missing)
export(is.reactive)
export(is.reactivevalues)
export(is.shiny.appobj)
export(is.singleton)
export(isRunning)
export(isTruthy)
export(isolate)
export(key_missing)
export(loadSupport)
export(localOtelCollect)
export(mainPanel)
export(makeReactiveBinding)
export(markRenderFunction)
export(markdown)
export(maskReactiveContext)
export(memoryCache)
export(modalButton)
export(modalDialog)
export(moduleServer)
export(navbarMenu)
export(navbarPage)
export(navlistPanel)
export(nearPoints)
export(need)
export(ns.sep)
export(numericInput)
export(observe)
export(observeEvent)
export(onBookmark)
export(onBookmarked)
export(onFlush)
export(onFlushed)
export(onReactiveDomainEnded)
export(onRestore)
export(onRestored)
export(onSessionEnded)
export(onStop)
export(onUnhandledError)
export(outputOptions)
export(p)
export(pageWithSidebar)
export(paneViewer)
export(parseQueryString)
export(passwordInput)
export(plotOutput)
export(plotPNG)
export(pre)
export(prependTab)
export(printError)
export(printStackTrace)
export(quoToFunction)
export(radioButtons)
export(reactive)
export(reactivePlot)
export(reactivePrint)
export(reactiveTable)
export(reactiveText)
export(reactiveConsole)
export(reactiveFileReader)
export(reactivePoll)
export(reactiveTimer)
export(reactiveUI)
export(reactiveVal)
export(reactiveValues)
export(reactiveValuesToList)
export(reactlog)
export(reactlogAddMark)
export(reactlogReset)
export(reactlogShow)
export(registerInputHandler)
export(registerThemeDependency)
export(register_devmode_option)
export(removeInputHandler)
export(removeModal)
export(removeNotification)
export(removeResourcePath)
export(removeTab)
export(removeUI)
export(renderCachedPlot)
export(renderDataTable)
export(renderImage)
export(renderPlot)
export(renderPrint)
@@ -83,45 +238,195 @@ export(renderTable)
export(renderText)
export(renderUI)
export(repeatable)
export(req)
export(resourcePaths)
export(restoreInput)
export(runApp)
export(runExample)
export(runGadget)
export(runGist)
export(runGitHub)
export(runTests)
export(runUrl)
export(safeError)
export(selectInput)
export(selectizeInput)
export(serverInfo)
export(setBookmarkExclude)
export(setProgress)
export(setSerializer)
export(shinyApp)
export(shinyAppDir)
export(shinyAppFile)
export(shinyAppTemplate)
export(shinyOptions)
export(shinyServer)
export(shinyUI)
export(showBookmarkUrlModal)
export(showModal)
export(showNotification)
export(showTab)
export(sidebarLayout)
export(sidebarPanel)
export(singleton)
export(sizeGrowthRatio)
export(sliderInput)
export(snapshotExclude)
export(snapshotPreprocessInput)
export(snapshotPreprocessOutput)
export(span)
export(splitLayout)
export(stopApp)
export(strong)
export(submitButton)
export(suppressDependencies)
export(tabPanel)
export(tabPanelBody)
export(tableOutput)
export(tabsetPanel)
export(tag)
export(tagAppendAttributes)
export(tagAppendChild)
export(tagAppendChildren)
export(tagGetAttribute)
export(tagHasAttribute)
export(tagList)
export(tagSetChildren)
export(tags)
export(testServer)
export(textAreaInput)
export(textInput)
export(textOutput)
export(throttle)
export(titlePanel)
export(uiOutput)
export(updateActionButton)
export(updateActionLink)
export(updateCheckboxGroupInput)
export(updateCheckboxInput)
export(updateDateInput)
export(updateDateRangeInput)
export(updateNavbarPage)
export(updateNavlistPanel)
export(updateNumericInput)
export(updateQueryString)
export(updateRadioButtons)
export(updateSelectInput)
export(updateSelectizeInput)
export(updateSliderInput)
export(updateTabsetPanel)
export(updateTextAreaInput)
export(updateTextInput)
export(updateVarSelectInput)
export(updateVarSelectizeInput)
export(urlModal)
export(useBusyIndicators)
export(validate)
export(validateCssUnit)
export(varSelectInput)
export(varSelectizeInput)
export(verbatimTextOutput)
export(verticalLayout)
export(wellPanel)
export(withLogErrors)
export(withMathJax)
export(withOtelCollect)
export(withProgress)
export(withReactiveDomain)
export(withTags)
import(RJSONIO)
import(caTools)
import(digest)
export(with_devmode)
import(R6)
import(htmltools)
import(httpuv)
import(methods)
import(mime)
import(xtable)
importFrom(fastmap,fastmap)
importFrom(fastmap,is.key_missing)
importFrom(fastmap,key_missing)
importFrom(grDevices,dev.cur)
importFrom(grDevices,dev.set)
importFrom(htmltools,HTML)
importFrom(htmltools,a)
importFrom(htmltools,br)
importFrom(htmltools,code)
importFrom(htmltools,div)
importFrom(htmltools,em)
importFrom(htmltools,h1)
importFrom(htmltools,h2)
importFrom(htmltools,h3)
importFrom(htmltools,h4)
importFrom(htmltools,h5)
importFrom(htmltools,h6)
importFrom(htmltools,hr)
importFrom(htmltools,htmlTemplate)
importFrom(htmltools,img)
importFrom(htmltools,includeCSS)
importFrom(htmltools,includeHTML)
importFrom(htmltools,includeMarkdown)
importFrom(htmltools,includeScript)
importFrom(htmltools,includeText)
importFrom(htmltools,is.singleton)
importFrom(htmltools,p)
importFrom(htmltools,pre)
importFrom(htmltools,singleton)
importFrom(htmltools,span)
importFrom(htmltools,strong)
importFrom(htmltools,suppressDependencies)
importFrom(htmltools,tag)
importFrom(htmltools,tagAppendAttributes)
importFrom(htmltools,tagAppendChild)
importFrom(htmltools,tagAppendChildren)
importFrom(htmltools,tagGetAttribute)
importFrom(htmltools,tagHasAttribute)
importFrom(htmltools,tagList)
importFrom(htmltools,tagSetChildren)
importFrom(htmltools,tags)
importFrom(htmltools,validateCssUnit)
importFrom(htmltools,withTags)
importFrom(lifecycle,deprecated)
importFrom(lifecycle,is_present)
importFrom(promises,"%...!%")
importFrom(promises,"%...>%")
importFrom(promises,as.promise)
importFrom(promises,hybrid_then)
importFrom(promises,is.promise)
importFrom(promises,is.promising)
importFrom(promises,new_promise_domain)
importFrom(promises,promise_reject)
importFrom(promises,promise_resolve)
importFrom(promises,with_promise_domain)
importFrom(rlang,"%||%")
importFrom(rlang,"fn_body<-")
importFrom(rlang,"fn_fmls<-")
importFrom(rlang,as_function)
importFrom(rlang,as_quosure)
importFrom(rlang,check_dots_empty)
importFrom(rlang,check_dots_unnamed)
importFrom(rlang,enexpr)
importFrom(rlang,enquo)
importFrom(rlang,enquo0)
importFrom(rlang,enquos)
importFrom(rlang,enquos0)
importFrom(rlang,eval_tidy)
importFrom(rlang,expr)
importFrom(rlang,fn_body)
importFrom(rlang,get_env)
importFrom(rlang,get_expr)
importFrom(rlang,inject)
importFrom(rlang,is_false)
importFrom(rlang,is_missing)
importFrom(rlang,is_na)
importFrom(rlang,is_quosure)
importFrom(rlang,list2)
importFrom(rlang,maybe_missing)
importFrom(rlang,missing_arg)
importFrom(rlang,new_function)
importFrom(rlang,new_quosure)
importFrom(rlang,pairlist2)
importFrom(rlang,quo)
importFrom(rlang,quo_get_expr)
importFrom(rlang,quo_is_missing)
importFrom(rlang,quo_set_env)
importFrom(rlang,quo_set_expr)
importFrom(rlang,zap_srcref)

294
NEWS
View File

@@ -1,294 +0,0 @@
shiny 0.6.0
--------------------------------------------------------------------------------
* `tabsetPanel()` can be directed to start with a specific tab selected.
* Fix bug where multiple file uploads with 3 or more files result in incorrect
data.
* Add `withTags()` function.
* Add dateInput and dateRangeInput.
* `shinyServer()` now takes an optional `session` argument, which is used for
communication with the session object.
* Add functions to update values of existing inputs on a page, instead of
replacing them entirely.
* Allow listening on domain sockets.
* Added `actionButton()` to Shiny.
* The server can now send custom JSON messages to the client. On the client
side, functions can be registered to handle these messages.
* Callbacks can be registered to be called at the end of a client session.
* Add ability to set priority of observers and outputs. Each priority level
gets its own queue.
* Fix bug where the presence of a submit button would prevent sending of
metadata until the button was clicked.
* `reactiveTimer()` and `invalidateLater()` by default no longer invalidate
reactive objects after the client session has closed.
* Shiny apps can be run without a server.r and ui.r file.
shiny 0.5.0
--------------------------------------------------------------------------------
* Switch from websockets package for handling websocket connections to httpuv.
* New method for detecting hidden output objects. Instead of checking that
height and width are 0, it checks that the object or any ancestor in the DOM
has style display:none.
* Add `clientData` reactive values object, which carries information about the
client. This includes the hidden status of output objects, height/width plot
output objects, and the URL of the browser.
* Add `parseQueryString()` function.
* Add `renderImage()` function for sending arbitrary image files to the client,
and its counterpart, `imageOutput()`.
* Add support for high-resolution (Retina) displays.
* Fix bug #55, where `renderTable()` would throw error with an empty data frame.
shiny 0.4.1
--------------------------------------------------------------------------------
* Fix bug where width and height weren't passed along properly from
`reactivePlot` to `renderPlot`.
* Fix bug where infinite recursion would happen when `reactivePlot` was passed
a function for width or height.
shiny 0.4.0
--------------------------------------------------------------------------------
* Added suspend/resume capability to observers.
* Output objects are automatically suspended when they are hidden on the user's
web browser.
* `runGist()` accepts GitHub's new URL format, which includes the username.
* `reactive()` and `observe()` now take expressions instead of functions.
* `reactiveText()`, `reactivePlot()`, and so on, have been renamed to
`renderText()`, `renderPlot()`, etc. They also now take expressions instead
of functions.
* Fixed a bug where empty values in a numericInput were sent to the R process
as 0. They are now sent as NA.
shiny 0.3.1
--------------------------------------------------------------------------------
* Fix issue #91: bug where downloading files did not work.
* Add [[<- operator for shinyoutput object, making it possible to assign values
with `output[['plot1']] <- ...`.
* Reactive functions now preserve the visible/invisible state of their returned
values.
shiny 0.3.0
--------------------------------------------------------------------------------
* Reactive functions are now evaluated lazily.
* Add `reactiveValues()`.
* Using `as.list()` to convert a reactivevalues object (like `input`) to a list
is deprecated. The new function `reactiveValuesToList()` should be used
instead.
* Add `isolate()`. This function is used for accessing reactive functions,
without them invalidating their parent contexts.
* Fix issue #58: bug where reactive functions are not re-run when all items in
a checkboxGroup are unchecked.
* Fix issue #71, where `reactiveTable()` would return blank if the first
element of a data frame was NA.
* In `plotOutput`, better validation for CSS units when specifying width and
height.
* `reactivePrint()` no longer displays invisible output.
* `reactiveText()` no longer displays printed output, only the return value
from a function.
* The `runGitHub()` and `runUrl()` functions have been added, for running
Shiny apps from GitHub repositories and zip/tar files at remote URLs.
* Fix issue #64, where pressing Enter in a textbox would cause a form to
submit.
shiny 0.2.4
--------------------------------------------------------------------------------
* `runGist` has been updated to use the new download URLs from
https://gist.github.com.
* Shiny now uses `CairoPNG()` for output, when the Cairo package is available.
This provides better-looking output on Linux and Windows.
shiny 0.2.3
--------------------------------------------------------------------------------
* Ignore request variables for routing purposes
shiny 0.2.2
--------------------------------------------------------------------------------
* Fix CRAN warning (assigning to global environment)
shiny 0.2.1
--------------------------------------------------------------------------------
* [BREAKING] Modify API of `downloadHandler`: The `content` function now takes
a file path, not writable connection, as an argument. This makes it much
easier to work with APIs that only write to file paths, not connections.
shiny 0.2.0
--------------------------------------------------------------------------------
* Fix subtle name resolution bug--the usual symptom being S4 methods not being
invoked correctly when called from inside of ui.R or server.R
shiny 0.1.14
--------------------------------------------------------------------------------
* Fix slider animator, which broke in 0.1.10
shiny 0.1.13
--------------------------------------------------------------------------------
* Fix temp file leak in reactivePlot
shiny 0.1.12
--------------------------------------------------------------------------------
* Fix problems with runGist on Windows
* Add feature for on-the-fly file downloads (e.g. CSV data, PDFs)
* Add CSS hooks for app-wide busy indicators
shiny 0.1.11
--------------------------------------------------------------------------------
* Fix input binding with IE8 on Shiny Server
* Fix issue #41: reactiveTable should allow print options too
* Allow dynamic sizing of reactivePlot (i.e. using a function instead of a fixed
value)
shiny 0.1.10
--------------------------------------------------------------------------------
* Support more MIME types when serving out of www
* Fix issue #35: Allow modification of untar args
* headerPanel can take an explicit window title parameter
* checkboxInput uses correct attribute `checked` instead of `selected`
* Fix plot rendering with IE8 on Shiny Server
shiny 0.1.9
--------------------------------------------------------------------------------
* Much less flicker when updating plots
* More customizable error display
* Add `includeText`, `includeHTML`, and `includeMarkdown` functions for putting
text, HTML, and Markdown content from external files in the application's UI.
shiny 0.1.8
--------------------------------------------------------------------------------
* Add `runGist` function for conveniently running a Shiny app that is published
on gist.github.com.
* Fix issue #27: Warnings cause reactive functions to stop executing.
* The server.R and ui.R filenames are now case insensitive.
* Add `wellPanel` function for creating inset areas on the page.
* Add `bootstrapPage` function for creating new Twitter Bootstrap based
layouts from scratch.
shiny 0.1.7
--------------------------------------------------------------------------------
* Fix issue #26: Shiny.OutputBindings not correctly exported.
* Add `repeatable` function for making easily repeatable versions of random
number generating functions.
* Transcode JSON into UTF-8 (prevents non-ASCII reactivePrint values from
causing errors on Windows).
shiny 0.1.6
--------------------------------------------------------------------------------
* Import package dependencies, instead of attaching them (with the exception of
websockets, which doesn't currently work unless attached).
* conditionalPanel was animated, now it is not.
* bindAll was not correctly sending initial values to the server; fixed.
shiny 0.1.5
--------------------------------------------------------------------------------
* BREAKING CHANGE: JS APIs Shiny.bindInput and Shiny.bindOutput removed and
replaced with Shiny.bindAll; Shiny.unbindInput and Shiny.unbindOutput removed
and replaced with Shiny.unbindAll.
* Add file upload support (currently only works with Chrome and Firefox). Use
a normal HTML file input, or call the `fileInput` UI function.
* Shiny.unbindOutputs did not work, now it does.
* Generally improved robustness of dynamic input/output bindings.
* Add conditionalPanel UI function to allow showing/hiding UI based on a JS
expression; for example, whether an input is a particular value. Also works in
raw HTML (add the `data-display-if` attribute to the element that should be
shown/hidden).
* htmlOutput (CSS class `shiny-html-output`) can contain inputs and outputs.
shiny 0.1.4
--------------------------------------------------------------------------------
* Allow Bootstrap tabsets to act as reactive inputs; their value indicates which
tab is active
* Upgrade to Bootstrap 2.1
* Add `checkboxGroupInput` control, which presents a list of checkboxes and
returns a vector of the selected values
* Add `addResourcePath`, intended for reusable component authors to access CSS,
JavaScript, image files, etc. from their package directories
* Add Shiny.bindInputs(scope), .unbindInputs(scope), .bindOutputs(scope), and
.unbindOutputs(scope) JS API calls to allow dynamic binding/unbinding of HTML
elements
shiny 0.1.3
--------------------------------------------------------------------------------
* Introduce Shiny.inputBindings.register JS API and InputBinding class, for
creating custom input controls
* Add `step` parameter to numericInput
* Read names of input using `names(input)`
* Access snapshot of input as a list using `as.list(input)`
* Fix issue #10: Plots in tabsets not rendered
shiny 0.1.2
--------------------------------------------------------------------------------
Initial private beta release!

2151
NEWS.md Normal file

File diff suppressed because it is too large Load Diff

26
R/app-state.R Normal file
View File

@@ -0,0 +1,26 @@
#' @include globals.R
NULL
# The current app state is a place to read and hang state for the
# currently-running application. This is useful for setting options that will
# last as long as the application is running.
.globals$appState <- NULL
initCurrentAppState <- function(appobj) {
if (!is.null(.globals$appState)) {
stop("Can't initialize current app state when another is currently active.")
}
.globals$appState <- new.env(parent = emptyenv())
.globals$appState$app <- appobj
# Copy over global options
.globals$appState$options <- .globals$options
}
getCurrentAppState <- function() {
.globals$appState
}
clearCurrentAppState <- function() {
.globals$appState <- NULL
}

281
R/app_template.R Normal file
View File

@@ -0,0 +1,281 @@
#' Generate a Shiny application from a template
#'
#' This function populates a directory with files for a Shiny application.
#'
#' In an interactive R session, this function will, by default, prompt the user
#' to select which components to add to the application. Choices are
#'
#' ```
#' 1: All
#' 2: app.R : Main application file
#' 3: R/example.R : Helper file with R code
#' 4: R/example-module.R : Example module
#' 5: tests/testthat/ : Tests using the testthat and shinytest2 package
#' ```
#'
#' If option 1 is selected, the full example application including the
#' following files and directories is created:
#'
#' ```
#' appdir/
#' |- app.R
#' |- R
#' | |- example-module.R
#' | `- example.R
#' `- tests
#' |- testthat.R
#' `- testthat
#' |- setup-shinytest2.R
#' |- test-examplemodule.R
#' |- test-server.R
#' |- test-shinytest2.R
#' `- test-sort.R
#' ```
#'
#' Some notes about these files:
#' * `app.R` is the main application file.
#' * All files in the `R/` subdirectory are automatically sourced when the
#' application is run.
#' * `R/example.R` and `R/example-module.R` are automatically sourced when
#' the application is run. The first contains a function `lexical_sort()`,
#' and the second contains code for module created by the
#' [moduleServer()] function, which is used in the application.
#' * `tests/` contains various tests for the application. You may
#' choose to use or remove any of them. They can be executed by the
#' [runTests()] function.
#' * `tests/testthat.R` is a test runner for test files in the
#' `tests/testthat/` directory using the
#' [shinytest2](https://rstudio.github.io/shinytest2/reference/test_app.html)
#' package.
#' * `tests/testthat/setup-shinytest2.R` is setup file to source your `./R` folder into the testing environment.
#' * `tests/testthat/test-examplemodule.R` is a test for an application's module server function.
#' * `tests/testthat/test-server.R` is a test for the application's server code
#' * `tests/testthat/test-shinytest2.R` is a test that uses the
#' [shinytest2](https://rstudio.github.io/shinytest2/) package to do
#' snapshot-based testing.
#' * `tests/testthat/test-sort.R` is a test for a supporting function in the `R/` directory.
#'
#' @param path Path to create new shiny application template.
#' @param examples Either one of "default", "ask", "all", or any combination of
#' "app", "rdir", "module", and "tests". In an
#' interactive session, "default" falls back to "ask"; in a non-interactive
#' session, "default" falls back to "all". With "ask", this function will
#' prompt the user to select which template items will be added to the new app
#' directory. With "all", all template items will be added to the app
#' directory.
#' @param dryrun If `TRUE`, don't actually write any files; just print out which
#' files would be written.
#'
#' @export
shinyAppTemplate <- function(path = NULL, examples = "default", dryrun = FALSE)
{
if (is.null(path)) {
stop("Please provide a `path`.")
}
# =======================================================
# Option handling
# =======================================================
choices <- c(
app = "app.R : Main application file",
rdir = "R/example.R : Helper file with R code",
module = "R/example-module.R : Example module",
tests = "tests/testthat/ : Tests using {testthat} and {shinytest2}"
)
# Support legacy value
examples[examples == "shinytest"] <- "tests"
examples[examples == "testthat"] <- "tests"
examples <- unique(examples)
if (identical(examples, "default")) {
if (rlang::is_interactive()) {
examples <- "ask"
} else {
examples <- "all"
}
}
if (!identical(examples, "ask") &&
!identical(examples, "all") &&
any(! examples %in% names(choices)))
{
stop('`examples` must be one of "default", "ask", "all", or any combination of "',
paste(names(choices), collapse = '", "'), '".')
}
if (identical(examples, "ask")) {
response <- select_menu(
c(all = "All", choices),
title = paste0(
"Select which of the following to add at ", path, "/ :"
),
msg = "Enter one or more numbers (with spaces), or an empty line to exit: \n"
)
examples <- names(response)
}
examples <- unique(examples)
if ("all" %in% examples) {
examples <- names(choices)
}
if (length(examples) == 0) {
return(invisible())
}
if ("tests" %in% examples) {
rlang::check_installed("shinytest2", "for {testthat} tests to work as expected", version = "0.2.0")
}
# =======================================================
# Utility functions
# =======================================================
# Check if a directory is empty, ignoring certain files
dir_is_empty <- function(path) {
files <- list.files(path, all.files = TRUE, no.. = TRUE)
# Ignore .DS_Store files, which are sometimes automatically created on macOS
files <- setdiff(files, ".DS_Store")
return(length(files) != 0)
}
# Helper to resolve paths relative to our template
template_path <- function(...) {
system_file("app_template", ..., package = "shiny")
}
# Resolve path relative to destination
dest_path <- function(...) {
file.path(path, ...)
}
mkdir <- function(path) {
if (!dirExists(path)) {
message("Creating ", ensure_trailing_slash(path))
if (!dryrun) {
dir.create(path, recursive = TRUE)
}
}
}
# Copy a file from the template directory to the destination directory. If the
# file has templating code (it contains `{{` in the text), then run it through
# the htmlTemplate().
copy_file_one <- function(name) {
from <- template_path(name)
to <- dest_path(name)
message("Creating ", to)
if (file.exists(to)) {
stop(to, " already exists. Please remove it and try again.", call. = FALSE)
}
if (!dryrun) {
is_template <- any(grepl("{{", readLines(from), fixed = TRUE))
if (is_template) {
writeChar(
as.character(htmlTemplate(
from,
rdir = "rdir" %in% examples,
module = "module" %in% examples
)),
con = to,
eos = NULL
)
} else {
file.copy(from, to)
}
}
}
# Copy multiple files from template to destination.
copy_file <- function(names) {
for (name in names) {
copy_file_one(name)
}
}
# Copy the files for a tests/ subdirectory
copy_test_dir <- function() {
files <- dir(template_path("tests"), recursive = TRUE)
# Filter out files that are not module files in the R directory.
if (! "rdir" %in% examples) {
# find all files in the testthat folder that are not module or server files
is_r_folder_file <- !grepl("module|server|shinytest2|testthat", basename(files))
files <- files[!is_r_folder_file]
}
# Filter out module files, if applicable.
if (! "module" %in% examples) {
files <- files[!grepl("module", files)]
}
mkdir(dest_path("tests"))
# Create any subdirectories if needed
dirs <- setdiff(unique(dirname(files)), ".")
for (dir in dirs) {
mkdir(dest_path("tests", dir))
}
copy_file(file.path("tests", files))
}
# =======================================================
# Main function
# =======================================================
if (is.null(path)) {
stop("`path` is missing.")
}
if (file.exists(path) && !dirExists(path)) {
stop(path, " exists but is not a directory.")
}
if (dirExists(path) && dir_is_empty(path)) {
if (interactive()) {
response <- readline(paste0(
ensure_trailing_slash(path),
" is not empty. Do you want to use this directory anyway? [y/n] "
))
if (tolower(response) != "y") {
return(invisible())
}
}
} else {
mkdir(path)
}
if ("app" %in% examples) {
copy_file("app.R")
}
# R/ dir with non-module files
if ("rdir" %in% examples) {
files <- dir(template_path("R"))
non_module_files <- files[!grepl("module.R$", files)]
mkdir(dest_path("R"))
copy_file(file.path("R", non_module_files))
}
# R/ dir with module files
if ("module" %in% examples) {
files <- dir(template_path("R"))
module_files <- files[grepl("module.R$", files)]
mkdir(dest_path("R"))
copy_file(file.path("R", module_files))
}
# tests/testthat dir
if ("tests" %in% examples) {
copy_test_dir()
}
invisible()
}

793
R/bind-cache.R Normal file
View File

@@ -0,0 +1,793 @@
utils::globalVariables(".GenericCallEnv", add = TRUE)
#' Add caching with reactivity to an object
#'
#' @description
#'
#' `bindCache()` adds caching [reactive()] expressions and `render*` functions
#' (like [renderText()], [renderTable()], ...).
#'
#' Ordinary [reactive()] expressions automatically cache their _most recent_
#' value, which helps to avoid redundant computation in downstream reactives.
#' `bindCache()` will cache all previous values (as long as they fit in the
#' cache) and they can be shared across user sessions. This allows
#' `bindCache()` to dramatically improve performance when used correctly.
#' @details
#'
#' `bindCache()` requires one or more expressions that are used to generate a
#' **cache key**, which is used to determine if a computation has occurred
#' before and hence can be retrieved from the cache. If you're familiar with the
#' concept of memoizing pure functions (e.g., the \pkg{memoise} package), you
#' can think of the cache key as the input(s) to a pure function. As such, one
#' should take care to make sure the use of `bindCache()` is _pure_ in the same
#' sense, namely:
#'
#' 1. For a given key, the return value is always the same.
#' 2. Evaluation has no side-effects.
#'
#' In the example here, the `bindCache()` key consists of `input$x` and
#' `input$y` combined, and the value is `input$x * input$y`. In this simple
#' example, for any given key, there is only one possible returned value.
#'
#' ```
#' r <- reactive({ input$x * input$y }) %>%
#' bindCache(input$x, input$y)
#' ```
#'
#' The largest performance improvements occur when the cache key is fast to
#' compute and the reactive expression is slow to compute. To see if the value
#' should be computed, a cached reactive evaluates the key, and then serializes
#' and hashes the result. If the resulting hashed key is in the cache, then the
#' cached reactive simply retrieves the previously calculated value and returns
#' it; if not, then the value is computed and the result is stored in the cache
#' before being returned.
#'
#' To compute the cache key, `bindCache()` hashes the contents of `...`, so it's
#' best to avoid including large objects in a cache key since that can result in
#' slow hashing. It's also best to avoid reference objects like environments and
#' R6 objects, since the serialization of these objects may not capture relevant
#' changes.
#'
#' If you want to use a large object as part of a cache key, it may make sense
#' to do some sort of reduction on the data that still captures information
#' about whether a value can be retrieved from the cache. For example, if you
#' have a large data set with timestamps, it might make sense to extract the
#' most recent timestamp and return that. Then, instead of hashing the entire
#' data object, the cached reactive only needs to hash the timestamp.
#'
#' ```
#' r <- reactive({ compute(bigdata()) } %>%
#' bindCache({ extract_most_recent_time(bigdata()) })
#' ```
#'
#' For computations that are very slow, it often makes sense to pair
#' [bindCache()] with [bindEvent()] so that no computation is performed until
#' the user explicitly requests it (for more, see the Details section of
#' [bindEvent()]).
#' @section Cache keys and reactivity:
#'
#' Because the **value** expression (from the original [reactive()]) is
#' cached, it is not necessarily re-executed when someone retrieves a value,
#' and therefore it can't be used to decide what objects to take reactive
#' dependencies on. Instead, the **key** is used to figure out which objects
#' to take reactive dependencies on. In short, the key expression is reactive,
#' and value expression is no longer reactive.
#'
#' Here's an example of what not to do: if the key is `input$x` and the value
#' expression is from `reactive({input$x + input$y})`, then the resulting
#' cached reactive will only take a reactive dependency on `input$x` -- it
#' won't recompute `{input$x + input$y}` when just `input$y` changes.
#' Moreover, the cache won't use `input$y` as part of the key, and so it could
#' return incorrect values in the future when it retrieves values from the
#' cache. (See the examples below for an example of this.)
#'
#' A better cache key would be something like `input$x, input$y`. This does
#' two things: it ensures that a reactive dependency is taken on both
#' `input$x` and `input$y`, and it also makes sure that both values are
#' represented in the cache key.
#'
#' In general, `key` should use the same reactive inputs as `value`, but the
#' computation should be simpler. If there are other (non-reactive) values
#' that are consumed, such as external data sources, they should be used in
#' the `key` as well. Note that if the `key` is large, it can make sense to do
#' some sort of reduction on it so that the serialization and hashing of the
#' cache key is not too expensive.
#'
#' Remember that the key is _reactive_, so it is not re-executed every single
#' time that someone accesses the cached reactive. It is only re-executed if
#' it has been invalidated by one of the reactives it depends on. For
#' example, suppose we have this cached reactive:
#'
#' ```
#' r <- reactive({ input$x * input$y }) %>%
#' bindCache(input$x, input$y)
#' ```
#'
#' In this case, the key expression is essentially `reactive(list(input$x,
#' input$y))` (there's a bit more to it, but that's a good enough
#' approximation). The first time `r()` is called, it executes the key, then
#' fails to find it in the cache, so it executes the value expression, `{
#' input$x + input$y }`. If `r()` is called again, then it does not need to
#' re-execute the key expression, because it has not been invalidated via a
#' change to `input$x` or `input$y`; it simply returns the previous value.
#' However, if `input$x` or `input$y` changes, then the reactive expression will
#' be invalidated, and the next time that someone calls `r()`, the key
#' expression will need to be re-executed.
#'
#' Note that if the cached reactive is passed to [bindEvent()], then the key
#' expression will no longer be reactive; instead, the event expression will be
#' reactive.
#'
#'
#' @section Cache scope:
#'
#' By default, when `bindCache()` is used, it is scoped to the running
#' application. That means that it shares a cache with all user sessions
#' connected to the application (within the R process). This is done with the
#' `cache` parameter's default value, `"app"`.
#'
#' With an app-level cache scope, one user can benefit from the work done for
#' another user's session. In most cases, this is the best way to get
#' performance improvements from caching. However, in some cases, this could
#' leak information between sessions. For example, if the cache key does not
#' fully encompass the inputs used by the value, then data could leak between
#' the sessions. Or if a user sees that a cached reactive returns its value
#' very quickly, they may be able to infer that someone else has already used
#' it with the same values.
#'
#' It is also possible to scope the cache to the session, with
#' `cache="session"`. This removes the risk of information leaking between
#' sessions, but then one session cannot benefit from computations performed in
#' another session.
#'
#' It is possible to pass in caching objects directly to
#' `bindCache()`. This can be useful if, for example, you want to use a
#' particular type of cache with specific cached reactives, or if you want to
#' use a [cachem::cache_disk()] that is shared across multiple processes and
#' persists beyond the current R session.
#'
#' To use different settings for an application-scoped cache, you can call
#' [shinyOptions()] at the top of your app.R, server.R, or
#' global.R. For example, this will create a cache with 500 MB of space
#' instead of the default 200 MB:
#'
#' ```
#' shinyOptions(cache = cachem::cache_mem(max_size = 500e6))
#' ```
#'
#' To use different settings for a session-scoped cache, you can set
#' `session$cache` at the top of your server function. By default, it will
#' create a 200 MB memory cache for each session, but you can replace it with
#' something different. To use the session-scoped cache, you must also call
#' `bindCache()` with `cache="session"`. This will create a 100 MB cache for
#' the session:
#'
#' ```
#' function(input, output, session) {
#' session$cache <- cachem::cache_mem(max_size = 100e6)
#' ...
#' }
#' ```
#'
#' If you want to use a cache that is shared across multiple R processes, you
#' can use a [cachem::cache_disk()]. You can create a application-level shared
#' cache by putting this at the top of your app.R, server.R, or global.R:
#'
#' ```
#' shinyOptions(cache = cachem::cache_disk(file.path(dirname(tempdir()), "myapp-cache")))
#' ```
#'
#' This will create a subdirectory in your system temp directory named
#' `myapp-cache` (replace `myapp-cache` with a unique name of
#' your choosing). On most platforms, this directory will be removed when
#' your system reboots. This cache will persist across multiple starts and
#' stops of the R process, as long as you do not reboot.
#'
#' To have the cache persist even across multiple reboots, you can create the
#' cache in a location outside of the temp directory. For example, it could
#' be a subdirectory of the application:
#'
#' ```
#' shinyOptions(cache = cachem::cache_disk("./myapp-cache"))
#' ```
#'
#' In this case, resetting the cache will have to be done manually, by deleting
#' the directory.
#'
#' You can also scope a cache to just one item, or selected items. To do that,
#' create a [cachem::cache_mem()] or [cachem::cache_disk()], and pass it
#' as the `cache` argument of `bindCache()`.
#'
#'
#' @section Computing cache keys:
#'
#' The actual cache key that is used internally takes value from evaluating
#' the key expression(s) (from the `...` arguments) and combines it with the
#' (unevaluated) value expression.
#'
#' This means that if there are two cached reactives which have the same
#' result from evaluating the key, but different value expressions, then they
#' will not need to worry about collisions.
#'
#' However, if two cached reactives have identical key and value expressions
#' expressions, they will share the cached values. This is useful when using
#' `cache="app"`: there may be multiple user sessions which create separate
#' cached reactive objects (because they are created from the same code in the
#' server function, but the server function is executed once for each user
#' session), and those cached reactive objects across sessions can share
#' values in the cache.
#'
#' @section Async with cached reactives:
#'
#' With a cached reactive expression, the key and/or value expression can be
#' _asynchronous_. In other words, they can be promises --- not regular R
#' promises, but rather objects provided by the
#' \href{https://rstudio.github.io/promises/}{\pkg{promises}} package, which
#' are similar to promises in JavaScript. (See [promises::promise()] for more
#' information.) You can also use [mirai::mirai()] or [future::future()]
#' objects to run code in a separate process or even on a remote machine.
#'
#' If the value returns a promise, then anything that consumes the cached
#' reactive must expect it to return a promise.
#'
#' Similarly, if the key is a promise (in other words, if it is asynchronous),
#' then the entire cached reactive must be asynchronous, since the key must be
#' computed asynchronously before it knows whether to compute the value or the
#' value is retrieved from the cache. Anything that consumes the cached
#' reactive must therefore expect it to return a promise.
#'
#'
#' @section Developing render functions for caching:
#'
#' If you've implemented your own `render*()` function, it may just work with
#' `bindCache()`, but it is possible that you will need to make some
#' modifications. These modifications involve helping `bindCache()` avoid
#' cache collisions, dealing with internal state that may be set by the,
#' `render` function, and modifying the data as it goes in and comes out of
#' the cache.
#'
#' You may need to provide a `cacheHint` to [createRenderFunction()] (or
#' `htmlwidgets::shinyRenderWidget()`, if you've authored an htmlwidget) in
#' order for `bindCache()` to correctly compute a cache key.
#'
#' The potential problem is a cache collision. Consider the following:
#'
#' ```
#' output$x1 <- renderText({ input$x }) %>% bindCache(input$x)
#' output$x2 <- renderText({ input$x * 2 }) %>% bindCache(input$x)
#' ```
#'
#' Both `output$x1` and `output$x2` use `input$x` as part of their cache key,
#' but if it were the only thing used in the cache key, then the two outputs
#' would have a cache collision, and they would have the same output. To avoid
#' this, a _cache hint_ is automatically added when [renderText()] calls
#' [createRenderFunction()]. The cache hint is used as part of the actual
#' cache key, in addition to the one passed to `bindCache()` by the user. The
#' cache hint can be viewed by calling the internal Shiny function
#' `extractCacheHint()`:
#'
#' ```
#' r <- renderText({ input$x })
#' shiny:::extractCacheHint(r)
#' ```
#'
#' This returns a nested list containing an item, `$origUserFunc$body`, which
#' in this case is the expression which was passed to `renderText()`:
#' `{ input$x }`. This (quoted) expression is mixed into the actual cache
#' key, and it is how `output$x1` does not have collisions with `output$x2`.
#'
#' For most developers of render functions, nothing extra needs to be done;
#' the automatic inference of the cache hint is sufficient. Again, you can
#' check it by calling `shiny:::extractCacheHint()`, and by testing the
#' render function for cache collisions in a real application.
#'
#' In some cases, however, the automatic cache hint inference is not
#' sufficient, and it is necessary to provide a cache hint. This is true
#' for `renderPrint()`. Unlike `renderText()`, it wraps the user-provided
#' expression in another function, before passing it to [createRenderFunction()]
#' (instead of [createRenderFunction()]). Because the user code is wrapped in
#' another function, `createRenderFunction()` is not able to automatically
#' extract the user-provided code and use it in the cache key. Instead,
#' `renderPrint` calls `createRenderFunction()`, it explicitly passes along a
#' `cacheHint`, which includes a label and the original user expression.
#'
#' In general, if you need to provide a `cacheHint`, it is best practice to
#' provide a `label` id, the user's `expr`, as well as any other arguments
#' that may influence the final value.
#'
#' For \pkg{htmlwidgets}, it will try to automatically infer a cache hint;
#' again, you can inspect the cache hint with `shiny:::extractCacheHint()` and
#' also test it in an application. If you do need to explicitly provide a
#' cache hint, pass it to `shinyRenderWidget`. For example:
#'
#' ```
#' renderMyWidget <- function(expr) {
#' q <- rlang::enquo0(expr)
#'
#' htmlwidgets::shinyRenderWidget(
#' q,
#' myWidgetOutput,
#' quoted = TRUE,
#' cacheHint = list(label = "myWidget", userQuo = q)
#' )
#' }
#' ```
#'
#' If your `render` function sets any internal state, you may find it useful
#' in your call to [createRenderFunction()] to use
#' the `cacheWriteHook` and/or `cacheReadHook` parameters. These hooks are
#' functions that run just before the object is stored in the cache, and just
#' after the object is retrieved from the cache. They can modify the data
#' that is stored and retrieved; this can be useful if extra information needs
#' to be stored in the cache. They can also be used to modify the state of the
#' application; for example, it can call [createWebDependency()] to make
#' JS/CSS resources available if the cached object is loaded in a different R
#' process. (See the source of `htmlwidgets::shinyRenderWidget` for an example
#' of this.)
#'
#' @section Uncacheable objects:
#'
#' Some render functions cannot be cached, typically because they have side
#' effects or modify some external state, and they must re-execute each time
#' in order to work properly.
#'
#' For developers of such code, they should call [createRenderFunction()] (or
#' [markRenderFunction()]) with `cacheHint = FALSE`.
#'
#'
#' @section Caching with `renderPlot()`:
#'
#' When `bindCache()` is used with `renderPlot()`, the `height` and `width`
#' passed to the original `renderPlot()` are ignored. They are superseded by
#' `sizePolicy` argument passed to `bindCache. The default is:
#'
#' ```
#' sizePolicy = sizeGrowthRatio(width = 400, height = 400, growthRate = 1.2)
#' ```
#'
#' `sizePolicy` must be a function that takes a two-element numeric vector as
#' input, representing the width and height of the `<img>` element in the
#' browser window, and it must return a two-element numeric vector, representing
#' the pixel dimensions of the plot to generate. The purpose is to round the
#' actual pixel dimensions from the browser to some other dimensions, so that
#' this will not generate and cache images of every possible pixel dimension.
#' See [sizeGrowthRatio()] for more information on the default sizing policy.
#'
#' @param x The object to add caching to.
#' @param ... One or more expressions to use in the caching key.
#' @param cache The scope of the cache, or a cache object. This can be `"app"`
#' (the default), `"session"`, or a cache object like a
#' [cachem::cache_disk()]. See the Cache Scoping section for more information.
#'
#' @seealso [bindEvent()], [renderCachedPlot()] for caching plots.
#'
#' @examples
#' \dontrun{
#' rc <- bindCache(
#' x = reactive({
#' Sys.sleep(2) # Pretend this is expensive
#' input$x * 100
#' }),
#' input$x
#' )
#'
#' # Can make it prettier with the %>% operator
#' library(magrittr)
#'
#' rc <- reactive({
#' Sys.sleep(2)
#' input$x * 100
#' }) %>%
#' bindCache(input$x)
#'
#' }
#'
#' ## Only run app examples in interactive R sessions
#' if (interactive()) {
#'
#' # Basic example
#' shinyApp(
#' ui = fluidPage(
#' sliderInput("x", "x", 1, 10, 5),
#' sliderInput("y", "y", 1, 10, 5),
#' div("x * y: "),
#' verbatimTextOutput("txt")
#' ),
#' server = function(input, output) {
#' r <- reactive({
#' # The value expression is an _expensive_ computation
#' message("Doing expensive computation...")
#' Sys.sleep(2)
#' input$x * input$y
#' }) %>%
#' bindCache(input$x, input$y)
#'
#' output$txt <- renderText(r())
#' }
#' )
#'
#'
#' # Caching renderText
#' shinyApp(
#' ui = fluidPage(
#' sliderInput("x", "x", 1, 10, 5),
#' sliderInput("y", "y", 1, 10, 5),
#' div("x * y: "),
#' verbatimTextOutput("txt")
#' ),
#' server = function(input, output) {
#' output$txt <- renderText({
#' message("Doing expensive computation...")
#' Sys.sleep(2)
#' input$x * input$y
#' }) %>%
#' bindCache(input$x, input$y)
#' }
#' )
#'
#'
#' # Demo of using events and caching with an actionButton
#' shinyApp(
#' ui = fluidPage(
#' sliderInput("x", "x", 1, 10, 5),
#' sliderInput("y", "y", 1, 10, 5),
#' actionButton("go", "Go"),
#' div("x * y: "),
#' verbatimTextOutput("txt")
#' ),
#' server = function(input, output) {
#' r <- reactive({
#' message("Doing expensive computation...")
#' Sys.sleep(2)
#' input$x * input$y
#' }) %>%
#' bindCache(input$x, input$y) %>%
#' bindEvent(input$go)
#' # The cached, eventified reactive takes a reactive dependency on
#' # input$go, but doesn't use it for the cache key. It uses input$x and
#' # input$y for the cache key, but doesn't take a reactive dependency on
#' # them, because the reactive dependency is superseded by addEvent().
#'
#' output$txt <- renderText(r())
#' }
#' )
#'
#' }
#'
#' @export
bindCache <- function(x, ..., cache = "app") {
force(cache)
UseMethod("bindCache")
}
#' @export
bindCache.default <- function(x, ...) {
stop("Don't know how to handle object with class ", paste(class(x), collapse = ", "))
}
#' @export
bindCache.reactiveExpr <- function(x, ..., cache = "app") {
check_dots_unnamed()
call_srcref <- get_call_srcref(-1)
label <- rassignSrcrefToLabel(
call_srcref,
defaultLabel = exprToLabel(substitute(x), "cachedReactive")
)
domain <- reactive_get_domain(x)
# Convert the ... to a function that returns their evaluated values.
keyFunc <- quos_to_func(enquos0(...))
valueFunc <- reactive_get_value_func(x)
# Hash cache hint now -- this will be added to the key later on, to reduce the
# chance of key collisions with other cachedReactives.
cacheHint <- rlang::hash(extractCacheHint(x))
valueFunc <- wrapFunctionLabel(valueFunc, "cachedReactiveValueFunc", ..stacktraceon = TRUE)
x_classes <- class(x)
x_otel_attrs <- attr(x, "observable", exact = TRUE)$.otelAttrs
# Don't hold on to the reference for x, so that it can be GC'd
rm(x)
# Hacky workaround for issue with `%>%` preventing GC:
# https://github.com/tidyverse/magrittr/issues/229
if (exists(".GenericCallEnv") && exists(".", envir = .GenericCallEnv, inherits = FALSE)) {
rm(list = ".", envir = .GenericCallEnv, inherits = FALSE)
}
with_no_otel_collect({
res <- reactive(label = label, domain = domain, {
cache <- resolve_cache_object(cache, domain)
hybrid_chain(
keyFunc(),
generateCacheFun(valueFunc, cache, cacheHint, cacheReadHook = identity, cacheWriteHook = identity)
)
})
})
class(res) <- c("reactive.cache", class(res))
local({
impl <- attr(res, "observable", exact = TRUE)
impl$.otelAttrs <- append_otel_srcref_attrs(x_otel_attrs, call_srcref, fn_name = "bindCache")
})
if (has_otel_collect("reactivity")) {
res <- enable_otel_reactive_expr(res)
}
res
}
#' @export
bindCache.shiny.render.function <- function(x, ..., cache = "app") {
check_dots_unnamed()
keyFunc <- quos_to_func(enquos0(...))
cacheHint <- rlang::hash(extractCacheHint(x))
cacheWriteHook <- attr(x, "cacheWriteHook", exact = TRUE) %||% identity
cacheReadHook <- attr(x, "cacheReadHook", exact = TRUE) %||% identity
valueFunc <- x
renderFunc <- function(...) {
domain <- getDefaultReactiveDomain()
cache <- resolve_cache_object(cache, domain)
hybrid_chain(
keyFunc(),
generateCacheFun(valueFunc, cache, cacheHint, cacheReadHook, cacheWriteHook, ...)
)
}
# Passes over the otelAttrs from valueFunc to renderFunc
renderFunc <- addAttributes(renderFunc, renderFunctionAttributes(valueFunc))
class(renderFunc) <- c("shiny.render.function.cache", class(valueFunc))
renderFunc
}
#' @export
bindCache.shiny.renderPlot <- function(x, ...,
cache = "app",
sizePolicy = sizeGrowthRatio(width = 400, height = 400, growthRate = 1.2))
{
check_dots_unnamed()
valueFunc <- x
# Given the actual width/height of the image element in the browser, the
# resize observer computes the width/height using sizePolicy() and pushes
# those values into `fitWidth` and `fitHeight`. It's done this way so that the
# `fitWidth` and `fitHeight` only change (and cause invalidations of the key
# expression) when the rendered image size changes, and not every time the
# browser's <img> tag changes size.
#
# If the key expression were invalidated every time the image element changed
# size, even if the resulting key was the same (because `sizePolicy()` gave
# the same output for a slightly different img element size), it would result
# in getting the (same) image from the cache and sending it to the client
# again. This resize observer prevents that.
fitDims <- reactiveVal(NULL)
resizeObserverCreated <- FALSE
outputName <- NULL
ensureResizeObserver <- function() {
if (resizeObserverCreated)
return()
doResizeCheck <- function() {
if (is.null(outputName)) {
outputName <<- getCurrentOutputInfo()$name
}
session <- getDefaultReactiveDomain()
width <- session$clientData[[paste0('output_', outputName, '_width')]] %||% 0
height <- session$clientData[[paste0('output_', outputName, '_height')]] %||% 0
rect <- sizePolicy(c(width, height))
fitDims(list(width = rect[1], height = rect[2]))
}
# Run it once immediately, then set up the observer
isolate(doResizeCheck())
observe({
doResizeCheck()
}, label = "plot-resize")
# TODO: Make sure this observer gets GC'd if output$foo is replaced.
# Currently, if you reassign output$foo, the observer persists until the
# session ends. This is generally bad programming practice and should be
# rare, but still, we should try to clean up properly.
resizeObserverCreated <<- TRUE
}
renderFunc <- function(...) {
hybrid_chain(
# Pass in fitDims so that so that the generated plot will be the
# dimensions specified by the sizePolicy; otherwise the plot would be the
# exact dimensions of the img element, which isn't what we want for cached
# plots.
valueFunc(..., get_dims = fitDims),
function(img) {
# Replace exact pixel dimensions; instead, the max-height and max-width
# will be set to 100% from CSS.
img$class <- "shiny-scalable"
img$width <- NULL
img$height <- NULL
img
}
)
}
renderFunc <- addAttributes(renderFunc, renderFunctionAttributes(valueFunc))
class(renderFunc) <- class(valueFunc)
bindCache.shiny.render.function(
renderFunc,
...,
{
ensureResizeObserver()
session <- getDefaultReactiveDomain()
if (is.null(session) || is.null(fitDims())) {
req(FALSE)
}
pixelratio <- session$clientData$pixelratio %||% 1
list(fitDims(), pixelratio)
},
cache = cache
)
}
#' @export
bindCache.reactive.cache <- function(x, ...) {
stop("bindCache() has already been called on the object.")
}
#' @export
bindCache.shiny.render.function.cache <- bindCache.reactive.cache
#' @export
bindCache.reactive.event <- function(x, ...) {
stop("Can't call bindCache() after calling bindEvent() on an object. Maybe you wanted to call bindEvent() after bindCache()?")
}
#' @export
bindCache.shiny.render.function.event <- bindCache.reactive.event
#' @export
bindCache.Observer <- function(x, ...) {
stop("Can't bindCache an observer, because observers exist for the side efects, not for their return values.")
}
#' @export
bindCache.function <- function(x, ...) {
stop(
"Don't know how to add caching to a plain function. ",
"If this is a render* function for Shiny, it may need to be updated. ",
"Please see ?shiny::bindCache for more information."
)
}
# Returns a function which should be passed as a step in to hybrid_chain(). The
# returned function takes a cache key as input and manages storing and retrieving
# values from the cache, as well as executing the valueFunc if needed.
generateCacheFun <- function(
valueFunc,
cache,
cacheHint,
cacheReadHook,
cacheWriteHook,
...
) {
function(cacheKeyResult) {
key_str <- rlang::hash(list(cacheKeyResult, cacheHint))
res <- cache$get(key_str)
# Case 1: cache hit
if (!is.key_missing(res)) {
return(hybrid_chain(
{
# The first step is just to convert `res` to a promise or not, so
# that hybrid_chain() knows to propagate the promise-ness.
if (res$is_promise) promise_resolve(res)
else res
},
function(res) {
if (res$error) {
stop(res$value)
}
cacheReadHook(valueWithVisible(res))
}
))
}
# Case 2: cache miss
#
# valueFunc() might return a promise, or an actual value. Normally we'd
# use a hybrid_chain() for this, but in this case, we need to have
# different behavior if it's a promise or not a promise -- the
# information about whether or not it's a promise needs to be stored in
# the cache. We need to handle both cases and record in the cache
# whether it's a promise or not, so that any consumer of the
# cachedReactive() will be given the correct kind of object (a promise
# vs. an actual value) in the case of a future cache hit.
p <- withCallingHandlers(
withVisible(isolate(valueFunc(...))),
error = function(e) {
cache$set(key_str, list(
is_promise = FALSE,
value = e,
visible = TRUE,
error = TRUE
))
}
)
if (is.promising(p$value)) {
p$value <- as.promise(p$value)
p$value <- p$value$
then(function(value) {
res <- withVisible(value)
cache$set(key_str, list(
is_promise = TRUE,
value = cacheWriteHook(res$value),
visible = res$visible,
error = FALSE
))
valueWithVisible(res)
})$
catch(function(e) {
cache$set(key_str, list(
is_promise = TRUE,
value = e,
visible = TRUE,
error = TRUE
))
stop(e)
})
valueWithVisible(p)
} else {
# result is an ordinary value, not a promise.
cache$set(key_str, list(
is_promise = FALSE,
value = cacheWriteHook(p$value),
visible = p$visible,
error = FALSE
))
return(valueWithVisible(p))
}
}
}
extractCacheHint <- function(func) {
cacheHint <- attr(func, "cacheHint", exact = TRUE)
if (is_false(cacheHint)) {
stop(
"Cannot call `bindCache()` on this object because it is marked as not cacheable.",
call. = FALSE
)
}
if (is.null(cacheHint)) {
warning("No cacheHint found for this object. ",
"Caching may not work properly.")
}
cacheHint
}

360
R/bind-event.R Normal file
View File

@@ -0,0 +1,360 @@
#' Make an object respond only to specified reactive events
#'
#' @description
#'
#' Modify an object to respond to "event-like" reactive inputs, values, and
#' expressions. `bindEvent()` can be used with reactive expressions, render
#' functions, and observers. The resulting object takes a reactive dependency on
#' the `...` arguments, and not on the original object's code. This can, for
#' example, be used to make an observer execute only when a button is pressed.
#'
#' `bindEvent()` was added in Shiny 1.6.0. When it is used with [reactive()] and
#' [observe()], it does the same thing as [eventReactive()] and
#' [observeEvent()]. However, `bindEvent()` is more flexible: it can be combined
#' with [bindCache()], and it can also be used with `render` functions (like
#' [renderText()] and [renderPlot()]).
#'
#' @section Details:
#'
#' Shiny's reactive programming framework is primarily designed for calculated
#' values (reactive expressions) and side-effect-causing actions (observers)
#' that respond to *any* of their inputs changing. That's often what is
#' desired in Shiny apps, but not always: sometimes you want to wait for a
#' specific action to be taken from the user, like clicking an
#' [actionButton()], before calculating an expression or taking an action. A
#' reactive value or expression that is used to trigger other calculations in
#' this way is called an *event*.
#'
#' These situations demand a more imperative, "event handling" style of
#' programming that is possible--but not particularly intuitive--using the
#' reactive programming primitives [observe()] and [isolate()]. `bindEvent()`
#' provides a straightforward API for event handling that wraps `observe` and
#' `isolate`.
#'
#' The `...` arguments are captured as expressions and combined into an
#' **event expression**. When this event expression is invalidated (when its
#' upstream reactive inputs change), that is an **event**, and it will cause
#' the original object's code to execute.
#'
#' Use `bindEvent()` with `observe()` whenever you want to *perform an action*
#' in response to an event. (This does the same thing as [observeEvent()],
#' which was available in Shiny prior to version 1.6.0.) Note that
#' "recalculate a value" does not generally count as performing an action --
#' use [reactive()] for that.
#'
#' Use `bindEvent()` with `reactive()` to create a *calculated value* that
#' only updates in response to an event. This is just like a normal [reactive
#' expression][reactive] except it ignores all the usual invalidations that
#' come from its reactive dependencies; it only invalidates in response to the
#' given event. (This does the same thing as [eventReactive()], which was
#' available in Shiny prior to version 1.6.0.)
#'
#' `bindEvent()` is often used with [bindCache()].
#'
#' @section ignoreNULL and ignoreInit:
#'
#' `bindEvent()` takes an `ignoreNULL` parameter that affects behavior when
#' the event expression evaluates to `NULL` (or in the special case of an
#' [actionButton()], `0`). In these cases, if `ignoreNULL` is `TRUE`, then it
#' will raise a silent [validation][validate] error. This is useful behavior
#' if you don't want to do the action or calculation when your app first
#' starts, but wait for the user to initiate the action first (like a "Submit"
#' button); whereas `ignoreNULL=FALSE` is desirable if you want to initially
#' perform the action/calculation and just let the user re-initiate it (like a
#' "Recalculate" button).
#'
#' `bindEvent()` also takes an `ignoreInit` argument. By default, reactive
#' expressions and observers will run on the first reactive flush after they
#' are created (except if, at that moment, the event expression evaluates to
#' `NULL` and `ignoreNULL` is `TRUE`). But when responding to a click of an
#' action button, it may often be useful to set `ignoreInit` to `TRUE`. For
#' example, if you're setting up an observer to respond to a dynamically
#' created button, then `ignoreInit = TRUE` will guarantee that the action
#' will only be triggered when the button is actually clicked, instead of also
#' being triggered when it is created/initialized. Similarly, if you're
#' setting up a reactive that responds to a dynamically created button used to
#' refresh some data (which is then returned by that `reactive`), then you
#' should use `reactive(...) %>% bindEvent(..., ignoreInit = TRUE)` if you
#' want to let the user decide if/when they want to refresh the data (since,
#' depending on the app, this may be a computationally expensive operation).
#'
#' Even though `ignoreNULL` and `ignoreInit` can be used for similar purposes
#' they are independent from one another. Here's the result of combining
#' these:
#'
#' \describe{
#' \item{`ignoreNULL = TRUE` and `ignoreInit = FALSE`}{
#' This is the default. This combination means that reactive/observer code
#' will run every time that event expression is not
#' `NULL`. If, at the time of creation, the event expression happens
#' to *not* be `NULL`, then the code runs.
#' }
#' \item{`ignoreNULL = FALSE` and `ignoreInit = FALSE`}{
#' This combination means that reactive/observer code will
#' run every time no matter what.
#' }
#' \item{`ignoreNULL = FALSE` and `ignoreInit = TRUE`}{
#' This combination means that reactive/observer code will
#' *not* run at the time of creation (because `ignoreInit = TRUE`),
#' but it will run every other time.
#' }
#' \item{`ignoreNULL = TRUE` and `ignoreInit = TRUE`}{
#' This combination means that reactive/observer code will
#' *not* at the time of creation (because `ignoreInit = TRUE`).
#' After that, the reactive/observer code will run every time that
#' the event expression is not `NULL`.
#' }
#' }
#'
#' @section Types of objects:
#'
#' `bindEvent()` can be used with reactive expressions, observers, and shiny
#' render functions.
#'
#' When `bindEvent()` is used with `reactive()`, it creates a new reactive
#' expression object.
#'
#' When `bindEvent()` is used with `observe()`, it alters the observer in
#' place. It can only be used with observers which have not yet executed.
#'
#' @section Combining events and caching:
#'
#' In many cases, it makes sense to use `bindEvent()` along with
#' `bindCache()`, because they each can reduce the amount of work done on the
#' server. For example, you could have [sliderInput]s `x` and `y` and a
#' `reactive()` that performs a time-consuming operation with those values.
#' Using `bindCache()` can speed things up, especially if there are multiple
#' users. But it might make sense to also not do the computation until the
#' user sets both `x` and `y`, and then clicks on an [actionButton] named
#' `go`.
#'
#' To use both caching and events, the object should first be passed to
#' `bindCache()`, then `bindEvent()`. For example:
#'
#' ```
#' r <- reactive({
#' Sys.sleep(2) # Pretend this is an expensive computation
#' input$x * input$y
#' }) %>%
#' bindCache(input$x, input$y) %>%
#' bindEvent(input$go)
#' ```
#'
#' Anything that consumes `r()` will take a reactive dependency on the event
#' expression given to `bindEvent()`, and not the cache key expression given to
#' `bindCache()`. In this case, it is just `input$go`.
#'
#' @param x An object to wrap so that is triggered only when a the specified
#' event occurs.
#' @param ignoreNULL Whether the action should be triggered (or value
#' calculated) when the input is `NULL`. See Details.
#' @param ignoreInit If `TRUE`, then, when the eventified object is first
#' created/initialized, don't trigger the action or (compute the value). The
#' default is `FALSE`. See Details.
#' @param once Used only for observers. Whether this `observer` should be
#' immediately destroyed after the first time that the code in the observer is
#' run. This pattern is useful when you want to subscribe to a event that
#' should only happen once.
#' @param label A label for the observer or reactive, useful for debugging.
#' @param ... One or more expressions that represents the event; this can be a
#' simple reactive value like `input$click`, a call to a reactive expression
#' like `dataset()`, or even a complex expression inside curly braces. If
#' there are multiple expressions in the `...`, then it will take a dependency
#' on all of them.
#' @export
bindEvent <- function(x, ..., ignoreNULL = TRUE, ignoreInit = FALSE,
once = FALSE, label = NULL)
{
check_dots_unnamed()
force(ignoreNULL)
force(ignoreInit)
force(once)
UseMethod("bindEvent")
}
#' @export
bindEvent.default <- function(x, ...) {
stop("Don't know how to handle object with class ", paste(class(x), collapse = ", "))
}
#' @export
bindEvent.reactiveExpr <- function(x, ..., ignoreNULL = TRUE, ignoreInit = FALSE,
label = NULL)
{
domain <- reactive_get_domain(x)
qs <- enquos0(...)
eventFunc <- quos_to_func(qs)
valueFunc <- reactive_get_value_func(x)
valueFunc <- wrapFunctionLabel(valueFunc, "eventReactiveValueFunc", ..stacktraceon = TRUE)
call_srcref <- get_call_srcref(-1)
if (is.null(label)) {
label <- rassignSrcrefToLabel(
call_srcref,
defaultLabel = as_default_label(sprintf(
'bindEvent(%s, %s)',
attr(x, "observable", exact = TRUE)$.label,
quos_to_label(qs)
))
)
}
x_classes <- class(x)
x_otel_attrs <- attr(x, "observable", exact = TRUE)$.otelAttrs
# Don't hold on to the reference for x, so that it can be GC'd
rm(x)
initialized <- FALSE
with_no_otel_collect({
res <- reactive(label = label, domain = domain, ..stacktraceon = FALSE, {
hybrid_chain(
{
eventFunc()
},
function(value) {
if (ignoreInit && !initialized) {
initialized <<- TRUE
req(FALSE)
}
req(!ignoreNULL || !isNullEvent(value))
isolate(valueFunc())
}
)
})
})
class(res) <- c("reactive.event", x_classes)
local({
impl <- attr(res, "observable", exact = TRUE)
impl$.otelAttrs <- append_otel_srcref_attrs(x_otel_attrs, call_srcref, fn_name = "bindEvent")
})
if (has_otel_collect("reactivity")) {
res <- enable_otel_reactive_expr(res)
}
res
}
#' @export
bindEvent.shiny.render.function <- function(x, ..., ignoreNULL = TRUE, ignoreInit = FALSE) {
eventFunc <- quos_to_func(enquos0(...))
valueFunc <- x
initialized <- FALSE
renderFunc <- function(...) {
hybrid_chain(
eventFunc(),
function(value) {
if (ignoreInit && !initialized) {
initialized <<- TRUE
req(FALSE)
}
req(!ignoreNULL || !isNullEvent(value))
isolate(valueFunc(...))
}
)
}
# Passes over the otelAttrs from valueFunc to renderFunc
renderFunc <- addAttributes(renderFunc, renderFunctionAttributes(valueFunc))
class(renderFunc) <- c("shiny.render.function.event", class(valueFunc))
renderFunc
}
#' @export
bindEvent.Observer <- function(x, ..., ignoreNULL = TRUE, ignoreInit = FALSE,
once = FALSE, label = NULL)
{
if (x$.execCount > 0) {
stop("Cannot call bindEvent() on an Observer that has already been executed.")
}
qs <- enquos0(...)
eventFunc <- quos_to_func(qs)
valueFunc <- x$.func
# Note that because the observer will already have been logged by this point,
# this updated label won't show up in the reactlog.
if (is.null(label)) {
call_srcref <- get_call_srcref(-1)
x$.label <- rassignSrcrefToLabel(
call_srcref,
defaultLabel = as_default_label(
sprintf('bindEvent(%s, %s)', x$.label, quos_to_label(qs))
)
)
} else {
x$.label <- label
}
initialized <- FALSE
x$.func <- wrapFunctionLabel(
name = x$.label,
..stacktraceon = FALSE,
func = function() {
hybrid_chain(
eventFunc(),
function(value) {
if (ignoreInit && !initialized) {
initialized <<- TRUE
return()
}
if (ignoreNULL && isNullEvent(value)) {
return()
}
if (once) {
on.exit(x$destroy())
}
req(!ignoreNULL || !isNullEvent(value))
isolate(valueFunc())
}
)
}
)
class(x) <- c("Observer.event", class(x))
call_srcref <- get_call_srcref(-1)
x$.otelAttrs <- append_otel_srcref_attrs(x$.otelAttrs, call_srcref, fn_name = "bindEvent")
if (has_otel_collect("reactivity")) {
x <- enable_otel_observe(x)
}
invisible(x)
}
#' @export
bindEvent.reactive.event <- function(x, ...) {
stop("bindEvent() has already been called on the object.")
}
#' @export
bindEvent.Observer.event <- bindEvent.reactive.event

28
R/bookmark-state-local.R Normal file
View File

@@ -0,0 +1,28 @@
# Function wrappers for saving and restoring state to/from disk when running
# Shiny locally.
#
# These functions provide a directory to the callback function.
#
# @param id A session ID to save.
# @param callback A callback function that saves state to or restores state from
# a directory. It must take one argument, \code{stateDir}, which is a
# directory to which it writes/reads.
saveInterfaceLocal <- function(id, callback) {
# Try to save in app directory
appDir <- getShinyOption("appDir", default = getwd())
stateDir <- file.path(appDir, "shiny_bookmarks", id)
if (!dirExists(stateDir))
dir.create(stateDir, recursive = TRUE)
callback(stateDir)
}
loadInterfaceLocal <- function(id, callback) {
# Try to load from app directory
appDir <- getShinyOption("appDir", default = getwd())
stateDir <- file.path(appDir, "shiny_bookmarks", id)
callback(stateDir)
}

1230
R/bookmark-state.R Normal file

File diff suppressed because it is too large Load Diff

47
R/bootstrap-deprecated.R Normal file
View File

@@ -0,0 +1,47 @@
#' Create a page with a sidebar
#'
#' **DEPRECATED**: use [fluidPage()] and [sidebarLayout()] instead.
#'
#' @param headerPanel The [headerPanel] with the application title
#' @param sidebarPanel The [sidebarPanel] containing input controls
#' @param mainPanel The [mainPanel] containing outputs
#' @keywords internal
#' @return A UI definition that can be passed to the [shinyUI] function
#' @export
pageWithSidebar <- function(headerPanel,
sidebarPanel,
mainPanel) {
bootstrapPage(
# basic application container divs
div(
class="container-fluid",
div(class="row",
headerPanel
),
div(class="row",
sidebarPanel,
mainPanel
)
)
)
}
#' Create a header panel
#'
#' **DEPRECATED**: use [titlePanel()] instead.
#'
#' @param title An application title to display
#' @param windowTitle The title that should be displayed by the browser window.
#' Useful if `title` is not a string.
#' @return A headerPanel that can be passed to [pageWithSidebar]
#' @keywords internal
#' @export
headerPanel <- function(title, windowTitle=title) {
tagList(
tags$head(tags$title(windowTitle)),
div(class="col-sm-12",
h1(title)
)
)
}

691
R/bootstrap-layout.R Normal file
View File

@@ -0,0 +1,691 @@
#' Create a page with fluid layout
#'
#' Functions for creating fluid page layouts. A fluid page layout consists of
#' rows which in turn include columns. Rows exist for the purpose of making sure
#' their elements appear on the same line (if the browser has adequate width).
#' Columns exist for the purpose of defining how much horizontal space within a
#' 12-unit wide grid it's elements should occupy. Fluid pages scale their
#' components in realtime to fill all available browser width.
#'
#' @param ... Elements to include within the page
#' @param title The browser window title (defaults to the host URL of the page).
#' Can also be set as a side effect of the [titlePanel()] function.
#' @inheritParams bootstrapPage
#'
#' @return A UI definition that can be passed to the [shinyUI] function.
#'
#' @details To create a fluid page use the `fluidPage` function and include
#' instances of `fluidRow` and [column()] within it. As an
#' alternative to low-level row and column functions you can also use
#' higher-level layout functions like [sidebarLayout()].
#'
#' @note See the [
#' Shiny-Application-Layout-Guide](https://shiny.rstudio.com/articles/layout-guide.html) for additional details on laying out fluid
#' pages.
#'
#' @family layout functions
#' @seealso [column()]
#'
#' @examples
#' ## Only run examples in interactive R sessions
#' if (interactive()) {
#'
#' # Example of UI with fluidPage
#' ui <- fluidPage(
#'
#' # Application title
#' titlePanel("Hello Shiny!"),
#'
#' sidebarLayout(
#'
#' # Sidebar with a slider input
#' sidebarPanel(
#' sliderInput("obs",
#' "Number of observations:",
#' min = 0,
#' max = 1000,
#' value = 500)
#' ),
#'
#' # Show a plot of the generated distribution
#' mainPanel(
#' plotOutput("distPlot")
#' )
#' )
#' )
#'
#' # Server logic
#' server <- function(input, output) {
#' output$distPlot <- renderPlot({
#' hist(rnorm(input$obs))
#' })
#' }
#'
#' # Complete app with UI and server components
#' shinyApp(ui, server)
#'
#'
#' # UI demonstrating column layouts
#' ui <- fluidPage(
#' title = "Hello Shiny!",
#' fluidRow(
#' column(width = 4,
#' "4"
#' ),
#' column(width = 3, offset = 2,
#' "3 offset 2"
#' )
#' )
#' )
#'
#' shinyApp(ui, server = function(input, output) { })
#' }
#' @rdname fluidPage
#' @export
fluidPage <- function(..., title = NULL, theme = NULL, lang = NULL) {
bootstrapPage(div(class = "container-fluid", ...),
title = title,
theme = theme,
lang = lang)
}
#' @rdname fluidPage
#' @export
fluidRow <- function(...) {
div(class = "row", ...)
}
#' Create a page with a fixed layout
#'
#' Functions for creating fixed page layouts. A fixed page layout consists of
#' rows which in turn include columns. Rows exist for the purpose of making sure
#' their elements appear on the same line (if the browser has adequate width).
#' Columns exist for the purpose of defining how much horizontal space within a
#' 12-unit wide grid it's elements should occupy. Fixed pages limit their width
#' to 940 pixels on a typical display, and 724px or 1170px on smaller and larger
#' displays respectively.
#'
#' @param ... Elements to include within the container
#' @param title The browser window title (defaults to the host URL of the page)
#' @inheritParams bootstrapPage
#'
#' @return A UI definition that can be passed to the [shinyUI] function.
#'
#' @details To create a fixed page use the `fixedPage` function and include
#' instances of `fixedRow` and [column()] within it. Note that
#' unlike [fluidPage()], fixed pages cannot make use of higher-level
#' layout functions like `sidebarLayout`, rather, all layout must be done
#' with `fixedRow` and `column`.
#'
#' @note See the [
#' Shiny Application Layout Guide](https://shiny.rstudio.com/articles/layout-guide.html) for additional details on laying out fixed
#' pages.
#'
#' @family layout functions
#'
#' @seealso [column()]
#'
#' @examples
#' ## Only run examples in interactive R sessions
#' if (interactive()) {
#'
#' ui <- fixedPage(
#' title = "Hello, Shiny!",
#' fixedRow(
#' column(width = 4,
#' "4"
#' ),
#' column(width = 3, offset = 2,
#' "3 offset 2"
#' )
#' )
#' )
#'
#' shinyApp(ui, server = function(input, output) { })
#' }
#'
#' @rdname fixedPage
#' @export
fixedPage <- function(..., title = NULL, theme = NULL, lang = NULL) {
bootstrapPage(div(class = "container", ...),
title = title,
theme = theme,
lang = lang)
}
#' @rdname fixedPage
#' @export
fixedRow <- function(...) {
div(class = "row", ...)
}
#' Create a column within a UI definition
#'
#' Create a column for use within a [fluidRow()] or
#' [fixedRow()]
#'
#' @param width The grid width of the column (must be between 1 and 12)
#' @param ... Elements to include within the column
#' @param offset The number of columns to offset this column from the end of the
#' previous column.
#'
#' @return A column that can be included within a
#' [fluidRow()] or [fixedRow()].
#'
#'
#' @seealso [fluidRow()], [fixedRow()].
#'
#' @examples
#' ## Only run examples in interactive R sessions
#' if (interactive()) {
#'
#' ui <- fluidPage(
#' fluidRow(
#' column(4,
#' sliderInput("obs", "Number of observations:",
#' min = 1, max = 1000, value = 500)
#' ),
#' column(8,
#' plotOutput("distPlot")
#' )
#' )
#' )
#'
#' server <- function(input, output) {
#' output$distPlot <- renderPlot({
#' hist(rnorm(input$obs))
#' })
#' }
#'
#' shinyApp(ui, server)
#'
#'
#'
#' ui <- fluidPage(
#' fluidRow(
#' column(width = 4,
#' "4"
#' ),
#' column(width = 3, offset = 2,
#' "3 offset 2"
#' )
#' )
#' )
#' shinyApp(ui, server = function(input, output) { })
#' }
#' @export
column <- function(width, ..., offset = 0) {
if (!is.numeric(width) || (width < 1) || (width > 12))
stop("column width must be between 1 and 12")
colClass <- paste0("col-sm-", width)
if (offset > 0) {
# offset-md-x is for bootstrap 4 forward compat
# (every size tier has been bumped up one level)
# https://github.com/twbs/bootstrap/blob/74b8fe7/docs/4.3/migration/index.html#L659
colClass <- paste0(colClass, " offset-md-", offset, " col-sm-offset-", offset)
}
div(class = colClass, ...)
}
#' Create a panel containing an application title.
#'
#' @param title An application title to display
#' @param windowTitle The title that should be displayed by the browser window.
#'
#' @details Calling this function has the side effect of including a
#' `title` tag within the head. You can also specify a page title
#' explicitly using the `title` parameter of the top-level page function.
#'
#' @examples
#' ## Only run examples in interactive R sessions
#' if (interactive()) {
#'
#' ui <- fluidPage(
#' titlePanel("Hello Shiny!")
#' )
#' shinyApp(ui, server = function(input, output) { })
#' }
#' @export
titlePanel <- function(title, windowTitle=title) {
tagList(
tags$head(tags$title(windowTitle)),
h2(title)
)
}
#' Layout a sidebar and main area
#'
#' Create a layout (`sidebarLayout()`) with a sidebar (`sidebarPanel()`) and
#' main area (`mainPanel()`). The sidebar is displayed with a distinct
#' background color and typically contains input controls. The main
#' area occupies 2/3 of the horizontal width and typically contains outputs.
#'
#' @param sidebarPanel The `sidebarPanel()` containing input controls.
#' @param mainPanel The `mainPanel()` containing outputs.
#' @param position The position of the sidebar relative to the main area ("left"
#' or "right").
#' @param fluid `TRUE` to use fluid layout; `FALSE` to use fixed
#' layout.
#' @param width The width of the sidebar and main panel. By default, the
#' sidebar takes up 1/3 of the width, and the main panel 2/3. The total
#' width must be 12 or less.
#' @param ... Output elements to include in the sidebar/main panel.
#'
#' @family layout functions
#'
#' @examples
#' ## Only run examples in interactive R sessions
#' if (interactive()) {
#' options(device.ask.default = FALSE)
#'
#' # Define UI
#' ui <- fluidPage(
#'
#' # Application title
#' titlePanel("Hello Shiny!"),
#'
#' sidebarLayout(
#'
#' # Sidebar with a slider input
#' sidebarPanel(
#' sliderInput("obs",
#' "Number of observations:",
#' min = 0,
#' max = 1000,
#' value = 500)
#' ),
#'
#' # Show a plot of the generated distribution
#' mainPanel(
#' plotOutput("distPlot")
#' )
#' )
#' )
#'
#' # Server logic
#' server <- function(input, output) {
#' output$distPlot <- renderPlot({
#' hist(rnorm(input$obs))
#' })
#' }
#'
#' # Complete app with UI and server components
#' shinyApp(ui, server)
#' }
#' @export
sidebarLayout <- function(sidebarPanel,
mainPanel,
position = c("left", "right"),
fluid = TRUE) {
# determine the order
position <- match.arg(position)
if (position == "left") {
firstPanel <- sidebarPanel
secondPanel <- mainPanel
}
else if (position == "right") {
firstPanel <- mainPanel
secondPanel <- sidebarPanel
}
# return as as row
if (fluid)
fluidRow(firstPanel, secondPanel)
else
fixedRow(firstPanel, secondPanel)
}
#' @export
#' @rdname sidebarLayout
sidebarPanel <- function(..., width = 4) {
div(class=paste0("col-sm-", width),
tags$form(class="well",
# A11y semantic landmark for sidebar
role="complementary",
...
)
)
}
#' @export
#' @rdname sidebarLayout
mainPanel <- function(..., width = 8) {
div(class=paste0("col-sm-", width),
# A11y semantic landmark for main region
role="main",
...
)
}
#' Lay out UI elements vertically
#'
#' Create a container that includes one or more rows of content (each element
#' passed to the container will appear on it's own line in the UI)
#'
#' @param ... Elements to include within the container
#' @param fluid `TRUE` to use fluid layout; `FALSE` to use fixed
#' layout.
#'
#' @family layout functions
#'
#' @examples
#' ## Only run examples in interactive R sessions
#' if (interactive()) {
#'
#' ui <- fluidPage(
#' verticalLayout(
#' a(href="http://example.com/link1", "Link One"),
#' a(href="http://example.com/link2", "Link Two"),
#' a(href="http://example.com/link3", "Link Three")
#' )
#' )
#' shinyApp(ui, server = function(input, output) { })
#' }
#' @export
verticalLayout <- function(..., fluid = TRUE) {
lapply(list2(...), function(row) {
col <- column(12, row)
if (fluid)
fluidRow(col)
else
fixedRow(col)
})
}
#' Flow layout
#'
#' Lays out elements in a left-to-right, top-to-bottom arrangement. The elements
#' on a given row will be top-aligned with each other. This layout will not work
#' well with elements that have a percentage-based width (e.g.
#' [plotOutput()] at its default setting of `width = "100%"`).
#'
#' @param ... Unnamed arguments will become child elements of the layout. Named
#' arguments will become HTML attributes on the outermost tag.
#' @param cellArgs Any additional attributes that should be used for each cell
#' of the layout.
#'
#' @family layout functions
#'
#' @examples
#' ## Only run examples in interactive R sessions
#' if (interactive()) {
#'
#' ui <- flowLayout(
#' numericInput("rows", "How many rows?", 5),
#' selectInput("letter", "Which letter?", LETTERS),
#' sliderInput("value", "What value?", 0, 100, 50)
#' )
#' shinyApp(ui, server = function(input, output) { })
#' }
#' @export
flowLayout <- function(..., cellArgs = list()) {
children <- list2(...)
childIdx <- !nzchar(names(children) %||% character(length(children)))
attribs <- children[!childIdx]
children <- children[childIdx]
do.call(tags$div, c(list(class = "shiny-flow-layout"),
attribs,
lapply(children, function(x) {
do.call(tags$div, c(cellArgs, list(x)))
})
))
}
#' Input panel
#'
#' A [flowLayout()] with a grey border and light grey background,
#' suitable for wrapping inputs.
#'
#' @param ... Input controls or other HTML elements.
#' @export
inputPanel <- function(...) {
div(class = "shiny-input-panel",
flowLayout(...)
)
}
#' Split layout
#'
#' Lays out elements horizontally, dividing the available horizontal space into
#' equal parts (by default).
#'
#' @param ... Unnamed arguments will become child elements of the layout. Named
#' arguments will become HTML attributes on the outermost tag.
#' @param cellWidths Character or numeric vector indicating the widths of the
#' individual cells. Recycling will be used if needed. Character values will
#' be interpreted as CSS lengths (see [validateCssUnit()]), numeric
#' values as pixels.
#' @param cellArgs Any additional attributes that should be used for each cell
#' of the layout.
#'
#' @family layout functions
#'
#' @examples
#' ## Only run examples in interactive R sessions
#' if (interactive()) {
#' options(device.ask.default = FALSE)
#'
#' # Server code used for all examples
#' server <- function(input, output) {
#' output$plot1 <- renderPlot(plot(cars))
#' output$plot2 <- renderPlot(plot(pressure))
#' output$plot3 <- renderPlot(plot(AirPassengers))
#' }
#'
#' # Equal sizing
#' ui <- splitLayout(
#' plotOutput("plot1"),
#' plotOutput("plot2")
#' )
#' shinyApp(ui, server)
#'
#' # Custom widths
#' ui <- splitLayout(cellWidths = c("25%", "75%"),
#' plotOutput("plot1"),
#' plotOutput("plot2")
#' )
#' shinyApp(ui, server)
#'
#' # All cells at 300 pixels wide, with cell padding
#' # and a border around everything
#' ui <- splitLayout(
#' style = "border: 1px solid silver;",
#' cellWidths = 300,
#' cellArgs = list(style = "padding: 6px"),
#' plotOutput("plot1"),
#' plotOutput("plot2"),
#' plotOutput("plot3")
#' )
#' shinyApp(ui, server)
#' }
#' @export
splitLayout <- function(..., cellWidths = NULL, cellArgs = list()) {
children <- list2(...)
childIdx <- !nzchar(names(children) %||% character(length(children)))
attribs <- children[!childIdx]
children <- children[childIdx]
count <- length(children)
if (length(cellWidths) == 0 || isTRUE(is.na(cellWidths))) {
cellWidths <- sprintf("%.3f%%", 100 / count)
}
cellWidths <- rep(cellWidths, length.out = count)
cellWidths <- sapply(cellWidths, validateCssUnit)
do.call(tags$div, c(list(class = "shiny-split-layout"),
attribs,
mapply(children, cellWidths, FUN = function(x, w) {
do.call(tags$div, c(
list(style = sprintf("width: %s;", w)),
cellArgs,
list(x)
))
}, SIMPLIFY = FALSE)
))
}
#' Flex Box-based row/column layouts
#'
#' Creates row and column layouts with proportionally-sized cells, using the
#' Flex Box layout model of CSS3. These can be nested to create arbitrary
#' proportional-grid layouts. **Warning:** Flex Box is not well supported
#' by Internet Explorer, so these functions should only be used where modern
#' browsers can be assumed.
#'
#' @details If you try to use `fillRow` and `fillCol` inside of other
#' Shiny containers, such as [sidebarLayout()],
#' [navbarPage()], or even `tags$div`, you will probably find
#' that they will not appear. This is due to `fillRow` and `fillCol`
#' defaulting to `height="100%"`, which will only work inside of
#' containers that have determined their own size (rather than shrinking to
#' the size of their contents, as is usually the case in HTML).
#'
#' To avoid this problem, you have two options:
#' \itemize{
#' \item only use `fillRow`/`fillCol` inside of `fillPage`,
#' `fillRow`, or `fillCol`
#' \item provide an explicit `height` argument to
#' `fillRow`/`fillCol`
#' }
#'
#' @param ... UI objects to put in each row/column cell; each argument will
#' occupy a single cell. (To put multiple items in a single cell, you can use
#' [tagList()] or [div()] to combine them.) Named
#' arguments will be used as attributes on the `div` element that
#' encapsulates the row/column.
#' @param flex Determines how space should be distributed to the cells. Can be a
#' single value like `1` or `2` to evenly distribute the available
#' space; or use a vector of numbers to specify the proportions. For example,
#' `flex = c(2, 3)` would cause the space to be split 40%/60% between
#' two cells. NA values will cause the corresponding cell to be sized
#' according to its contents (without growing or shrinking).
#' @param width,height The total amount of width and height to use for the
#' entire row/column. For the default height of `"100%"` to be
#' effective, the parent must be `fillPage`, another
#' `fillRow`/`fillCol`, or some other HTML element whose height is
#' not determined by the height of its contents.
#'
#' @examples
#' # Only run this example in interactive R sessions.
#' if (interactive()) {
#'
#' ui <- fillPage(fillRow(
#' plotOutput("plotLeft", height = "100%"),
#' fillCol(
#' plotOutput("plotTopRight", height = "100%"),
#' plotOutput("plotBottomRight", height = "100%")
#' )
#' ))
#'
#' server <- function(input, output, session) {
#' output$plotLeft <- renderPlot(plot(cars))
#' output$plotTopRight <- renderPlot(plot(pressure))
#' output$plotBottomRight <- renderPlot(plot(AirPassengers))
#' }
#'
#' shinyApp(ui, server)
#'
#' }
#' @export
fillRow <- function(..., flex = 1, width = "100%", height = "100%") {
flexfill(..., direction = "row", flex = flex, width = width, height = height)
}
#' @rdname fillRow
#' @export
fillCol <- function(..., flex = 1, width = "100%", height = "100%") {
flexfill(..., direction = "column", flex = flex, width = width, height = height)
}
flexfill <- function(..., direction, flex, width = width, height = height) {
children <- list2(...)
attrs <- list()
if (!is.null(names(children))) {
attrs <- children[names(children) != ""]
children <- children[names(children) == ""]
}
if (length(flex) > length(children)) {
flex <- flex[seq_along(children)]
}
# The dimension along the main axis
main <- switch(direction,
row = "width",
"row-reverse" = "width",
column = "height",
"column-reverse" = "height",
stop("Unexpected direction")
)
# The dimension along the cross axis
cross <- if (main == "width") "height" else "width"
divArgs <- list(
class = sprintf("flexfill-container flexfill-container-%s", direction),
style = css(
display = "-webkit-flex",
display = "-ms-flexbox",
display = "flex",
.webkit.flex.direction = direction,
.ms.flex.direction = direction,
flex.direction = direction,
width = validateCssUnit(width),
height = validateCssUnit(height)
),
mapply(children, flex, FUN = function(el, flexValue) {
if (is.na(flexValue)) {
# If the flex value is NA, then put the element in a simple flex item
# that sizes itself (along the main axis) to its contents
tags$div(
class = "flexfill-item",
style = css(
position = "relative",
"-webkit-flex" = "none",
"-ms-flex" = "none",
flex = "none"
),
style = paste0(main, ":auto;", cross, ":100%;"),
el
)
} else if (is.numeric(flexValue)) {
# If the flex value is numeric, we need *two* wrapper divs. The outer is
# the flex item, and the inner is an absolute-fill div that is needed to
# make percentage-based sizing for el work correctly. I don't understand
# why this is needed but the truth is probably in this SO page:
# http://stackoverflow.com/questions/15381172/css-flexbox-child-height-100
tags$div(
class = "flexfill-item",
style = css(
position = "relative",
"-webkit-flex" = flexValue,
"-ms-flex" = flexValue,
flex = flexValue,
width = "100%", height = "100%"
),
tags$div(
class = "flexfill-item-inner",
style = css(
position = "absolute",
top = 0, left = 0, right = 0, bottom = 0
),
el
)
)
} else {
stop("Unexpected flex argument: ", flexValue)
}
}, SIMPLIFY = FALSE, USE.NAMES = FALSE)
)
do.call(tags$div, c(attrs, divArgs))
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,4 @@
# Generated by tools/updateSpinnerTypes.R: do not edit by hand
.busySpinnerTypes <-
c("ring", "ring2", "ring3", "bars", "bars2", "bars3", "pulse",
"pulse2", "pulse3", "dots", "dots2", "dots3")

294
R/busy-indicators.R Normal file
View File

@@ -0,0 +1,294 @@
#' Enable/disable busy indication
#'
#' Busy indicators provide a visual cue to users when the server is busy
#' calculating outputs or otherwise performing tasks (e.g., producing
#' downloads). When enabled, a spinner is shown on each
#' calculating/recalculating output, and a pulsing banner is shown at the top of
#' the page when the app is otherwise busy. Busy indication is enabled by
#' default for UI created with \pkg{bslib}, but must be enabled otherwise. To
#' enable/disable, include the result of this function in anywhere in the app's
#' UI.
#'
#' When both `spinners` and `pulse` are set to `TRUE`, the pulse is
#' automatically disabled when spinner(s) are active. When both `spinners` and
#' `pulse` are set to `FALSE`, no busy indication is shown (other than the
#' graying out of recalculating outputs).
#'
#' @param ... Currently ignored.
#' @param spinners Whether to show a spinner on each calculating/recalculating
#' output.
#' @param pulse Whether to show a pulsing banner at the top of the page when the
#' app is busy.
#' @param fade Whether to fade recalculating outputs. A value of `FALSE` is
#' equivalent to `busyIndicatorOptions(fade_opacity=1)`.
#'
#' @export
#' @seealso [busyIndicatorOptions()] for customizing the appearance of the busy
#' indicators.
#' @examplesIf rlang::is_interactive()
#'
#' library(bslib)
#'
#' ui <- page_fillable(
#' useBusyIndicators(),
#' card(
#' card_header(
#' "A plot",
#' input_task_button("simulate", "Simulate"),
#' class = "d-flex justify-content-between align-items-center"
#' ),
#' plotOutput("p"),
#' )
#' )
#'
#' server <- function(input, output) {
#' output$p <- renderPlot({
#' input$simulate
#' Sys.sleep(4)
#' plot(x = rnorm(100), y = rnorm(100))
#' })
#' }
#'
#' shinyApp(ui, server)
useBusyIndicators <- function(..., spinners = TRUE, pulse = TRUE, fade = TRUE) {
rlang::check_dots_empty()
attrs <- list("shinyBusySpinners" = spinners, "shinyBusyPulse" = pulse)
js <- vapply(names(attrs), character(1), FUN = function(key) {
if (attrs[[key]]) {
sprintf("document.documentElement.dataset.%s = 'true';", key)
} else {
sprintf("delete document.documentElement.dataset.%s;", key)
}
})
# TODO: it'd be nice if htmltools had something like a page_attrs() that allowed us
# to do this without needing to inject JS into the head.
res <- tags$script(HTML(paste(js, collapse = "\n")))
if (!fade) {
res <- tagList(res, fadeOptions(opacity = 1))
}
res
}
#' Customize busy indicator options
#'
#' @description
#' Shiny automatically includes busy indicators, which more specifically means:
#' 1. Calculating/recalculating outputs have a spinner overlay.
#' 2. Outputs fade out/in when recalculating.
#' 3. When no outputs are calculating/recalculating, but Shiny is busy
#' doing something else (e.g., a download, side-effect, etc), a page-level
#' pulsing banner is shown.
#'
#' This function allows you to customize the appearance of these busy indicators
#' by including the result of this function inside the app's UI. Note that,
#' unless `spinner_selector` (or `fade_selector`) is specified, the spinner/fade
#' customization applies to the parent element. If the customization should
#' instead apply to the entire page, set `spinner_selector = 'html'` and
#' `fade_selector = 'html'`.
#'
#' @param ... Currently ignored.
#' @param spinner_type The type of spinner. Pre-bundled types include:
#' '`r paste0(.busySpinnerTypes, collapse = "', '")`'.
#'
#' A path to a local SVG file can also be provided. The SVG should adhere to
#' the following rules:
#' * The SVG itself should contain the animation.
#' * It should avoid absolute sizes (the spinner's containing DOM element
#' size is set in CSS by `spinner_size`, so it should fill that container).
#' * It should avoid setting absolute colors (the spinner's containing DOM element
#' color is set in CSS by `spinner_color`, so it should inherit that color).
#' @param spinner_color The color of the spinner. This can be any valid CSS
#' color. Defaults to the app's "primary" color if Bootstrap is on the page.
#' @param spinner_size The size of the spinner. This can be any valid CSS size.
#' @param spinner_delay The amount of time to wait before showing the spinner.
#' This can be any valid CSS time and can be useful for not showing the spinner
#' if the computation finishes quickly.
#' @param spinner_selector A character string containing a CSS selector for
#' scoping the spinner customization. The default (`NULL`) will apply the
#' spinner customization to the parent element of the spinner.
#' @param fade_opacity The opacity (a number between 0 and 1) for recalculating
#' output. Set to 1 to "disable" the fade.
#' @param fade_selector A character string containing a CSS selector for
#' scoping the spinner customization. The default (`NULL`) will apply the
#' spinner customization to the parent element of the spinner.
#' @param pulse_background A CSS background definition for the pulse. The
#' default uses a
#' [linear-gradient](https://developer.mozilla.org/en-US/docs/Web/CSS/gradient/linear-gradient)
#' of the theme's indigo, purple, and pink colors.
#' @param pulse_height The height of the pulsing banner. This can be any valid
#' CSS size.
#' @param pulse_speed The speed of the pulsing banner. This can be any valid CSS
#' time.
#'
#' @export
#' @seealso [useBusyIndicators()] to disable/enable busy indicators.
#' @examplesIf rlang::is_interactive()
#'
#' library(bslib)
#'
#' card_ui <- function(id, spinner_type = id) {
#' card(
#' busyIndicatorOptions(spinner_type = spinner_type),
#' card_header(paste("Spinner:", spinner_type)),
#' plotOutput(shiny::NS(id, "plot"))
#' )
#' }
#'
#' card_server <- function(id, simulate = reactive()) {
#' moduleServer(
#' id = id,
#' function(input, output, session) {
#' output$plot <- renderPlot({
#' Sys.sleep(1)
#' simulate()
#' plot(x = rnorm(100), y = rnorm(100))
#' })
#' }
#' )
#' }
#'
#' ui <- page_fillable(
#' useBusyIndicators(),
#' input_task_button("simulate", "Simulate", icon = icon("refresh")),
#' layout_columns(
#' card_ui("ring"),
#' card_ui("bars"),
#' card_ui("dots"),
#' card_ui("pulse"),
#' col_widths = 6
#' )
#' )
#'
#' server <- function(input, output, session) {
#' simulate <- reactive(input$simulate)
#' card_server("ring", simulate)
#' card_server("bars", simulate)
#' card_server("dots", simulate)
#' card_server("pulse", simulate)
#' }
#'
#' shinyApp(ui, server)
#'
busyIndicatorOptions <- function(
...,
spinner_type = NULL,
spinner_color = NULL,
spinner_size = NULL,
spinner_delay = NULL,
spinner_selector = NULL,
fade_opacity = NULL,
fade_selector = NULL,
pulse_background = NULL,
pulse_height = NULL,
pulse_speed = NULL
) {
rlang::check_dots_empty()
res <- tagList(
spinnerOptions(
type = spinner_type,
color = spinner_color,
size = spinner_size,
delay = spinner_delay,
selector = spinner_selector
),
fadeOptions(opacity = fade_opacity, selector = fade_selector),
pulseOptions(
background = pulse_background,
height = pulse_height,
speed = pulse_speed
)
)
bslib::as.card_item(dropNulls(res))
}
spinnerOptions <- function(type = NULL, color = NULL, size = NULL, delay = NULL, selector = NULL) {
if (is.null(type) && is.null(color) && is.null(size) && is.null(delay) && is.null(selector)) {
return(NULL)
}
url <- NULL
if (!is.null(type)) {
stopifnot(is.character(type) && length(type) == 1)
if (file.exists(type) && grepl("\\.svg$", type)) {
typeRaw <- readBin(type, "raw", n = file.info(type)$size)
url <- sprintf("url('data:image/svg+xml;base64,%s')", rawToBase64(typeRaw))
} else {
type <- rlang::arg_match(type, .busySpinnerTypes)
url <- sprintf("url('spinners/%s.svg')", type)
}
}
# Options controlled via CSS variables.
css_vars <- htmltools::css(
"--shiny-spinner-url" = url,
"--shiny-spinner-color" = htmltools::parseCssColors(color),
"--shiny-spinner-size" = htmltools::validateCssUnit(size),
"--shiny-spinner-delay" = delay
)
id <- NULL
if (is.null(selector)) {
id <- paste0("spinner-options-", p_randomInt(100, 1000000))
selector <- sprintf(":has(> #%s)", id)
}
css <- HTML(paste0(selector, " {", css_vars, "}"))
tags$style(css, id = id)
}
fadeOptions <- function(opacity = NULL, selector = NULL) {
if (is.null(opacity) && is.null(selector)) {
return(NULL)
}
css_vars <- htmltools::css(
"--shiny-fade-opacity" = opacity
)
id <- NULL
if (is.null(selector)) {
id <- paste0("fade-options-", p_randomInt(100, 1000000))
selector <- sprintf(":has(> #%s)", id)
}
css <- HTML(paste0(selector, " {", css_vars, "}"))
tags$style(css, id = id)
}
pulseOptions <- function(background = NULL, height = NULL, speed = NULL) {
if (is.null(background) && is.null(height) && is.null(speed)) {
return(NULL)
}
css_vars <- htmltools::css(
"--shiny-pulse-background" = background,
"--shiny-pulse-height" = htmltools::validateCssUnit(height),
"--shiny-pulse-speed" = speed
)
tags$style(HTML(paste0(":root {", css_vars, "}")))
}
busyIndicatorDependency <- function() {
htmlDependency(
name = "shiny-busy-indicators",
version = get_package_version("shiny"),
src = "www/shared/busy-indicators",
package = "shiny",
stylesheet = "busy-indicators.css",
# TODO-future: In next release make spinners and pulse opt-out
# head = as.character(useBusyIndicators())
)
}

25
R/cache-utils.R Normal file
View File

@@ -0,0 +1,25 @@
# For our purposes, cache objects must support these methods.
is_cache_object <- function(x) {
# Use tryCatch in case the object does not support `$`.
tryCatch(
is.function(x$get) && is.function(x$set),
error = function(e) FALSE
)
}
# Given a cache object, or string "app" or "session", return appropriate cache
# object.
resolve_cache_object <- function(cache, session) {
if (identical(cache, "app")) {
cache <- getShinyOption("cache", default = NULL)
} else if (identical(cache, "session")) {
cache <- session$cache
}
if (is_cache_object(cache)) {
return(cache)
}
stop('`cache` must either be "app", "session", or a cache object with methods, `$get`, and `$set`.')
}

View File

@@ -1,80 +0,0 @@
# A context object for tracking a cache that needs to be dirtied when a set of
# files changes on disk. Each time the cache is dirtied, the set of files is
# cleared. Therefore, the set of files needs to be re-built each time the cached
# code executes. This approach allows for dynamic dependency graphs.
CacheContext <- setRefClass(
'CacheContext',
fields = list(
.dirty = 'logical',
.tests = 'list'
),
methods = list(
initialize = function() {
.dirty <<- TRUE
# List of functions that return TRUE if dirty
.tests <<- list()
},
addDependencyFile = function(file) {
if (.dirty)
return()
file <- normalizePath(file)
mtime <- file.info(file)$mtime
.tests <<- c(.tests, function() {
newMtime <- try(file.info(file)$mtime, silent=TRUE)
if (is(newMtime, 'try-error'))
return(TRUE)
return(!identical(mtime, newMtime))
})
invisible()
},
forceDirty = function() {
.dirty <<- TRUE
.tests <<- list()
invisible()
},
isDirty = function() {
if (.dirty)
return(TRUE)
for (test in .tests) {
if (test()) {
forceDirty()
return(TRUE)
}
}
return(FALSE)
},
reset = function() {
.dirty <<- FALSE
.tests <<- list()
},
with = function(func) {
oldCC <- .currentCacheContext$cc
.currentCacheContext$cc <- .self
on.exit(.currentCacheContext$cc <- oldCC)
return(func())
}
)
)
.currentCacheContext <- new.env()
# Indicates to Shiny that the given file path is part of the dependency graph
# for whatever is currently executing (so far, only ui.R). By default, ui.R only
# gets re-executed when it is detected to have changed; this function allows the
# caller to indicate that it should also re-execute if the given file changes.
#
# If NULL or NA is given as the argument, then ui.R will re-execute next time.
dependsOnFile <- function(filepath) {
if (is.null(.currentCacheContext$cc))
stop("addFileDependency was called at an unexpected time (no cache context found)")
if (is.null(filepath) || is.na(filepath))
.currentCacheContext$cc$forceDirty()
else
.currentCacheContext$cc$addDependencyFile(filepath)
}

637
R/conditions.R Normal file
View File

@@ -0,0 +1,637 @@
#' Stack trace manipulation functions
#'
#' Advanced (borderline internal) functions for capturing, printing, and
#' manipulating stack traces.
#'
#' @return `printError` and `printStackTrace` return
#' `invisible()`. The other functions pass through the results of
#' `expr`.
#'
#' @examples
#' # Keeps tryCatch and withVisible related calls off the
#' # pretty-printed stack trace
#'
#' visibleFunction1 <- function() {
#' stop("Kaboom!")
#' }
#'
#' visibleFunction2 <- function() {
#' visibleFunction1()
#' }
#'
#' hiddenFunction <- function(expr) {
#' expr
#' }
#'
#' # An example without ..stacktraceon/off.. manipulation.
#' # The outer "try" is just to prevent example() from stopping.
#' try({
#' # The withLogErrors call ensures that stack traces are captured
#' # and that errors that bubble up are logged using warning().
#' withLogErrors({
#' # tryCatch and withVisible are just here to add some noise to
#' # the stack trace.
#' tryCatch(
#' withVisible({
#' hiddenFunction(visibleFunction2())
#' })
#' )
#' })
#' })
#'
#' # Now the same example, but with ..stacktraceon/off.. to hide some
#' # of the less-interesting bits (tryCatch and withVisible).
#' ..stacktraceoff..({
#' try({
#' withLogErrors({
#' tryCatch(
#' withVisible(
#' hiddenFunction(
#' ..stacktraceon..(visibleFunction2())
#' )
#' )
#' )
#' })
#' })
#' })
#'
#'
#' @name stacktrace
#' @rdname stacktrace
#' @keywords internal
NULL
getCallNames <- function(calls) {
sapply(calls, function(call) {
if (is.function(call[[1]])) {
"<Anonymous>"
} else if (inherits(call[[1]], "call")) {
paste0(format(call[[1]]), collapse = " ")
} else if (typeof(call[[1]]) == "promise") {
"<Promise>"
} else {
paste0(as.character(call[[1]]), collapse = " ")
}
})
}
# A stripped down version of getCallNames() that intentionally avoids deparsing expressions.
# Instead, it leaves expressions to be directly `rlang::hash()` (for de-duplication), which
# is much faster than deparsing then hashing.
getCallNamesForHash <- function(calls) {
lapply(calls, function(call) {
name <- call[[1L]]
if (is.function(name)) return("<Anonymous>")
if (typeof(name) == "promise") return("<Promise>")
name
})
}
getLocs <- function(calls) {
vapply(calls, function(call) {
srcref <- attr(call, "srcref", exact = TRUE)
if (!is.null(srcref)) {
srcfile <- attr(srcref, "srcfile", exact = TRUE)
if (!is.null(srcfile) && !is.null(srcfile$filename)) {
loc <- paste0(srcfile$filename, "#", srcref[[1]])
return(paste0(" [", loc, "]"))
}
}
return("")
}, character(1))
}
getCallCategories <- function(calls) {
vapply(calls, function(call) {
srcref <- attr(call, "srcref", exact = TRUE)
if (!is.null(srcref)) {
srcfile <- attr(srcref, "srcfile", exact = TRUE)
if (!is.null(srcfile)) {
if (!is.null(srcfile$original)) {
return("pkg")
} else {
return("user")
}
}
}
return("")
}, character(1))
}
#' @details `captureStackTraces` runs the given `expr` and if any
#' *uncaught* errors occur, annotates them with stack trace info for use
#' by `printError` and `printStackTrace`. It is not necessary to use
#' `captureStackTraces` around the same expression as
#' `withLogErrors`, as the latter includes a call to the former. Note
#' that if `expr` contains calls (either directly or indirectly) to
#' `try`, or `tryCatch` with an error handler, stack traces therein
#' cannot be captured unless another `captureStackTraces` call is
#' inserted in the interior of the `try` or `tryCatch`. This is
#' because these calls catch the error and prevent it from traveling up to the
#' condition handler installed by `captureStackTraces`.
#'
#' @param expr The expression to wrap.
#' @rdname stacktrace
#' @export
captureStackTraces <- function(expr) {
# Use `promises::` as it shows up in the stack trace
promises::with_promise_domain(
createStackTracePromiseDomain(),
expr
)
}
#' @include globals.R
.globals$deepStack <- NULL
getCallStackDigest <- function(callStack, warn = FALSE) {
dg <- attr(callStack, "shiny.stack.digest", exact = TRUE)
if (!is.null(dg)) {
return(dg)
}
if (isTRUE(warn)) {
rlang::warn(
"Call stack doesn't have a cached digest; expensively computing one now",
.frequency = "once",
.frequency_id = "deepstack-uncached-digest-warning"
)
}
rlang::hash(getCallNamesForHash(callStack))
}
saveCallStackDigest <- function(callStack) {
attr(callStack, "shiny.stack.digest") <- getCallStackDigest(callStack, warn = FALSE)
callStack
}
# Appends a call stack to a list of call stacks, but only if it's not already
# in the list. The list is deduplicated by digest; ideally the digests on the
# list are cached before calling this function (you will get a warning if not).
appendCallStackWithDedupe <- function(lst, x) {
digests <- vapply(lst, getCallStackDigest, character(1), warn = TRUE)
xdigest <- getCallStackDigest(x, warn = TRUE)
stopifnot(all(nzchar(digests)))
stopifnot(length(xdigest) == 1)
stopifnot(nzchar(xdigest))
if (xdigest %in% digests) {
return(lst)
} else {
return(c(lst, list(x)))
}
}
createStackTracePromiseDomain <- function() {
# These are actually stateless, we wouldn't have to create a new one each time
# if we didn't want to. They're pretty cheap though.
d <- new_promise_domain(
wrapOnFulfilled = function(onFulfilled) {
force(onFulfilled)
# Subscription time
if (deepStacksEnabled()) {
currentStack <- sys.calls()
currentParents <- sys.parents()
attr(currentStack, "parents") <- currentParents
currentStack <- saveCallStackDigest(currentStack)
currentDeepStack <- .globals$deepStack
}
function(...) {
# Fulfill time
if (deepStacksEnabled()) {
origDeepStack <- .globals$deepStack
.globals$deepStack <- appendCallStackWithDedupe(currentDeepStack, currentStack)
on.exit(.globals$deepStack <- origDeepStack, add = TRUE)
}
withCallingHandlers(
onFulfilled(...),
error = doCaptureStack
)
}
},
wrapOnRejected = function(onRejected) {
force(onRejected)
# Subscription time
if (deepStacksEnabled()) {
currentStack <- sys.calls()
currentParents <- sys.parents()
attr(currentStack, "parents") <- currentParents
currentStack <- saveCallStackDigest(currentStack)
currentDeepStack <- .globals$deepStack
}
function(...) {
# Fulfill time
if (deepStacksEnabled()) {
origDeepStack <- .globals$deepStack
.globals$deepStack <- appendCallStackWithDedupe(currentDeepStack, currentStack)
on.exit(.globals$deepStack <- origDeepStack, add = TRUE)
}
withCallingHandlers(
onRejected(...),
error = doCaptureStack
)
}
},
wrapSync = function(expr) {
withCallingHandlers(expr,
error = doCaptureStack
)
},
onError = doCaptureStack
)
}
deepStacksEnabled <- function() {
getOption("shiny.deepstacktrace", TRUE)
}
doCaptureStack <- function(e) {
if (is.null(attr(e, "stack.trace", exact = TRUE))) {
calls <- sys.calls()
parents <- sys.parents()
attr(calls, "parents") <- parents
calls <- saveCallStackDigest(calls)
attr(e, "stack.trace") <- calls
}
if (deepStacksEnabled()) {
if (is.null(attr(e, "deep.stack.trace", exact = TRUE)) && !is.null(.globals$deepStack)) {
attr(e, "deep.stack.trace") <- .globals$deepStack
}
}
stop(e)
}
#' @details `withLogErrors` captures stack traces and logs errors that
#' occur in `expr`, but does allow errors to propagate beyond this point
#' (i.e. it doesn't catch the error). The same caveats that apply to
#' `captureStackTraces` with regard to `try`/`tryCatch` apply
#' to `withLogErrors`.
#' @rdname stacktrace
#' @export
withLogErrors <- function(expr,
full = get_devmode_option("shiny.fullstacktrace", FALSE),
offset = getOption("shiny.stacktraceoffset", TRUE)) {
withCallingHandlers(
{
result <- captureStackTraces(expr)
# Handle expr being an async operation
if (is.promise(result)) {
result <- promises::catch(result, function(cond) {
# Don't print shiny.silent.error (i.e. validation errors)
if (cnd_inherits(cond, "shiny.silent.error")) {
return()
}
if (isTRUE(getOption("show.error.messages"))) {
printError(cond, full = full, offset = offset)
}
})
}
result
},
error = function(cond) {
# Don't print shiny.silent.error (i.e. validation errors)
if (cnd_inherits(cond, "shiny.silent.error")) return()
if (isTRUE(getOption("show.error.messages"))) {
printError(cond, full = full, offset = offset)
}
}
)
}
#' @details `printError` prints the error and stack trace (if any) using
#' `warning(immediate.=TRUE)`. `printStackTrace` prints the stack
#' trace only.
#'
#' @param cond An condition object (generally, an error).
#' @param full If `TRUE`, then every element of `sys.calls()` will be
#' included in the stack trace. By default (`FALSE`), calls that Shiny
#' deems uninteresting will be hidden.
#' @param offset If `TRUE` (the default), srcrefs will be reassigned from
#' the calls they originated from, to the destinations of those calls. If
#' you're used to stack traces from other languages, this feels more
#' intuitive, as the definition of the function indicated in the call and the
#' location specified by the srcref match up. If `FALSE`, srcrefs will be
#' left alone (traditional R treatment where the srcref is of the callsite).
#' @rdname stacktrace
#' @export
printError <- function(cond,
full = get_devmode_option("shiny.fullstacktrace", FALSE),
offset = getOption("shiny.stacktraceoffset", TRUE)) {
warning(call. = FALSE, immediate. = TRUE, sprintf("Error in %s: %s",
getCallNames(list(conditionCall(cond))), conditionMessage(cond)))
printStackTrace(cond, full = full, offset = offset)
}
#' @rdname stacktrace
#' @export
printStackTrace <- function(cond,
full = get_devmode_option("shiny.fullstacktrace", FALSE),
offset = getOption("shiny.stacktraceoffset", TRUE)) {
stackTraces <- c(
attr(cond, "deep.stack.trace", exact = TRUE),
list(attr(cond, "stack.trace", exact = TRUE))
)
# Stripping of stack traces is the one step where the different stack traces
# interact. So we need to do this in one go, instead of individually within
# printOneStackTrace.
if (!full) {
stripResults <- stripStackTraces(lapply(stackTraces, getCallNames))
} else {
# If full is TRUE, we don't want to strip anything
stripResults <- rep_len(list(TRUE), length(stackTraces))
}
mapply(
seq_along(stackTraces),
rev(stackTraces),
rev(stripResults),
FUN = function(i, trace, stripResult) {
if (is.integer(trace)) {
noun <- if (trace > 1L) "traces" else "trace"
message("[ reached getOption(\"shiny.deepstacktrace\") -- omitted ", trace, " more stack ", noun, " ]")
} else {
if (i != 1) {
message("From earlier call:")
}
printOneStackTrace(
stackTrace = trace,
stripResult = stripResult,
full = full,
offset = offset
)
}
# No mapply return value--we're just printing
NULL
},
SIMPLIFY = FALSE
)
invisible()
}
printOneStackTrace <- function(stackTrace, stripResult, full, offset) {
calls <- offsetSrcrefs(stackTrace, offset = offset)
callNames <- getCallNames(stackTrace)
parents <- attr(stackTrace, "parents", exact = TRUE)
should_drop <- !full
should_strip <- !full
should_prune <- !full
if (should_drop) {
toKeep <- dropTrivialFrames(callNames)
calls <- calls[toKeep]
callNames <- callNames[toKeep]
parents <- parents[toKeep]
stripResult <- stripResult[toKeep]
}
toShow <- rep(TRUE, length(callNames))
if (should_prune) {
toShow <- toShow & pruneStackTrace(parents)
}
if (should_strip) {
toShow <- toShow & stripResult
}
# If we're running in testthat, hide the parts of the stack trace that can
# vary based on how testthat was launched. It's critical that this is not
# happen at the same time as dropTrivialFrames, which happens before
# pruneStackTrace; because dropTrivialTestFrames removes calls from the top
# (or bottom? whichever is the oldest?) of the stack, it breaks `parents`
# which is based on absolute indices of calls. dropTrivialFrames gets away
# with this because it only removes calls from the opposite side of the stack.
toShow <- toShow & dropTrivialTestFrames(callNames)
st <- data.frame(
num = rev(which(toShow)),
call = rev(callNames[toShow]),
loc = rev(getLocs(calls[toShow])),
category = rev(getCallCategories(calls[toShow])),
stringsAsFactors = FALSE
)
if (nrow(st) == 0) {
message(" [No stack trace available]")
} else {
width <- floor(log10(max(st$num))) + 1
formatted <- paste0(
" ",
formatC(st$num, width = width),
": ",
mapply(paste0(st$call, st$loc), st$category, FUN = function(name, category) {
if (category == "pkg")
cli::col_silver(name)
else if (category == "user")
cli::style_bold(cli::col_blue(name))
else
cli::col_white(name)
}),
"\n"
)
cat(file = stderr(), formatted, sep = "")
}
invisible(st)
}
stripStackTraces <- function(stackTraces, values = FALSE) {
score <- 1L # >=1: show, <=0: hide
lapply(seq_along(stackTraces), function(i) {
res <- stripOneStackTrace(stackTraces[[i]], i != 1, score)
score <<- res$score
toShow <- as.logical(res$trace)
if (values) {
as.character(stackTraces[[i]][toShow])
} else {
as.logical(toShow)
}
})
}
stripOneStackTrace <- function(stackTrace, truncateFloor, startingScore) {
prefix <- logical(0)
if (truncateFloor) {
indexOfFloor <- utils::tail(which(stackTrace == "..stacktracefloor.."), 1)
if (length(indexOfFloor)) {
stackTrace <- stackTrace[(indexOfFloor+1L):length(stackTrace)]
prefix <- rep_len(FALSE, indexOfFloor)
}
}
if (length(stackTrace) == 0) {
return(list(score = startingScore, character(0)))
}
score <- rep.int(0L, length(stackTrace))
score[stackTrace == "..stacktraceon.."] <- 1L
score[stackTrace == "..stacktraceoff.."] <- -1L
score <- startingScore + cumsum(score)
toShow <- score > 0 & !(stackTrace %in% c("..stacktraceon..", "..stacktraceoff..", "..stacktracefloor.."))
list(score = utils::tail(score, 1), trace = c(prefix, toShow))
}
# Given sys.parents() (which corresponds to sys.calls()), return a logical index
# that prunes each subtree so that only the final branch remains. The result,
# when applied to sys.calls(), is a linear list of calls without any "wrapper"
# functions like tryCatch, try, with, hybrid_chain, etc. While these are often
# part of the active call stack, they rarely are helpful when trying to identify
# a broken bit of code.
pruneStackTrace <- function(parents) {
# Detect nodes that are not the last child. This is necessary, but not
# sufficient; we also need to drop nodes that are the last child, but one of
# their ancestors is not.
is_dupe <- duplicated(parents, fromLast = TRUE)
# The index of the most recently seen node that was actually kept instead of
# dropped.
current_node <- 0
# Loop over the parent indices. Anything that is not parented by current_node
# (a.k.a. last-known-good node), or is a dupe, can be discarded. Anything that
# is kept becomes the new current_node.
#
# jcheng 2022-03-18: Two more reasons a node can be kept:
# 1. parent is 0
# 2. parent is i
# Not sure why either of these situations happen, but they're common when
# interacting with rlang/dplyr errors. See issue rstudio/shiny#3250 for repro
# cases.
include <- vapply(seq_along(parents), function(i) {
if ((!is_dupe[[i]] && parents[[i]] == current_node) ||
parents[[i]] == 0 ||
parents[[i]] == i) {
current_node <<- i
TRUE
} else {
FALSE
}
}, FUN.VALUE = logical(1))
include
}
dropTrivialFrames <- function(callnames) {
# Remove stop(), .handleSimpleError(), and h() calls from the end of
# the calls--they don't add any helpful information. But only remove
# the last *contiguous* block of them, and then, only if they are the
# last thing in the calls list.
hideable <- callnames %in% c(".handleSimpleError", "h", "base$wrapOnFulfilled")
# What's the last that *didn't* match stop/.handleSimpleError/h?
lastGoodCall <- max(which(!hideable))
toRemove <- length(callnames) - lastGoodCall
c(
rep_len(TRUE, length(callnames) - toRemove),
rep_len(FALSE, toRemove)
)
}
dropTrivialTestFrames <- function(callnames) {
if (!identical(Sys.getenv("TESTTHAT_IS_SNAPSHOT"), "true")) {
return(rep_len(TRUE, length(callnames)))
}
hideable <- callnames %in% c(
"test",
"devtools::test",
"test_check",
"testthat::test_check",
"test_dir",
"testthat::test_dir",
"test_file",
"testthat::test_file",
"test_local",
"testthat::test_local"
)
# Remove everything from inception to calling the test
# It shouldn't matter how you get there, just that you're finally testing
toRemove <- max(which(hideable))
c(
rep_len(FALSE, toRemove),
rep_len(TRUE, length(callnames) - toRemove)
)
}
offsetSrcrefs <- function(calls, offset = TRUE) {
if (offset) {
srcrefs <- getSrcRefs(calls)
# Offset calls vs. srcrefs by 1 to make them more intuitive.
# E.g. for "foo [bar.R:10]", line 10 of bar.R will be part of
# the definition of foo().
srcrefs <- c(utils::tail(srcrefs, -1), list(NULL))
calls <- setSrcRefs(calls, srcrefs)
}
calls
}
getSrcRefs <- function(calls) {
lapply(calls, function(call) {
attr(call, "srcref", exact = TRUE)
})
}
setSrcRefs <- function(calls, srcrefs) {
mapply(function(call, srcref) {
structure(call, srcref = srcref)
}, calls, srcrefs)
}
stripStackTrace <- function(cond) {
conditionStackTrace(cond) <- NULL
}
#' @details `conditionStackTrace` and `conditionStackTrace<-` are
#' accessor functions for getting/setting stack traces on conditions.
#'
#' @param cond A condition that may have previously been annotated by
#' `captureStackTraces` (or `withLogErrors`).
#' @rdname stacktrace
#' @export
conditionStackTrace <- function(cond) {
attr(cond, "stack.trace", exact = TRUE)
}
#' @param value The stack trace value to assign to the condition.
#' @rdname stacktrace
#' @export
`conditionStackTrace<-` <- function(cond, value) {
attr(cond, "stack.trace") <- value
invisible(cond)
}
#' @details The two functions `..stacktraceon..` and
#' `..stacktraceoff..` have no runtime behavior during normal execution;
#' they exist only to create artifacts on the stack trace (sys.call()) that
#' instruct the stack trace pretty printer what parts of the stack trace are
#' interesting or not. The initial state is 1 and we walk from the outermost
#' call inwards. Each ..stacktraceoff.. decrements the state by one, and each
#' ..stacktraceon.. increments the state by one. Any stack trace frame whose
#' value is less than 1 is hidden, and finally, the ..stacktraceon.. and
#' ..stacktraceoff.. calls themselves are hidden too.
#'
#' @rdname stacktrace
#' @export
..stacktraceon.. <- function(expr) expr
#' @rdname stacktrace
#' @export
..stacktraceoff.. <- function(expr) expr
..stacktracefloor.. <- function(expr) expr

121
R/deprecated.R Normal file
View File

@@ -0,0 +1,121 @@
#' Print message for deprecated functions in Shiny
#'
#' To disable these messages, use `options(shiny.deprecation.messages=FALSE)`.
#'
#' @param version Shiny version when the function was deprecated
#' @param what Function with possible arguments
#' @param with Possible function with arguments that should be used instead
#' @param details Additional information to be added after a new line to the displayed message
#' @keywords internal
shinyDeprecated <- function(
version,
what,
with = NULL,
details = NULL,
type = c("deprecated", "superseded")
) {
if (is_false(getOption("shiny.deprecation.messages"))) {
return(invisible())
}
type <- match.arg(type)
msg <- paste0("`", what, "` is ", type, " as of shiny ", version, ".")
if (!is.null(with)) {
msg <- paste0(msg, "\n", "Please use `", with, "` instead.")
}
if (!is.null(details)) {
msg <- paste0(msg, "\n", details)
}
# lifecycle::deprecate_soft(when, what, with = with, details = details, id = id, env = env)
rlang::inform(message = msg, .frequency = "always", .frequency_id = msg, .file = stderr())
}
deprecatedEnvQuotedMessage <- function() {
if (!in_devmode()) return(invisible())
if (is_false(getOption("shiny.deprecation.messages"))) return(invisible())
# Capture calling function
grandparent_call <- sys.call(-2)
# Turn language into user friendly string
grandparent_txt <- paste0(utils::capture.output({grandparent_call}), collapse = "\n")
msg <- paste0(
"The `env` and `quoted` arguments are deprecated as of shiny 1.7.0.",
" Please use quosures from `rlang` instead.\n",
"See <https://github.com/rstudio/shiny/issues/3108> for more information.\n",
"Function call:\n",
grandparent_txt
)
# Call less often as users do not have much control over this warning
rlang::inform(message = msg, .frequency = "regularly", .frequency_id = msg, .file = stderr())
}
#' Create disk cache (deprecated)
#'
#' @param exec_missing Deprecated.
#' @inheritParams cachem::cache_disk
#' @keywords internal
#' @export
diskCache <- function(
dir = NULL,
max_size = 500 * 1024 ^ 2,
max_age = Inf,
max_n = Inf,
evict = c("lru", "fifo"),
destroy_on_finalize = FALSE,
missing = key_missing(),
exec_missing = deprecated(),
logfile = NULL
) {
shinyDeprecated("1.6.0", "diskCache()", "cachem::cache_disk()")
if (is_present(exec_missing)) {
shinyDeprecated("1.6.0", "diskCache(exec_missing =)")
}
cachem::cache_disk(
dir = dir,
max_size = max_size,
max_age = max_age,
max_n = max_n,
evict = evict,
destroy_on_finalize = destroy_on_finalize,
missing = missing,
logfile = logfile
)
}
#' Create memory cache (deprecated)
#'
#' @param exec_missing Deprecated.
#' @inheritParams cachem::cache_mem
#' @keywords internal
#' @export
memoryCache <- function(
max_size = 200 * 1024 ^ 2,
max_age = Inf,
max_n = Inf,
evict = c("lru", "fifo"),
missing = key_missing(),
exec_missing = deprecated(),
logfile = NULL)
{
shinyDeprecated("1.6.0", "diskCache()", "cachem::cache_mem()")
if (is_present(exec_missing)) {
shinyDeprecated("1.6.0", "diskCache(exec_missing =)")
}
cachem::cache_mem(
max_size = max_size,
max_age = max_age,
max_n = max_n,
evict = evict,
missing = missing,
logfile = logfile
)
}

369
R/devmode.R Normal file
View File

@@ -0,0 +1,369 @@
#' Shiny Developer Mode
#'
#' @description `r lifecycle::badge("experimental")`
#'
#' Developer Mode enables a number of [options()] to make a developer's life
#' easier, like enabling non-minified JS and printing messages about
#' deprecated functions and options.
#'
#' Shiny Developer Mode can be enabled by calling `devmode(TRUE)` and disabled
#' by calling `devmode(FALSE)`.
#'
#' Please see the function descriptions for more details.
#'
#' @describeIn devmode Function to set two options to enable/disable Shiny
#' Developer Mode and Developer messages
#' @param devmode Logical value which should be set to `TRUE` to enable Shiny
#' Developer Mode
#' @param verbose Logical value which should be set to `TRUE` display Shiny
#' Developer messages
#' @export
#' @examples
#' # Enable Shiny Developer mode
#' devmode()
#'
devmode <- function(
devmode = getOption("shiny.devmode", TRUE),
verbose = getOption("shiny.devmode.verbose", TRUE)
) {
options(
shiny.devmode = devmode,
shiny.devmode.verbose = verbose
)
}
#' @describeIn devmode Determines if Shiny is in Developer Mode. If the
#' `getOption("shiny.devmode")` is set to `TRUE` and not in testing inside
#' `testthat`, then Shiny Developer Mode is enabled.
#' @section Avoiding direct dependency on shiny:
#'
#' The methods explained in this help file act independently from the rest of
#' Shiny but are included to provide blue prints for your own packages. If
#' your package already has (or is willing to take) a dependency on Shiny, we
#' recommend using the exported Shiny methods for consistent behavior. Note
#' that if you use exported Shiny methods, it will cause the Shiny package to
#' load. This may be undesirable if your code will be used in (for example) R
#' Markdown documents that do not have a Shiny runtime (`runtime: shiny`).
#'
#' If your package can **not** take a dependency on Shiny, we recommending
#' re-implementing these two functions:
#'
#' \enumerate{
#' \item `in_devmode()`:
#'
#' This function should return `TRUE` if `getOption("shiny.devmode")` is set.
#' In addition, we strongly recommend that it also checks to make sure
#' `testthat` is not testing.
#'
#' ```r
#' in_devmode <- function() {
#' isTRUE(getOption("shiny.devmode", FALSE)) &&
#' !identical(Sys.getenv("TESTTHAT"), "true")
#' }
#' ```
#'
#' \item `get_devmode_option(name, default, devmode_default, devmode_message)`:
#'
#' This function is similar to `getOption(name, default)`, but when the option
#' is not set, the default value changes depending on the Dev Mode.
#' `get_devmode_option()` should be implemented as follows:
#'
#' * If not in Dev Mode:
#' * Return `getOption(name, default)`.
#' * If in Dev Mode:
#' * Get the global option `getOption(name)` value.
#' * If the global option value is set:
#' * Return the value.
#' * If the global option value is not set:
#' * Notify the developer that the Dev Mode default value will be used.
#' * Return the Dev Mode default value.
#'
#' When notifying the developer that the default value has changed, we strongly
#' recommend displaying a message (`devmode_message`) to `stderr()` once every 8
#' hours using [rlang::inform()]. This will keep the author up to date as to
#' which Dev Mode options are being altered. To allow developers a chance to
#' disable Dev Mode messages, the message should be skipped if
#' `getOption("shiny.devmode.verbose", TRUE)` is not `TRUE`.
#'
#' ```r
#' get_devmode_option <- function(name, default = NULL, devmode_default, devmode_message) {
#' if (!in_devmode()) {
#' # Dev Mode disabled, act like `getOption()`
#' return(getOption(name, default = default))
#' }
#'
#' # Dev Mode enabled, update the default value for `getOption()`
#' getOption(name, default = {
#' # Notify developer
#' if (
#' !missing(devmode_message) &&
#' !is.null(devmode_message) &&
#' getOption("shiny.devmode.verbose", TRUE)
#' ) {
#' rlang::inform(
#' message = devmode_message,
#' .frequency = "regularly",
#' .frequency_id = devmode_message,
#' .file = stderr()
#' )
#' }
#'
#' # Return Dev Mode default value `devmode_default`
#' devmode_default
#' })
#' }
#' ```
#' }
#'
#' The remaining functions in this file are used for author convenience and are
#' not recommended for all reimplementation situations.
#' @export
#' @examples
#' in_devmode() # TRUE/FALSE?
#'
in_devmode <- function() {
isTRUE(getOption("shiny.devmode", FALSE)) &&
# !testthat::is_testing()
!identical(Sys.getenv("TESTTHAT"), "true")
}
in_client_devmode <- function() {
# Client-side devmode enables client-side only dev features without local
# devmode. Currently, the main feature is the client-side error console.
isTRUE(getOption("shiny.client_devmode", FALSE))
}
#' @describeIn devmode Temporarily set Shiny Developer Mode and Developer
#' message verbosity
#' @param code Code to execute with the temporary Dev Mode options set
#' @export
#' @examples
#' # Execute code in a temporary shiny dev mode
#' with_devmode(TRUE, in_devmode()) # TRUE
#'
with_devmode <- function(
devmode,
code,
verbose = getOption("shiny.devmode.verbose", TRUE)
) {
withr::with_options(
list(
shiny.devmode = devmode,
shiny.devmode.verbose = verbose
),
code
)
}
#' @describeIn devmode If Shiny Developer Mode and verbosity are enabled,
#' displays a message once every 8 hrs (by default)
#' @param message Developer Mode message to be sent to [rlang::inform()]
#' @param .frequency Frequency of the Developer Mode message used with
#' [rlang::inform()]. Defaults to once every 8 hours.
#' @param .frequency_id [rlang::inform()] message identifier. Defaults to
#' `message`.
#' @param .file Output connection for [rlang::inform()]. Defaults to [stderr()]
#' @param ... Parameters passed to [rlang::inform()]
devmode_inform <- function(
message,
.frequency = "regularly",
.frequency_id = message,
.file = stderr(),
...
) {
if (!(
in_devmode() &&
isTRUE(getOption("shiny.devmode.verbose", TRUE))
)) {
return()
}
if (is.null(message)) {
return()
}
rlang::inform(
message = paste0("shiny devmode - ", message),
.frequency = .frequency,
.frequency_id = .frequency_id,
.file = .file,
...
)
}
registered_devmode_options <- NULL
on_load({
registered_devmode_options <- Map$new()
})
#' @describeIn devmode Registers a Shiny Developer Mode option with an updated
#' value and Developer message. This registration method allows package
#' authors to write one message in a single location.
#'
#' For example, the following Shiny Developer Mode options are registered:
#'
#' ```r
#' # Reload the Shiny app when a sourced R file changes
#' register_devmode_option(
#' "shiny.autoreload",
#' "Turning on shiny autoreload. To disable, call `options(shiny.autoreload = FALSE)`",
#' devmode_default = TRUE
#' )
#'
#' # Use the unminified Shiny JavaScript file, `shiny.js`
#' register_devmode_option(
#' "shiny.minified",
#' "Using full shiny javascript file. To use the minified version, call `options(shiny.minified = TRUE)`",
#' devmode_default = FALSE
#' )
#'
#' # Display the full stack trace when errors occur during Shiny app execution
#' register_devmode_option(
#' "shiny.fullstacktrace",
#' "Turning on full stack trace. To disable, call `options(shiny.fullstacktrace = FALSE)`",
#' devmode_default = TRUE
#' )
#' ```
#'
#' Other known, non-Shiny Developer Mode options:
#'
#' * Sass:
#' ```r
#' # Display the full stack trace when errors occur during Shiny app execution
#' register_devmode_option(
#' "sass.cache",
#' "Turning off sass cache. To use default caching, call `options(sass.cache = TRUE)`",
#' devmode_default = FALSE
#' )
#' ```
#'
#' @param name Name of option to look for in `options()`
#' @param default Default value to return if `in_devmode()` returns
#' `TRUE` and the specified option is not set in [`options()`].
#' @param devmode_message Message to display once every 8 hours when utilizing
#' the `devmode_default` value. If `devmode_message` is missing, the
#' registered `devmode_message` value be used.
#' @param devmode_default Default value to return if `in_devmode()` returns
#' `TRUE` and the specified option is not set in [`options()`]. For
#' `get_devmode_option()`, if `devmode_default` is missing, the
#' registered `devmode_default` value will be used.
#' @export
#' @examples
#' # Ex: Within shiny, we register the option "shiny.minified"
#' # to default to `FALSE` when in Dev Mode
#' \dontrun{register_devmode_option(
#' "shiny.minified",
#' devmode_message = paste0(
#' "Using full shiny javascript file. ",
#' "To use the minified version, call `options(shiny.minified = TRUE)`"
#' ),
#' devmode_default = FALSE
#' )}
#'
register_devmode_option <- function(
name,
devmode_message = NULL,
devmode_default = NULL
) {
if (!is.null(devmode_message)) {
stopifnot(length(devmode_message) == 1 && is.character(devmode_message))
}
registered_devmode_options$set(
name,
list(devmode_default = devmode_default, devmode_message = devmode_message)
)
}
#' @describeIn devmode Provides a consistent way to change the expected
#' [getOption()] behavior when Developer Mode is enabled. This method is very
#' similar to [getOption()] where the globally set option takes precedence.
#' See section "Avoiding direct dependency on shiny" for
#' `get_devmode_option()` implementation details.
#'
#' **Package developers:** Register your Dev Mode option using
#' `register_devmode_option()` to avoid supplying the same `devmode_default`
#' and `devmode_message` values throughout your package. (This requires a
#' \pkg{shiny} dependency.)
#' @export
#' @examples
#' # Used within `shiny::runApp(launch.browser)`
#' get_devmode_option("shiny.minified", TRUE) # TRUE if Dev mode is off
#' is_minified <- with_devmode(TRUE, {
#' get_devmode_option("shiny.minified", TRUE)
#' })
#' is_minified # FALSE
#'
get_devmode_option <- function(
name,
default = NULL,
devmode_default = missing_arg(),
devmode_message = missing_arg()
) {
getOption(
name,
local({
if (!in_devmode()) {
# typical case
return(default)
}
info <- registered_devmode_options$get(name)
if (is.null(info)) {
# Not registered,
# Warn and return default value
rlang::warn(
message = paste0(
"`get_devmode_option(name)` could not find `name = \"", name, "\"`. ",
"Returning `default` value"
)
)
return(default)
}
# display message
devmode_inform(
maybe_missing(
# use provided `devmode_message` value
devmode_message,
# If `devmode_message` is missing, display registered `devmode_message`
default = info$devmode_message
)
)
# return value
maybe_missing(
# use provided `devmode_default` value
devmode_default,
# if `devmode_default` is missing, provide registered `devmode_default`
default = info$devmode_default
)
})
)
}
on_load({
register_devmode_option(
"shiny.autoreload",
"Turning on shiny autoreload. To disable, call `options(shiny.autoreload = FALSE)`",
TRUE
)
register_devmode_option(
"shiny.minified",
"Using full shiny javascript file. To use the minified version, call `options(shiny.minified = TRUE)`",
FALSE
)
register_devmode_option(
"shiny.fullstacktrace",
"Turning on full stack trace. To disable, call `options(shiny.fullstacktrace = FALSE)`",
TRUE
)
})

157
R/diagnose.R Normal file
View File

@@ -0,0 +1,157 @@
# Analyze an R file for possible extra or missing commas. Returns FALSE if any
# problems detected, TRUE otherwise.
diagnoseCode <- function(path = NULL, text = NULL) {
if (!xor(is.null(path), is.null(text))) {
stop("Must specify `path` or `text`, but not both.")
}
if (!is.null(path)) {
tokens <- sourcetools::tokenize_file(path)
} else {
tokens <- sourcetools::tokenize_string(text)
}
find_scopes <- function(tokens) {
# Strip whitespace and comments
tokens <- tokens[!(tokens$type %in% c("whitespace", "comment")),]
# Replace various types of things with "value"
tokens$type[tokens$type %in% c("string", "number", "symbol", "keyword")] <- "value"
# Record types for close and open brace/bracket/parens, and commas
brace_idx <- tokens$value %in% c("(", ")", "{", "}", "[", "]", ",")
tokens$type[brace_idx] <- tokens$value[brace_idx]
# Stack-related function for recording scope. Starting scope is "{"
stack <- "{"
push <- function(x) {
stack <<- c(stack, x)
}
pop <- function() {
if (length(stack) == 1) {
# Stack underflow, but we need to keep going
return(NA_character_)
}
res <- stack[length(stack)]
stack <<- stack[-length(stack)]
res
}
peek <- function() {
stack[length(stack)]
}
# First, establish a scope for each token. For opening and closing
# braces/brackets/parens, the scope at that location is the *surrounding*
# scope, not the new scope created by the brace/bracket/paren.
for (i in seq_len(nrow(tokens))) {
value <- tokens$value[i]
tokens$scope[i] <- peek()
if (value %in% c("{", "(", "[")) {
push(value)
} else if (value == "}") {
if (!identical(pop(), "{"))
tokens$err[i] <- "unmatched_brace"
# For closing brace/paren/bracket, get the scope after popping
tokens$scope[i] <- peek()
} else if (value == ")") {
if (!identical(pop(), "("))
tokens$err[i] <- "unmatched_paren"
tokens$scope[i] <- peek()
} else if (value == "]") {
if (!identical(pop(), "["))
tokens$err[i] <- "unmatched_bracket"
tokens$scope[i] <- peek()
}
}
tokens
}
check_commas <- function(tokens) {
# Find extra and missing commas
tokens$err <- mapply(
tokens$type,
c("", tokens$type[-length(tokens$type)]),
c(tokens$type[-1], ""),
tokens$scope,
tokens$err,
SIMPLIFY = FALSE,
FUN = function(type, prevType, nextType, scope, err) {
# If an error was already found, just return it. This could have
# happened in the brace/paren/bracket matching phase.
if (!is.na(err)) {
return(err)
}
if (scope == "(") {
if (type == "," &&
(prevType == "(" || prevType == "," || nextType == ")"))
{
return("extra_comma")
}
if ((prevType == ")" && type == "value") ||
(prevType == "value" && type == "value")) {
return("missing_comma")
}
}
NA_character_
}
)
tokens
}
tokens$err <- NA_character_
tokens <- find_scopes(tokens)
tokens <- check_commas(tokens)
# No errors found
if (all(is.na(tokens$err))) {
return(TRUE)
}
# If we got here, errors were found; print messages.
if (!is.null(path)) {
lines <- readLines(path)
} else {
lines <- strsplit(text, "\n")[[1]]
}
# Print out the line of code with the error, and point to the column with
# the error.
show_code_error <- function(msg, lines, row, col) {
message(paste0(
msg, "\n",
row, ":", lines[row], "\n",
paste0(rep.int(" ", nchar(as.character(row)) + 1), collapse = ""),
gsub(perl = TRUE, "[^\\s]", " ", substr(lines[row], 1, col-1)), "^"
))
}
err_idx <- which(!is.na(tokens$err))
msg <- ""
for (i in err_idx) {
row <- tokens$row[i]
col <- tokens$column[i]
err <- tokens$err[i]
if (err == "missing_comma") {
show_code_error("Possible missing comma at:", lines, row, col)
} else if (err == "extra_comma") {
show_code_error("Possible extra comma at:", lines, row, col)
} else if (err == "unmatched_brace") {
show_code_error("Possible unmatched '}' at:", lines, row, col)
} else if (err == "unmatched_paren") {
show_code_error("Possible unmatched ')' at:", lines, row, col)
} else if (err == "unmatched_bracket") {
show_code_error("Possible unmatched ']' at:", lines, row, col)
}
}
return(FALSE)
}

338
R/extended-task.R Normal file
View File

@@ -0,0 +1,338 @@
#' Task or computation that proceeds in the background
#'
#' @description In normal Shiny reactive code, whenever an observer, calc, or
#' output is busy computing, it blocks the current session from receiving any
#' inputs or attempting to proceed with any other computation related to that
#' session.
#'
#' The `ExtendedTask` class allows you to have an expensive operation that is
#' started by a reactive effect, and whose (eventual) results can be accessed
#' by a regular observer, calc, or output; but during the course of the
#' operation, the current session is completely unblocked, allowing the user
#' to continue using the rest of the app while the operation proceeds in the
#' background.
#'
#' Note that each `ExtendedTask` object does not represent a _single
#' invocation_ of its long-running function. Rather, it's an object that is
#' used to invoke the function with different arguments, keeps track of
#' whether an invocation is in progress, and provides ways to get at the
#' current status or results of the operation. A single `ExtendedTask` object
#' does not permit overlapping invocations: if the `invoke()` method is called
#' before the previous `invoke()` is completed, the new invocation will not
#' begin until the previous invocation has completed.
#'
#' @section `ExtendedTask` versus asynchronous reactives:
#'
#' Shiny has long supported [using
#' \{promises\}](https://rstudio.github.io/promises/articles/promises_06_shiny.html)
#' to write asynchronous observers, calcs, or outputs. You may be wondering
#' what the differences are between those techniques and this class.
#'
#' Asynchronous observers, calcs, and outputs are not--and have never
#' been--designed to let a user start a long-running operation, while keeping
#' that very same (browser) session responsive to other interactions. Instead,
#' they unblock other sessions, so you can take a long-running operation that
#' would normally bring the entire R process to a halt and limit the blocking
#' to just the session that started the operation. (For more details, see the
#' section on ["The Flush
#' Cycle"](https://rstudio.github.io/promises/articles/promises_06_shiny.html#the-flush-cycle).)
#'
#' `ExtendedTask`, on the other hand, invokes an asynchronous function (that
#' is, a function that quickly returns a promise) and allows even that very
#' session to immediately unblock and carry on with other user interactions.
#'
#' @section OpenTelemetry Integration:
#'
#' When an `ExtendedTask` is created, if OpenTelemetry tracing is enabled for
#' `"reactivity"` (see [withOtelCollect()]), the `ExtendedTask` will record
#' spans for each invocation of the task. The tracing level at `invoke()` time
#' does not affect whether spans are recorded; only the tracing level when
#' calling `ExtendedTask$new()` matters.
#'
#' The OTel span will be named based on the label created from the variable the
#' `ExtendedTask` is assigned to. If no label can be determined, the span will
#' be named `<anonymous>`. Similar to other Shiny OpenTelemetry spans, the span
#' will also include source reference attributes and session ID attributes.
#'
#' ```r
#' withOtelCollect("all", {
#' my_task <- ExtendedTask$new(function(...) { ... })
#' })
#'
#' # Span recorded for this invocation: ExtendedTask my_task
#' my_task$invoke(...)
#' ```
#'
#' @examplesIf rlang::is_interactive() && rlang::is_installed("mirai")
#' library(shiny)
#' library(bslib)
#' library(mirai)
#'
#' # Set background processes for running tasks
#' daemons(1)
#' # Reset when the app is stopped
#' onStop(function() daemons(0))
#'
#' ui <- page_fluid(
#' titlePanel("Extended Task Demo"),
#' p(
#' 'Click the button below to perform a "calculation"',
#' "that takes a while to perform."
#' ),
#' input_task_button("recalculate", "Recalculate"),
#' p(textOutput("result"))
#' )
#'
#' server <- function(input, output) {
#' rand_task <- ExtendedTask$new(function() {
#' mirai(
#' {
#' # Slow operation goes here
#' Sys.sleep(2)
#' sample(1:100, 1)
#' }
#' )
#' })
#'
#' # Make button state reflect task.
#' # If using R >=4.1, you can do this instead:
#' # rand_task <- ExtendedTask$new(...) |> bind_task_button("recalculate")
#' bind_task_button(rand_task, "recalculate")
#'
#' observeEvent(input$recalculate, {
#' # Invoke the extended in an observer
#' rand_task$invoke()
#' })
#'
#' output$result <- renderText({
#' # React to updated results when the task completes
#' number <- rand_task$result()
#' paste0("Your number is ", number, ".")
#' })
#' }
#'
#' shinyApp(ui, server)
#'
#' @export
ExtendedTask <- R6Class("ExtendedTask", portable = TRUE, cloneable = FALSE,
public = list(
#' @description
#' Creates a new `ExtendedTask` object. `ExtendedTask` should generally be
#' created either at the top of a server function, or at the top of a module
#' server function.
#'
#' @param func The long-running operation to execute. This should be an
#' asynchronous function, meaning, it should use the
#' [\{promises\}](https://rstudio.github.io/promises/) package, most
#' likely in conjunction with the
#' [\{mirai\}](https://mirai.r-lib.org) or
#' [\{future\}](https://rstudio.github.io/promises/articles/promises_04_futures.html)
#' package. (In short, the return value of `func` should be a
#' [`mirai`][mirai::mirai()], [`Future`][future::future()], `promise`,
#' or something else that [promises::as.promise()] understands.)
#'
#' It's also important that this logic does not read from any
#' reactive inputs/sources, as inputs may change after the function is
#' invoked; instead, if the function needs to access reactive inputs, it
#' should take parameters and the caller of the `invoke()` method should
#' read reactive inputs and pass them as arguments.
initialize = function(func) {
private$func <- func
# Do not show these private reactive values in otel spans
with_no_otel_collect({
private$rv_status <- reactiveVal("initial", label = "ExtendedTask$private$status")
private$rv_value <- reactiveVal(NULL, label = "ExtendedTask$private$value")
private$rv_error <- reactiveVal(NULL, label = "ExtendedTask$private$error")
})
private$invocation_queue <- fastmap::fastqueue()
domain <- getDefaultReactiveDomain()
# Set a label for the reactive values for easier debugging
# Go up an extra sys.call() to get the user's call to ExtendedTask$new()
# The first sys.call() is to `initialize(...)`
call_srcref <- get_call_srcref(-1)
label <- rassignSrcrefToLabel(
call_srcref,
defaultLabel = "<anonymous>"
)
private$otel_span_label <- otel_span_label_extended_task(label, domain = domain)
private$otel_log_label_add_to_queue <- otel_log_label_extended_task_add_to_queue(label, domain = domain)
private$otel_attrs <- c(
otel_srcref_attributes(call_srcref, "ExtendedTask"),
otel_session_id_attrs(domain)
) %||% list()
# Capture this value at init-time, not run-time
# This way, the span is only created if otel was enabled at time of creation... just like other spans
private$is_recording_otel <- has_otel_collect("reactivity")
},
#' @description
#' Starts executing the long-running operation. If this `ExtendedTask` is
#' already running (meaning, a previous call to `invoke()` is not yet
#' complete) then enqueues this invocation until after the current
#' invocation, and any already-enqueued invocation, completes.
#'
#' @param ... Parameters to use for this invocation of the underlying
#' function. If reactive inputs are needed by the underlying function,
#' they should be read by the caller of `invoke` and passed in as
#' arguments.
invoke = function(...) {
args <- rlang::dots_list(..., .ignore_empty = "none")
call <- rlang::caller_call(n = 0)
if (
isolate(private$rv_status()) == "running" ||
private$invocation_queue$size() > 0
) {
otel_log(
private$otel_log_add_to_queue_label,
severity = "debug",
attributes = c(
private$otel_attrs,
list(
queue_size = private$invocation_queue$size() + 1L
)
)
)
private$invocation_queue$add(list(args = args, call = call))
} else {
if (private$is_recording_otel) {
private$otel_span <- start_otel_span(
private$otel_span_label,
attributes = private$otel_attrs
)
otel::local_active_span(private$otel_span)
}
private$do_invoke(args, call = call)
}
invisible(NULL)
},
#' @description
#' This is a reactive read that invalidates the caller when the task's
#' status changes.
#'
#' Returns one of the following values:
#'
#' * `"initial"`: This `ExtendedTask` has not yet been invoked
#' * `"running"`: An invocation is currently running
#' * `"success"`: An invocation completed successfully, and a value can be
#' retrieved via the `result()` method
#' * `"error"`: An invocation completed with an error, which will be
#' re-thrown if you call the `result()` method
status = function() {
private$rv_status()
},
#' @description
#' Attempts to read the results of the most recent invocation. This is a
#' reactive read that invalidates as the task's status changes.
#'
#' The actual behavior differs greatly depending on the current status of
#' the task:
#'
#' * `"initial"`: Throws a silent error (like [`req(FALSE)`][req()]). If
#' this happens during output rendering, the output will be blanked out.
#' * `"running"`: Throws a special silent error that, if it happens during
#' output rendering, makes the output appear "in progress" until further
#' notice.
#' * `"success"`: Returns the return value of the most recent invocation.
#' * `"error"`: Throws whatever error was thrown by the most recent
#' invocation.
#'
#' This method is intended to be called fairly naively by any output or
#' reactive expression that cares about the output--you just have to be
#' aware that if the result isn't ready for whatever reason, processing will
#' stop in much the same way as `req(FALSE)` does, but when the result is
#' ready you'll get invalidated, and when you run again the result should be
#' there.
#'
#' Note that the `result()` method is generally not meant to be used with
#' [observeEvent()], [eventReactive()], [bindEvent()], or [isolate()] as the
#' invalidation will be ignored.
result = function() {
switch (private$rv_status(),
running = req(FALSE, cancelOutput = "progress"),
success = if (private$rv_value()$visible) {
private$rv_value()$value
} else {
invisible(private$rv_value()$value)
},
error = stop(private$rv_error()),
# default case (initial, cancelled)
req(FALSE)
)
}
),
private = list(
func = NULL,
# reactive value with "initial"|"running"|"success"|"error"
rv_status = NULL,
rv_value = NULL,
rv_error = NULL,
invocation_queue = NULL,
otel_span_label = NULL,
otel_log_label_add_to_queue = NULL,
otel_attrs = list(),
is_recording_otel = FALSE,
otel_span = NULL,
do_invoke = function(args, call = NULL) {
private$rv_status("running")
private$rv_value(NULL)
private$rv_error(NULL)
p <- promise_resolve(
maskReactiveContext(do.call(private$func, args))
)
p <- promises::then(
p,
onFulfilled = function(value, .visible) {
if (is_otel_span(private$otel_span)) {
private$otel_span$end(status_code = "ok")
private$otel_span <- NULL
}
private$on_success(list(value = value, visible = .visible))
},
onRejected = function(error) {
if (is_otel_span(private$otel_span)) {
private$otel_span$end(status_code = "error")
private$otel_span <- NULL
}
private$on_error(error, call = call)
}
)
promises::finally(p, onFinally = function() {
if (private$invocation_queue$size() > 0) {
next_call <- private$invocation_queue$remove()
private$do_invoke(next_call$args, next_call$call)
}
})
invisible(NULL)
},
on_error = function(err, call = NULL) {
cli::cli_warn(
"ERROR: An error occurred when invoking the ExtendedTask.",
parent = err,
call = call
)
private$rv_status("error")
private$rv_error(err)
},
on_success = function(value) {
private$rv_status("success")
private$rv_value(value)
}
)
)

View File

@@ -1,37 +1,50 @@
# For HTML5-capable browsers, file uploads happen through a series of requests.
#
#
# 1. Client tells server that one or more files are about to be uploaded; the
# server responds with a "job ID" that the client should use for the rest of
# the upload.
#
#
# 2. For each file (sequentially):
# a. Client tells server the name, size, and type of the file.
# b. Client sends server a small-ish blob of data.
# c. Repeat 2b until the entire file has been uploaded.
# d. Client tells server that the current file is done.
#
#
# 3. Repeat 2 until all files have been uploaded.
#
#
# 4. Client tells server that all files have been uploaded, along with the
# input ID that this data should be associated with.
#
#
# Unfortunately this approach will not work for browsers that don't support
# HTML5 File API, but the fallback approach we would like to use (multipart
# form upload, i.e. traditional HTTP POST-based file upload) doesn't work with
# the websockets package's HTTP server at the moment.
FileUploadOperation <- setRefClass(
# @description Returns a file's extension, with a leading dot, if one can be
# found. A valid extension contains only alphanumeric characters. If there is
# no extension, or if it contains non-alphanumeric characters, an empty
# string is returned.
# @param x character vector giving file paths.
# @return The extension of \code{x}, with a leading dot, if one was found.
# Otherwise, an empty character vector.
maybeGetExtension <- function(x) {
ext <- tools::file_ext(x)
ifelse(ext == "", ext, paste0(".", ext))
}
FileUploadOperation <- R6Class(
'FileUploadOperation',
fields = list(
.parent = 'ANY',
.id = 'character',
.files = 'data.frame',
.dir = 'character',
.currentFileInfo = 'list',
.currentFileData = 'ANY',
.pendingFileInfos = 'list'
),
methods = list(
portable = FALSE,
class = FALSE,
public = list(
.parent = NULL,
.id = character(0),
.files = data.frame(),
.dir = character(0),
.currentFileInfo = list(),
.currentFileData = NULL,
.pendingFileInfos = list(),
initialize = function(parent, id, dir, fileInfos) {
.parent <<- parent
.id <<- id
@@ -51,15 +64,16 @@ FileUploadOperation <- setRefClass(
.currentFileInfo <<- file
.pendingFileInfos <<- tail(.pendingFileInfos, -1)
filename <- file.path(.dir, as.character(length(.files$name)))
row <- data.frame(name=file$name, size=file$size, type=file$type,
fileBasename <- basename(.currentFileInfo$name)
filename <- file.path(.dir, paste0(as.character(length(.files$name)), maybeGetExtension(fileBasename)))
row <- data.frame(name=fileBasename, size=file$size, type=file$type,
datapath=filename, stringsAsFactors=FALSE)
if (length(.files$name) == 0)
.files <<- row
else
.files <<- rbind(.files, row)
.currentFileData <<- file(filename, open='wb')
},
fileChunk = function(rawdata) {
@@ -77,33 +91,50 @@ FileUploadOperation <- setRefClass(
)
)
FileUploadContext <- setRefClass(
#' @include map.R
FileUploadContext <- R6Class(
'FileUploadContext',
fields = list(
.basedir = 'character',
.operations = 'Map'
class = FALSE,
private = list(
basedir = character(0),
operations = 'Map',
ids = character(0) # Keep track of all ids used for file uploads
),
methods = list(
public = list(
initialize = function(dir=tempdir()) {
.basedir <<- dir
private$basedir <- dir
private$operations <- Map$new()
},
createUploadOperation = function(fileInfos) {
while (TRUE) {
id <- paste(as.raw(runif(12, min=0, max=0xFF)), collapse='')
dir <- file.path(.basedir, id)
id <- createUniqueId(12)
private$ids <- c(private$ids, id)
dir <- file.path(private$basedir, id)
if (!dir.create(dir))
next
op <- FileUploadOperation$new(.self, id, dir, fileInfos)
.operations$set(id, op)
op <- FileUploadOperation$new(self, id, dir, fileInfos)
private$operations$set(id, op)
return(id)
}
},
getUploadOperation = function(jobId) {
.operations$get(jobId)
private$operations$get(jobId)
},
onJobFinished = function(jobId) {
.operations$remove(jobId)
private$operations$remove(jobId)
},
# Remove the directories containing file uploads; this is to be called when
# a session ends.
rmUploadDirs = function() {
# Make sure all_paths is underneath the tempdir()
if (!grepl(normalizePath(tempdir()), normalizePath(private$basedir), fixed = TRUE)) {
stop("Won't remove upload path ", private$basedir,
"because it is not under tempdir(): ", tempdir())
}
all_paths <- file.path(private$basedir, private$ids)
unlink(all_paths, recursive = TRUE)
}
)
)

31
R/globals.R Normal file
View File

@@ -0,0 +1,31 @@
# A scope where we can put mutable global state
.globals <- new.env(parent = emptyenv())
.onLoad <- function(libname, pkgname) {
# R's lazy-loading package scheme causes the private seed to be cached in the
# package itself, making our PRNG completely deterministic. This line resets
# the private seed during load.
withPrivateSeed(set.seed(NULL))
for (expr in on_load_exprs) {
eval(expr, envir = environment(.onLoad))
}
# Make sure these methods are available to knitr if shiny is loaded but not
# attached.
s3_register("knitr::knit_print", "reactive")
s3_register("knitr::knit_print", "shiny.appobj")
s3_register("knitr::knit_print", "shiny.render.function")
}
on_load_exprs <- list()
# Register an expression to be evaluated when the package is loaded (in the
# .onLoad function).
on_load <- function(expr) {
on_load_exprs[[length(on_load_exprs) + 1]] <<- substitute(expr)
}
on_load({
IS_SHINY_LOCAL_PKG <- exists(".__DEVTOOLS__")
})

543
R/graph.R Normal file
View File

@@ -0,0 +1,543 @@
# domain is like session
# used to help define truly global react id's.
# should work across session and in global namespace
.globals$reactIdCounter <- 0L
nextGlobalReactId <- function() {
.globals$reactIdCounter <- .globals$reactIdCounter + 1L
reactIdStr(.globals$reactIdCounter)
}
reactIdStr <- function(num) {
paste0("r", num)
}
#' Reactive Log Visualizer
#'
#' Provides an interactive browser-based tool for visualizing reactive
#' dependencies and execution in your application.
#'
#' To use the reactive log visualizer, start with a fresh R session and
#' run the command `reactlog::reactlog_enable()`; then launch your
#' application in the usual way (e.g. using [runApp()]). At
#' any time you can hit Ctrl+F3 (or for Mac users, Command+F3) in your
#' web browser to launch the reactive log visualization.
#'
#' The reactive log visualization only includes reactive activity up
#' until the time the report was loaded. If you want to see more recent
#' activity, refresh the browser.
#'
#' Note that Shiny does not distinguish between reactive dependencies
#' that "belong" to one Shiny user session versus another, so the
#' visualization will include all reactive activity that has taken place
#' in the process, not just for a particular application or session.
#'
#' As an alternative to pressing Ctrl/Command+F3--for example, if you
#' are using reactives outside of the context of a Shiny
#' application--you can run the `reactlogShow` function, which will
#' generate the reactive log visualization as a static HTML file and
#' launch it in your default browser. In this case, refreshing your
#' browser will not load new activity into the report; you will need to
#' call `reactlogShow()` explicitly.
#'
#' For security and performance reasons, do not enable
#' `options(shiny.reactlog=TRUE)` (or `reactlog::reactlog_enable()`) in
#' production environments. When the option is enabled, it's possible
#' for any user of your app to see at least some of the source code of
#' your reactive expressions and observers. In addition, reactlog
#' should be considered a memory leak as it will constantly grow and
#' will never reset until the R session is restarted.
#'
#' @name reactlog
NULL
#' @describeIn reactlog Return a list of reactive information. Can be used in
#' conjunction with [reactlog::reactlog_show] to later display the reactlog
#' graph.
#' @export
reactlog <- function() {
rLog$asList()
}
#' @describeIn reactlog Display a full reactlog graph for all sessions.
#' @param time A boolean that specifies whether or not to display the
#' time that each reactive takes to calculate a result.
#' @export
reactlogShow <- function(time = TRUE) {
check_reactlog()
reactlog::reactlog_show(reactlog(), time = time)
}
#' @describeIn reactlog Resets the entire reactlog stack. Useful for debugging
#' and removing all prior reactive history.
#' @export
reactlogReset <- function() {
rLog$reset()
}
#' @describeIn reactlog Adds "mark" entry into the reactlog stack. This is
#' useful for programmatically adding a marked entry in the reactlog, rather
#' than using your keyboard's key combination.
#'
#' For example, we can _mark_ the reactlog at the beginning of an
#' `observeEvent`'s calculation:
#' ```r
#' observeEvent(input$my_event_trigger, {
#' # Add a mark in the reactlog
#' reactlogAddMark()
#' # Run your regular event reaction code here...
#' ....
#' })
#' ```
#' @param session The Shiny session to assign the mark to. Defaults to the
#' current session.
#' @export
reactlogAddMark <- function(session = getDefaultReactiveDomain()) {
rLog$userMark(session)
}
# called in "/reactlog" middleware
renderReactlog <- function(sessionToken = NULL, time = TRUE) {
check_reactlog()
reactlog::reactlog_render(
reactlog(),
session_token = sessionToken,
time = time
)
}
check_reactlog <- function() {
if (!is_installed("reactlog", reactlog_min_version)) {
rlang::check_installed("reactlog", reactlog_min_version)
}
}
# Should match the (suggested) version in DESCRIPTION file
reactlog_min_version <- "1.0.0"
RLog <- R6Class(
"RLog",
portable = FALSE,
private = list(
option = "shiny.reactlog",
msgOption = "shiny.reactlog.console",
appendEntry = function(domain, logEntry) {
if (self$isLogging()) {
sessionToken <- if (is.null(domain)) NULL else domain$token
logStack$push(c(logEntry, list(
session = sessionToken,
time = as.numeric(Sys.time())
)))
}
if (!is.null(domain)) domain$reactlog(logEntry)
}
),
public = list(
msg = "<MessageLogger>",
logStack = "<Stack>",
noReactIdLabel = "NoCtxReactId",
noReactId = reactIdStr("NoCtxReactId"),
dummyReactIdLabel = "DummyReactId",
dummyReactId = reactIdStr("DummyReactId"),
asList = function() {
ret <- self$logStack$as_list()
attr(ret, "version") <- "1"
ret
},
ctxIdStr = function(ctxId) {
if (is.null(ctxId) || identical(ctxId, "")) {
return(NULL)
}
paste0("ctx", ctxId)
},
namesIdStr = function(reactId) {
paste0("names(", reactId, ")")
},
asListIdStr = function(reactId) {
paste0("reactiveValuesToList(", reactId, ")")
},
asListAllIdStr = function(reactId) {
paste0("reactiveValuesToList(", reactId, ", all.names = TRUE)")
},
keyIdStr = function(reactId, key) {
paste0(reactId, "$", key)
},
valueStr = function(value, n = 200) {
if (!self$isLogging()) {
# return a placeholder string to avoid calling str
return("<reactlog is turned off>")
}
output <- try(silent = TRUE, {
# only capture the first level of the object
utils::capture.output(utils::str(value, max.level = 1))
})
outputTxt <- paste0(output, collapse = "\n")
msg$shortenString(outputTxt, n = n)
},
initialize = function(rlogOption = "shiny.reactlog", msgOption = "shiny.reactlog.console") {
private$option <- rlogOption
private$msgOption <- msgOption
self$reset()
},
reset = function() {
.globals$reactIdCounter <- 0L
self$logStack <- fastmap::faststack()
self$msg <- MessageLogger$new(option = private$msgOption)
# setup dummy and missing react information
self$msg$setReact(force = TRUE, list(reactId = self$noReactId, label = self$noReactIdLabel))
self$msg$setReact(force = TRUE, list(reactId = self$dummyReactId, label = self$dummyReactIdLabel))
},
isLogging = function() {
isTRUE(getOption(private$option, FALSE))
},
define = function(reactId, value, label, type, domain) {
valueStr <- self$valueStr(value)
if (msg$hasReact(reactId)) {
stop("react definition for id: ", reactId, " already found!!", "Label: ", label, "Type: ", type)
}
msg$setReact(list(reactId = reactId, label = label))
msg$log("define:", msg$reactStr(reactId), msg$typeStr(type = type), msg$valueStr(valueStr))
private$appendEntry(domain, list(
action = "define",
reactId = reactId,
label = msg$shortenString(label),
type = type,
value = valueStr
))
},
defineNames = function(reactId, value, label, domain) {
self$define(self$namesIdStr(reactId), value, self$namesIdStr(label), "reactiveValuesNames", domain)
},
defineAsList = function(reactId, value, label, domain) {
self$define(self$asListIdStr(reactId), value, self$asListIdStr(label), "reactiveValuesAsList", domain)
},
defineAsListAll = function(reactId, value, label, domain) {
self$define(self$asListAllIdStr(reactId), value, self$asListAllIdStr(label), "reactiveValuesAsListAll", domain)
},
defineKey = function(reactId, value, key, label, domain) {
self$define(self$keyIdStr(reactId, key), value, self$keyIdStr(label, key), "reactiveValuesKey", domain)
},
defineObserver = function(reactId, label, domain) {
self$define(reactId, value = NULL, label, "observer", domain)
},
dependsOn = function(reactId, depOnReactId, ctxId, domain) {
if (is.null(reactId)) {
return()
}
ctxId <- ctxIdStr(ctxId)
msg$log("dependsOn:", msg$reactStr(reactId), " on", msg$reactStr(depOnReactId), msg$ctxStr(ctxId))
private$appendEntry(domain, list(
action = "dependsOn",
reactId = reactId,
depOnReactId = depOnReactId,
ctxId = ctxId
))
},
dependsOnKey = function(reactId, depOnReactId, key, ctxId, domain) {
self$dependsOn(reactId, self$keyIdStr(depOnReactId, key), ctxId, domain)
},
dependsOnRemove = function(reactId, depOnReactId, ctxId, domain) {
ctxId <- self$ctxIdStr(ctxId)
msg$log("dependsOnRemove:", msg$reactStr(reactId), " on", msg$reactStr(depOnReactId), msg$ctxStr(ctxId))
private$appendEntry(domain, list(
action = "dependsOnRemove",
reactId = reactId,
depOnReactId = depOnReactId,
ctxId = ctxId
))
},
dependsOnKeyRemove = function(reactId, depOnReactId, key, ctxId, domain) {
self$dependsOnRemove(reactId, self$keyIdStr(depOnReactId, key), ctxId, domain)
},
createContext = function(ctxId, label, type, prevCtxId, domain) {
ctxId <- self$ctxIdStr(ctxId)
prevCtxId <- self$ctxIdStr(prevCtxId)
msg$log("createContext:", msg$ctxPrevCtxStr(preCtxIdTxt = " ", ctxId, prevCtxId, type))
private$appendEntry(domain, list(
action = "createContext",
ctxId = ctxId,
label = msg$shortenString(label),
type = type,
prevCtxId = prevCtxId,
srcref = as.vector(attr(label, "srcref")), srcfile = attr(label, "srcfile")
))
},
enter = function(reactId, ctxId, type, domain) {
ctxId <- self$ctxIdStr(ctxId)
if (identical(type, "isolate")) {
msg$log("isolateEnter:", msg$reactStr(reactId), msg$ctxStr(ctxId))
msg$depthIncrement()
private$appendEntry(domain, list(
action = "isolateEnter",
reactId = reactId,
ctxId = ctxId
))
} else {
msg$log("enter:", msg$reactStr(reactId), msg$ctxStr(ctxId, type))
msg$depthIncrement()
private$appendEntry(domain, list(
action = "enter",
reactId = reactId,
ctxId = ctxId,
type = type
))
}
},
exit = function(reactId, ctxId, type, domain) {
ctxId <- self$ctxIdStr(ctxId)
if (identical(type, "isolate")) {
msg$depthDecrement()
msg$log("isolateExit:", msg$reactStr(reactId), msg$ctxStr(ctxId))
private$appendEntry(domain, list(
action = "isolateExit",
reactId = reactId,
ctxId = ctxId
))
} else {
msg$depthDecrement()
msg$log("exit:", msg$reactStr(reactId), msg$ctxStr(ctxId, type))
private$appendEntry(domain, list(
action = "exit",
reactId = reactId,
ctxId = ctxId,
type = type
))
}
},
valueChange = function(reactId, value, domain) {
valueStr <- self$valueStr(value)
msg$log("valueChange:", msg$reactStr(reactId), msg$valueStr(valueStr))
private$appendEntry(domain, list(
action = "valueChange",
reactId = reactId,
value = valueStr
))
},
valueChangeNames = function(reactId, nameValues, domain) {
self$valueChange(self$namesIdStr(reactId), nameValues, domain)
},
valueChangeAsList = function(reactId, listValue, domain) {
self$valueChange(self$asListIdStr(reactId), listValue, domain)
},
valueChangeAsListAll = function(reactId, listValue, domain) {
self$valueChange(self$asListAllIdStr(reactId), listValue, domain)
},
valueChangeKey = function(reactId, key, value, domain) {
self$valueChange(self$keyIdStr(reactId, key), value, domain)
},
invalidateStart = function(reactId, ctxId, type, domain) {
ctxId <- self$ctxIdStr(ctxId)
if (identical(type, "isolate")) {
msg$log("isolateInvalidateStart:", msg$reactStr(reactId), msg$ctxStr(ctxId))
msg$depthIncrement()
private$appendEntry(domain, list(
action = "isolateInvalidateStart",
reactId = reactId,
ctxId = ctxId
))
} else {
msg$log("invalidateStart:", msg$reactStr(reactId), msg$ctxStr(ctxId, type))
msg$depthIncrement()
private$appendEntry(domain, list(
action = "invalidateStart",
reactId = reactId,
ctxId = ctxId,
type = type
))
}
},
invalidateEnd = function(reactId, ctxId, type, domain) {
ctxId <- self$ctxIdStr(ctxId)
if (identical(type, "isolate")) {
msg$depthDecrement()
msg$log("isolateInvalidateEnd:", msg$reactStr(reactId), msg$ctxStr(ctxId))
private$appendEntry(domain, list(
action = "isolateInvalidateEnd",
reactId = reactId,
ctxId = ctxId
))
} else {
msg$depthDecrement()
msg$log("invalidateEnd:", msg$reactStr(reactId), msg$ctxStr(ctxId, type))
private$appendEntry(domain, list(
action = "invalidateEnd",
reactId = reactId,
ctxId = ctxId,
type = type
))
}
},
invalidateLater = function(reactId, runningCtx, millis, domain) {
msg$log("invalidateLater: ", millis, "ms", msg$reactStr(reactId), msg$ctxStr(runningCtx))
private$appendEntry(domain, list(
action = "invalidateLater",
reactId = reactId,
ctxId = runningCtx,
millis = millis
))
},
idle = function(domain = NULL) {
msg$log("idle")
private$appendEntry(domain, list(
action = "idle"
))
},
asyncStart = function(domain = NULL) {
msg$log("asyncStart")
private$appendEntry(domain, list(
action = "asyncStart"
))
},
asyncStop = function(domain = NULL) {
msg$log("asyncStop")
private$appendEntry(domain, list(
action = "asyncStop"
))
},
freezeReactiveVal = function(reactId, domain) {
msg$log("freeze:", msg$reactStr(reactId))
private$appendEntry(domain, list(
action = "freeze",
reactId = reactId
))
},
freezeReactiveKey = function(reactId, key, domain) {
self$freezeReactiveVal(self$keyIdStr(reactId, key), domain)
},
thawReactiveVal = function(reactId, domain) {
msg$log("thaw:", msg$reactStr(reactId))
private$appendEntry(domain, list(
action = "thaw",
reactId = reactId
))
},
thawReactiveKey = function(reactId, key, domain) {
self$thawReactiveVal(self$keyIdStr(reactId, key), domain)
},
userMark = function(domain = NULL) {
msg$log("userMark")
private$appendEntry(domain, list(
action = "userMark"
))
}
)
)
MessageLogger <- R6Class(
"MessageLogger",
portable = FALSE,
public = list(
depth = 0L,
reactCache = list(),
option = "shiny.reactlog.console",
initialize = function(option = "shiny.reactlog.console", depth = 0L) {
if (!missing(depth)) self$depth <- depth
if (!missing(option)) self$option <- option
},
isLogging = function() {
isTRUE(getOption(self$option))
},
isNotLogging = function() {
!isTRUE(getOption(self$option))
},
depthIncrement = function() {
if (self$isNotLogging()) {
return(NULL)
}
self$depth <- self$depth + 1L
},
depthDecrement = function() {
if (self$isNotLogging()) {
return(NULL)
}
self$depth <- self$depth - 1L
},
hasReact = function(reactId) {
if (self$isNotLogging()) {
return(FALSE)
}
!is.null(self$getReact(reactId))
},
getReact = function(reactId, force = FALSE) {
if (identical(force, FALSE) && self$isNotLogging()) {
return(NULL)
}
self$reactCache[[reactId]]
},
setReact = function(reactObj, force = FALSE) {
if (identical(force, FALSE) && self$isNotLogging()) {
return(NULL)
}
self$reactCache[[reactObj$reactId]] <- reactObj
},
shortenString = function(txt, n = 250) {
if (is.null(txt) || isTRUE(is.na(txt))) {
return("")
}
if (nchar(txt) > n) {
return(
paste0(substr(txt, 1, n - 3), "...")
)
}
return(txt)
},
singleLine = function(txt) {
gsub("([^\\])\\n", "\\1\\\\n", txt)
},
valueStr = function(valueStr) {
paste0(
" '", self$shortenString(self$singleLine(valueStr)), "'"
)
},
reactStr = function(reactId) {
if (self$isNotLogging()) {
return(NULL)
}
reactInfo <- self$getReact(reactId)
if (is.null(reactInfo)) {
return(" <UNKNOWN_REACTID>")
}
paste0(
" ", reactInfo$reactId, ":'", self$shortenString(self$singleLine(reactInfo$label)), "'"
)
},
typeStr = function(type = NULL) {
self$ctxStr(ctxId = NULL, type = type)
},
ctxStr = function(ctxId = NULL, type = NULL) {
if (self$isNotLogging()) {
return(NULL)
}
self$ctxPrevCtxStr(ctxId = ctxId, prevCtxId = NULL, type = type)
},
ctxPrevCtxStr = function(ctxId = NULL, prevCtxId = NULL, type = NULL, preCtxIdTxt = " in ") {
if (self$isNotLogging()) {
return(NULL)
}
paste0(
if (!is.null(ctxId)) paste0(preCtxIdTxt, ctxId),
if (!is.null(prevCtxId)) paste0(" from ", prevCtxId),
if (!is.null(type) && !identical(type, "other")) paste0(" - ", type)
)
},
log = function(...) {
if (self$isNotLogging()) {
return(NULL)
}
msg <- paste0(
paste0(rep("= ", depth), collapse = ""), "- ", paste0(..., collapse = ""),
collapse = ""
)
message(msg)
}
)
)
on_load({
rLog <- RLog$new("shiny.reactlog", "shiny.reactlog.console")
})

95
R/history.R Normal file
View File

@@ -0,0 +1,95 @@
#' @include reactive-domains.R
NULL
#' @include reactives.R
NULL
#' Get the query string / hash component from the URL
#'
#' Two user friendly wrappers for getting the query string and the hash
#' component from the app's URL.
#'
#' These can be particularly useful if you want to display different content
#' depending on the values in the query string / hash (e.g. instead of basing
#' the conditional on an input or a calculated reactive, you can base it on the
#' query string). However, note that, if you're changing the query string / hash
#' programmatically from within the server code, you must use
#' `updateQueryString(_yourNewQueryString_, mode = "push")`. The default
#' `mode` for `updateQueryString` is `"replace"`, which doesn't
#' raise any events, so any observers or reactives that depend on it will
#' *not* get triggered. However, if you're changing the query string / hash
#' directly by typing directly in the browser and hitting enter, you don't have
#' to worry about this.
#'
#' @param session A Shiny session object.
#'
#' @return For `getQueryString`, a named list. For example, the query
#' string `?param1=value1&param2=value2` becomes `list(param1 =
#' value1, param2 = value2)`. For `getUrlHash`, a character vector with
#' the hash (including the leading `#` symbol).
#'
#' @seealso [updateQueryString()]
#'
#' @examples
#' ## Only run this example in interactive R sessions
#' if (interactive()) {
#'
#' ## App 1: getQueryString
#' ## Printing the value of the query string
#' ## (Use the back and forward buttons to see how the browser
#' ## keeps a record of each state)
#' shinyApp(
#' ui = fluidPage(
#' textInput("txt", "Enter new query string"),
#' helpText("Format: ?param1=val1&param2=val2"),
#' actionButton("go", "Update"),
#' hr(),
#' verbatimTextOutput("query")
#' ),
#' server = function(input, output, session) {
#' observeEvent(input$go, {
#' updateQueryString(input$txt, mode = "push")
#' })
#' output$query <- renderText({
#' query <- getQueryString()
#' queryText <- paste(names(query), query,
#' sep = "=", collapse=", ")
#' paste("Your query string is:\n", queryText)
#' })
#' }
#' )
#'
#' ## App 2: getUrlHash
#' ## Printing the value of the URL hash
#' ## (Use the back and forward buttons to see how the browser
#' ## keeps a record of each state)
#' shinyApp(
#' ui = fluidPage(
#' textInput("txt", "Enter new hash"),
#' helpText("Format: #hash"),
#' actionButton("go", "Update"),
#' hr(),
#' verbatimTextOutput("hash")
#' ),
#' server = function(input, output, session) {
#' observeEvent(input$go, {
#' updateQueryString(input$txt, mode = "push")
#' })
#' output$hash <- renderText({
#' hash <- getUrlHash()
#' paste("Your hash is:\n", hash)
#' })
#' }
#' )
#' }
#' @export
getQueryString <- function(session = getDefaultReactiveDomain()) {
parseQueryString(session$clientData$url_search)
}
#' @rdname getQueryString
#' @export
getUrlHash <- function(session = getDefaultReactiveDomain()) {
session$clientData$url_hash
}

24
R/hooks.R Normal file
View File

@@ -0,0 +1,24 @@
# Call an application hook. Application hooks are provided so that front ends
# can know when a Shiny application is running:
#
# shiny.onAppStart -- called when an application begins running
# shiny.onAppStop -- called when an appliation stops
#
# Both hooks are passed the url where the application is accessible (appUrl).
# Note that the appUrl can be NULL if the application was run on a UNIX domain
# socket rather than a TCP/IP port/
callAppHook <- function(name, appUrl) {
for (hook in getHooksList(paste0("shiny.", name)))
hook(appUrl)
}
# The value for getHook can be a single function or a list of functions,
# This function ensures that the result can always be processed as a list
getHooksList <- function(name) {
hooks <- getHook(name)
if (!is.list(hooks))
hooks <- list(hooks)
hooks
}

59
R/html-deps.R Normal file
View File

@@ -0,0 +1,59 @@
#' Create a web dependency
#'
#' Ensure that a file-based HTML dependency (from the htmltools package) can be
#' served over Shiny's HTTP server. This function works by using
#' [addResourcePath()] to map the HTML dependency's directory to a
#' URL.
#'
#' @param dependency A single HTML dependency object, created using
#' [htmltools::htmlDependency()]. If the `src` value is named,
#' then `href` and/or `file` names must be present.
#' @param scrubFile If TRUE (the default), remove `src$file` for the
#' dependency. This prevents the local file path from being sent to the client
#' when dynamic web dependencies are used. If FALSE, don't remove
#' `src$file`. Setting it to FALSE should be needed only in very unusual
#' cases.
#'
#' @return A single HTML dependency object that has an `href`-named element
#' in its `src`.
#' @export
createWebDependency <- function(dependency, scrubFile = TRUE) {
if (is.null(dependency))
return(NULL)
if (!inherits(dependency, "html_dependency"))
stop("Unexpected non-html_dependency type")
if (is.null(dependency$src$href)) {
prefix <- paste(dependency$name, "-", dependency$version, sep = "")
addResourcePath(prefix, dependency$src$file)
dependency$src$href <- prefix
}
# Don't leak local file path to client
if (scrubFile)
dependency$src$file <- NULL
return(dependency)
}
# Given a Shiny tag object, process singletons and dependencies. Returns a list
# with rendered HTML and dependency objects.
# This implementation is very similar to renderTags(), but ignores
# <head> handling (it should only be used after the user session has started)
processDeps <- function(tags, session) {
tags <- utils::getFromNamespace("tagify", "htmltools")(tags)
ui <- takeSingletons(tags, session$singletons, desingleton = FALSE)$ui
ui <- surroundSingletons(ui)
dependencies <- lapply(
resolveDependencies(findDependencies(ui, tagify = FALSE)),
createWebDependency
)
names(dependencies) <- NULL
list(
html = doRenderTags(ui),
deps = dependencies
)
}

141
R/image-interact-opts.R Normal file
View File

@@ -0,0 +1,141 @@
#' Control interactive plot point events
#'
#' These functions give control over the `click`, `dblClick` and
#' `hover` events generated by [imageOutput()] and [plotOutput()].
#'
#' @param id Input value name. For example, if the value is `"plot_click"`,
#' then the event data will be available as `input$plot_click`.
#' @param clip Should the click area be clipped to the plotting area? If
#' `FALSE`, then the server will receive click events even when the mouse is
#' outside the plotting area, as long as it is still inside the image.
#' @param delay For `dblClickOpts()`: the maximum delay (in ms) between a
#' pair clicks for them to be counted as a double-click.
#'
#' For `hoverOpts()`: how long to delay (in ms) when debouncing or throttling
#' before sending the mouse location to the server.
#' @param delayType The type of algorithm for limiting the number of hover
#' events. Use `"throttle"` to limit the number of hover events to one
#' every `delay` milliseconds. Use `"debounce"` to suspend events
#' while the cursor is moving, and wait until the cursor has been at rest for
#' `delay` milliseconds before sending an event.
#' @seealso [brushOpts()] for brushing events.
#' @export
clickOpts <- function(id, clip = TRUE) {
if (is.null(id))
stop("id must not be NULL")
list(
id = id,
clip = clip
)
}
#' @export
#' @rdname clickOpts
dblclickOpts <- function(id, clip = TRUE, delay = 400) {
if (is.null(id))
stop("id must not be NULL")
list(
id = id,
clip = clip,
delay = delay
)
}
#' @param nullOutside If `TRUE` (the default), the value will be set to
#' `NULL` when the mouse exits the plotting area. If `FALSE`, the
#' value will stop changing when the cursor exits the plotting area.
#' @export
#' @rdname clickOpts
hoverOpts <- function(id, delay = 300,
delayType = c("debounce", "throttle"), clip = TRUE,
nullOutside = TRUE) {
if (is.null(id))
stop("id must not be NULL")
list(
id = id,
delay = delay,
delayType = match.arg(delayType),
clip = clip,
nullOutside = nullOutside
)
}
#' Create an object representing brushing options
#'
#' This generates an object representing brushing options, to be passed as the
#' `brush` argument of [imageOutput()] or
#' [plotOutput()].
#'
#' @param id Input value name. For example, if the value is `"plot_brush"`,
#' then the coordinates will be available as `input$plot_brush`. Multiple
#' `imageOutput`/`plotOutput` calls may share the same `id`
#' value; brushing one image or plot will cause any other brushes with the
#' same `id` to disappear.
#' @param fill Fill color of the brush. If `'auto'`, it derives from the link
#' color of the plot's HTML container (if **thematic** is enabled, and `accent`
#' is a non-`'auto'` value, that color is used instead).
#' @param stroke Outline color of the brush. If `'auto'`, it derives from the
#' foreground color of the plot's HTML container (if **thematic** is enabled,
#' and `fg` is a non-`'auto'` value, that color is used instead).
#' @param opacity Opacity of the brush
#' @param delay How long to delay (in milliseconds) when debouncing or
#' throttling, before sending the brush data to the server.
#' @param delayType The type of algorithm for limiting the number of brush
#' events. Use `"throttle"` to limit the number of brush events to one
#' every `delay` milliseconds. Use `"debounce"` to suspend events
#' while the cursor is moving, and wait until the cursor has been at rest for
#' `delay` milliseconds before sending an event.
#' @param clip Should the brush area be clipped to the plotting area? If FALSE,
#' then the user will be able to brush outside the plotting area, as long as
#' it is still inside the image.
#' @param direction The direction for brushing. If `"xy"`, the brush can be
#' drawn and moved in both x and y directions. If `"x"`, or `"y"`,
#' the brush wil work horizontally or vertically.
#' @param resetOnNew When a new image is sent to the browser (via
#' [renderImage()]), should the brush be reset? The default,
#' `FALSE`, is useful if you want to update the plot while keeping the
#' brush. Using `TRUE` is useful if you want to clear the brush whenever
#' the plot is updated.
#' @seealso [clickOpts()] for clicking events.
#' @export
brushOpts <- function(id, fill = "#9cf", stroke = "#036",
opacity = 0.25, delay = 300,
delayType = c("debounce", "throttle"), clip = TRUE,
direction = c("xy", "x", "y"),
resetOnNew = FALSE) {
if (is.null(id))
stop("id must not be NULL")
if (identical(fill, "auto")) {
fill <- getThematicOption("accent", "auto")
}
if (identical(stroke, "auto")) {
stroke <- getThematicOption("fg", "auto")
}
list(
id = id,
fill = fill,
stroke = stroke,
opacity = opacity,
delay = delay,
delayType = match.arg(delayType),
clip = clip,
direction = match.arg(direction),
resetOnNew = resetOnNew
)
}
getThematicOption <- function(name = "", default = NULL, resolve = FALSE) {
if (isNamespaceLoaded("thematic")) {
# TODO: use :: once thematic is on CRAN
tgo <- utils::getFromNamespace("thematic_get_option", "thematic")
tgo(name = name, default = default, resolve = resolve)
} else {
default
}
}

532
R/image-interact.R Normal file
View File

@@ -0,0 +1,532 @@
#' Find rows of data selected on an interactive plot.
#'
#' @description
#' `brushedPoints()` returns rows from a data frame which are under a brush.
#' `nearPoints()` returns rows from a data frame which are near a click, hover,
#' or double-click. Alternatively, set `allRows = TRUE` to return all rows from
#' the input data with an additional column `selected_` that indicates which
#' rows of the would be selected.
#'
#' @section ggplot2:
#' For plots created with ggplot2, it is not necessary to specify the
#' column names to `xvar`, `yvar`, `panelvar1`, and `panelvar2` as that
#' information can be automatically derived from the plot specification.
#'
#' Note, however, that this will not work if you use a computed column, like
#' `aes(speed/2, dist))`. Instead, we recommend that you modify the data
#' first, and then make the plot with "raw" columns in the modified data.
#'
#' @section Brushing:
#' If x or y column is a factor, then it will be coerced to an integer vector.
#' If it is a character vector, then it will be coerced to a factor and then
#' integer vector. This means that the brush will be considered to cover a
#' given character/factor value when it covers the center value.
#'
#' If the brush is operating in just the x or y directions (e.g., with
#' `brushOpts(direction = "x")`, then this function will filter out points
#' using just the x or y variable, whichever is appropriate.
#'
#' @returns
#' A data frame based on `df`, containing the observations selected by the
#' brush or near the click event. For `nearPoints()`, the rows will be sorted
#' by distance to the event.
#'
#' If `allRows = TRUE`, then all rows will returned, along with a new
#' `selected_` column that indicates whether or not the point was selected.
#' The output from `nearPoints()` will no longer be sorted, but you can
#' set `addDist = TRUE` to get an additional column that gives the pixel
#' distance to the pointer.
#'
#' @param df A data frame from which to select rows.
#' @param brush,coordinfo The data from a brush or click/dblclick/hover event
#' e.g. `input$plot_brush`, `input$plot_click`.
#' @param xvar,yvar A string giving the name of the variable on the x or y axis.
#' These are only required for base graphics, and must be the name of
#' a column in `df`.
#' @param panelvar1,panelvar2 A string giving the name of a panel variable.
#' For expert use only; in most cases these will be automatically
#' derived from the ggplot2 spec.
#' @param allRows If `FALSE` (the default) return a data frame containing
#' the selected rows. If `TRUE`, the input data frame will have a new
#' column, `selected_`, which indicates whether the row was selected or not.
#' @param threshold A maximum distance (in pixels) to the pointer location.
#' Rows in the data frame will be selected if the distance to the pointer is
#' less than `threshold`.
#' @param maxpoints Maximum number of rows to return. If `NULL` (the default),
#' will return all rows within the threshold distance.
#' @param addDist If TRUE, add a column named `dist_` that contains the
#' distance from the coordinate to the point, in pixels. When no pointer
#' event has yet occurred, the value of `dist_` will be `NA`.
#' @seealso [plotOutput()] for example usage.
#' @export
#' @examples
#' \dontrun{
#' # Note that in practice, these examples would need to go in reactives
#' # or observers.
#'
#' # This would select all points within 5 pixels of the click
#' nearPoints(mtcars, input$plot_click)
#'
#' # Select just the nearest point within 10 pixels of the click
#' nearPoints(mtcars, input$plot_click, threshold = 10, maxpoints = 1)
#'
#' }
brushedPoints <- function(df, brush, xvar = NULL, yvar = NULL,
panelvar1 = NULL, panelvar2 = NULL,
allRows = FALSE) {
if (is.null(brush)) {
if (allRows)
df$selected_ <- FALSE
else
df <- df[0, , drop = FALSE]
return(df)
}
if (is.null(brush$xmin)) {
stop("brushedPoints requires a brush object with xmin, xmax, ymin, and ymax.")
}
# Which direction(s) the brush is selecting over. Direction can be 'x', 'y',
# or 'xy'.
use_x <- grepl("x", brush$direction)
use_y <- grepl("y", brush$direction)
# We transitioned to using %||% in Shiny 1.6.0. Previously, these vars could
# be NA, because the old %OR% operator recognized NA. These warnings and
# the NULL replacement are here just to ease the transition in case anyone is
# using NA. We can remove these checks in a future version of Shiny.
# https://github.com/rstudio/shiny/pull/3172
if (is_na(xvar)) { xvar <- NULL; warning("xvar should be NULL, not NA.") }
if (is_na(yvar)) { yvar <- NULL; warning("yvar should be NULL, not NA.") }
if (is_na(panelvar1)) { panelvar1 <- NULL; warning("panelvar1 should be NULL, not NA.") }
if (is_na(panelvar2)) { panelvar2 <- NULL; warning("panelvar2 should be NULL, not NA.") }
# Try to extract vars from brush object
xvar <- xvar %||% brush$mapping$x
yvar <- yvar %||% brush$mapping$y
panelvar1 <- panelvar1 %||% brush$mapping$panelvar1
panelvar2 <- panelvar2 %||% brush$mapping$panelvar2
# Filter out x and y values
keep_rows <- rep(TRUE, nrow(df))
if (use_x) {
if (is.null(xvar))
stop("brushedPoints: not able to automatically infer `xvar` from brush")
if (!(xvar %in% names(df)))
stop("brushedPoints: `xvar` ('", xvar ,"') not in names of input")
keep_rows <- keep_rows & within_brush(df[[xvar]], brush, "x")
}
if (use_y) {
if (is.null(yvar))
stop("brushedPoints: not able to automatically infer `yvar` from brush")
if (!(yvar %in% names(df)))
stop("brushedPoints: `yvar` ('", yvar ,"') not in names of input")
keep_rows <- keep_rows & within_brush(df[[yvar]], brush, "y")
}
# Find which rows are matches for the panel vars (if present)
if (!is.null(panelvar1))
keep_rows <- keep_rows & panelMatch(brush$panelvar1, df[[panelvar1]])
if (!is.null(panelvar2))
keep_rows <- keep_rows & panelMatch(brush$panelvar2, df[[panelvar2]])
if (allRows) {
df$selected_ <- keep_rows
df
} else {
df[keep_rows, , drop = FALSE]
}
}
# The `brush` data structure will look something like the examples below.
# For base graphics, `mapping` is empty, and there are no panelvars:
# List of 8
# $ xmin : num 3.73
# $ xmax : num 4.22
# $ ymin : num 13.9
# $ ymax : num 19.8
# $ coords_css:List of 4
# ..$ xmin: int 260
# ..$ xmax: int 298
# ..$ ymin: num 112
# ..$ ymax: num 205
# $ coords_img:List of 4
# ..$ xmin: int 325
# ..$ xmax: num 372
# ..$ ymin: num 140
# ..$ ymax: num 257
# $ img_css_ratio:List of 2
# ..$ x: num 1.25
# ..$ y: num 1.25
# $ mapping: Named list()
# $ domain :List of 4
# ..$ left : num 1.36
# ..$ right : num 5.58
# ..$ bottom: num 9.46
# ..$ top : num 34.8
# $ range :List of 4
# ..$ left : num 58
# ..$ right : num 429
# ..$ bottom: num 226
# ..$ top : num 58
# $ log :List of 2
# ..$ x: NULL
# ..$ y: NULL
# $ direction: chr "y"
#
# For ggplot2, the mapping vars usually will be included, and if faceting is
# used, they will be listed as panelvars:
# List of 10
# $ xmin : num 3.18
# $ xmax : num 3.78
# $ ymin : num 17.1
# $ ymax : num 20.4
# $ panelvar1: chr "6"
# $ panelvar2: chr "0
# $ coords_css:List of 4
# ..$ xmin: int 260
# ..$ xmax: int 298
# ..$ ymin: num 112
# ..$ ymax: num 205
# $ coords_img:List of 4
# ..$ xmin: int 325
# ..$ xmax: num 372
# ..$ ymin: num 140
# ..$ ymax: num 257
# $ img_css_ratio:List of 2
# ..$ x: num 1.25
# ..$ y: num 1.25
# $ mapping :List of 4
# ..$ x : chr "wt"
# ..$ y : chr "mpg"
# ..$ panelvar1: chr "cyl"
# ..$ panelvar2: chr "am"
# $ domain :List of 4
# ..$ left : num 1.32
# ..$ right : num 5.62
# ..$ bottom: num 9.22
# ..$ top : num 35.1
# $ range :List of 4
# ..$ left : num 172
# ..$ right : num 300
# ..$ bottom: num 144
# ..$ top : num 28.5
# $ log :List of 2
# ..$ x: NULL
# ..$ y: NULL
# $ direction: chr "y"
#' @export
#' @rdname brushedPoints
nearPoints <- function(df, coordinfo, xvar = NULL, yvar = NULL,
panelvar1 = NULL, panelvar2 = NULL,
threshold = 5, maxpoints = NULL, addDist = FALSE,
allRows = FALSE) {
if (is.null(coordinfo)) {
if (addDist)
df$dist_ <- NA_real_
if (allRows)
df$selected_ <- FALSE
else
df <- df[0, , drop = FALSE]
return(df)
}
if (is.null(coordinfo$x)) {
stop("nearPoints requires a click/hover/double-click object with x and y values.")
}
# We transitioned to using %||% in Shiny 1.6.0. Previously, these vars could
# be NA, because the old %OR% operator recognized NA. These warnings and
# the NULL replacement are here just to ease the transition in case anyone is
# using NA. We can remove these checks in a future version of Shiny.
# https://github.com/rstudio/shiny/pull/3172
if (is_na(xvar)) { xvar <- NULL; warning("xvar should be NULL, not NA.") }
if (is_na(yvar)) { yvar <- NULL; warning("yvar should be NULL, not NA.") }
if (is_na(panelvar1)) { panelvar1 <- NULL; warning("panelvar1 should be NULL, not NA.") }
if (is_na(panelvar2)) { panelvar2 <- NULL; warning("panelvar2 should be NULL, not NA.") }
# Try to extract vars from coordinfo object
xvar <- xvar %||% coordinfo$mapping$x
yvar <- yvar %||% coordinfo$mapping$y
panelvar1 <- panelvar1 %||% coordinfo$mapping$panelvar1
panelvar2 <- panelvar2 %||% coordinfo$mapping$panelvar2
if (is.null(xvar))
stop("nearPoints: not able to automatically infer `xvar` from coordinfo")
if (is.null(yvar))
stop("nearPoints: not able to automatically infer `yvar` from coordinfo")
if (!(xvar %in% names(df)))
stop("nearPoints: `xvar` ('", xvar ,"') not in names of input")
if (!(yvar %in% names(df)))
stop("nearPoints: `yvar` ('", yvar ,"') not in names of input")
# Extract data values from the data frame
coordinfo <- fortifyDiscreteLimits(coordinfo)
x <- asNumber(df[[xvar]], coordinfo$domain$discrete_limits$x)
y <- asNumber(df[[yvar]], coordinfo$domain$discrete_limits$y)
# Get the coordinates of the point (in img pixel coordinates)
point_img <- coordinfo$coords_img
# Get coordinates of data points (in img pixel coordinates)
data_img <- scaleCoords(x, y, coordinfo)
# Get x/y distances (in css coordinates)
dist_css <- list(
x = (data_img$x - point_img$x) / coordinfo$img_css_ratio$x,
y = (data_img$y - point_img$y) / coordinfo$img_css_ratio$y
)
# Distances of data points to the target point, in css pixels.
dists <- sqrt(dist_css$x^2 + dist_css$y^2)
if (addDist)
df$dist_ <- dists
keep_rows <- (dists <= threshold)
# Find which rows are matches for the panel vars (if present)
if (!is.null(panelvar1))
keep_rows <- keep_rows & panelMatch(coordinfo$panelvar1, df[[panelvar1]])
if (!is.null(panelvar2))
keep_rows <- keep_rows & panelMatch(coordinfo$panelvar2, df[[panelvar2]])
# Track the indices to keep
keep_idx <- which(keep_rows)
# Order by distance
dists <- dists[keep_idx]
keep_idx <- keep_idx[order(dists)]
# Keep max number of rows
if (!is.null(maxpoints) && length(keep_idx) > maxpoints) {
keep_idx <- keep_idx[seq_len(maxpoints)]
}
if (allRows) {
# Add selected_ column if needed
df$selected_ <- FALSE
df$selected_[keep_idx] <- TRUE
} else {
# If we don't keep all rows, return just the selected rows, sorted by
# distance.
df <- df[keep_idx, , drop = FALSE]
}
df
}
# The coordinfo data structure will look something like the examples below.
# For base graphics, `mapping` is empty, and there are no panelvars:
# List of 7
# $ x : num 4.37
# $ y : num 12
# $ coords_css:List of 2
# ..$ x: int 286
# ..$ y: int 192
# $ coords_img:List of 2
# ..$ x: num 358
# ..$ y: int 240
# $ img_css_ratio:List of 2
# ..$ x: num 1.25
# ..$ y: num 1.25
# $ mapping : Named list()
# $ domain :List of 4
# ..$ left : num 1.36
# ..$ right : num 5.58
# ..$ bottom: num 9.46
# ..$ top : num 34.8
# $ range :List of 4
# ..$ left : num 58
# ..$ right : num 429
# ..$ bottom: num 226
# ..$ top : num 58
# $ log :List of 2
# ..$ x: NULL
# ..$ y: NULL
# $ .nonce : num 0.343
#
# For ggplot2, the mapping vars usually will be included, and if faceting is
# used, they will be listed as panelvars:
# List of 9
# $ x : num 3.78
# $ y : num 17.1
# $ coords_css:List of 2
# ..$ x: int 286
# ..$ y: int 192
# $ coords_img:List of 2
# ..$ x: num 358
# ..$ y: int 240
# $ img_css_ratio:List of 2
# ..$ x: num 1.25
# ..$ y: num 1.25
# $ panelvar1 : chr "6"
# $ panelvar2 : chr "0"
# $ mapping :List of 4
# ..$ x : chr "wt"
# ..$ y : chr "mpg"
# ..$ panelvar1: chr "cyl"
# ..$ panelvar2: chr "am"
# $ domain :List of 4
# ..$ left : num 1.32
# ..$ right : num 5.62
# ..$ bottom: num 9.22
# ..$ top : num 35.1
# $ range :List of 4
# ..$ left : num 172
# ..$ right : num 300
# ..$ bottom: num 144
# ..$ top : num 28.5
# $ log :List of 2
# ..$ x: NULL
# ..$ y: NULL
# $ .nonce : num 0.603
# Helper to determine if data values are within the limits of
# an input brush
within_brush <- function(vals, brush, var = "x") {
var <- match.arg(var, c("x", "y"))
brush <- fortifyDiscreteLimits(brush)
vals <- asNumber(vals, brush$domain$discrete_limits[[var]])
# It's possible for a non-missing data values to not
# map to the axis limits, for example:
# https://github.com/rstudio/shiny/pull/2410#issuecomment-488100881
!is.na(vals) &
vals >= brush[[paste0(var, "min")]] &
vals <= brush[[paste0(var, "max")]]
}
# Coerce various types of variables to numbers. This works for Date, POSIXt,
# characters, and factors. Used because the mouse coords are numeric.
# The `levels` argument should be used when mapping this variable to
# a known set of discrete levels, which is needed for ggplot2 since
# it allows you to control ordering and possible values of a discrete
# positional scale (#2410)
asNumber <- function(x, levels = NULL) {
if (length(levels)) return(match(x, levels))
if (is.character(x)) x <- as.factor(x)
if (is.factor(x)) x <- as.integer(x)
as.numeric(x)
}
# Ensure the discrete limits/levels of a coordmap received
# from the client matches the data structure sent the client.
#
# When we construct the coordmap (in getGgplotCoordmap()),
# we save a character vector which may contain missing values
# (e.g., c("a", "b", NA)). When that same character is received
# from the client, it runs through decodeMessage() which sets
# simplifyVector=FALSE, which means NA are replaced by NULL
# (because jsonlite::fromJSON('["a", "b", null]') -> list("a", "b", NULL))
#
# Thankfully, it doesn't seem like it's meaningful for limits to
# contains a NULL in the 1st place, so we simply treat NULL like NA.
# For more context, https://github.com/rstudio/shiny/issues/2666
fortifyDiscreteLimits <- function(coord) {
# Note that discrete_limits$x/y are populated iff
# x/y are discrete mappings
coord$domain$discrete_limits <- lapply(
coord$domain$discrete_limits,
function(var) {
# if there is an 'explicit' NULL, then the limits are NA
if (is.null(var)) return(NA)
vapply(var, function(x) {
if (is.null(x) || isTRUE(is.na(x))) NA_character_ else x
}, character(1))
}
)
coord
}
# Given a panelvar value and a vector x, return logical vector indicating which
# items match the panelvar value. Because the panelvar value is always a
# string but the vector could be numeric, it might be necessary to coerce the
# panelvar to a number before comparing to the vector.
panelMatch <- function(search_value, x) {
if (is.null(search_value)) return(is.na(x))
if (is.numeric(x)) search_value <- as.numeric(search_value)
x == search_value
}
# ----------------------------------------------------------------------------
# Scaling functions
# These functions have direct analogs in Javascript code, except these are
# vectorized for x and y.
# Map a value x from a domain to a range. If clip is true, clip it to the
# range.
mapLinear <- function(x, domainMin, domainMax, rangeMin, rangeMax, clip = TRUE) {
factor <- (rangeMax - rangeMin) / (domainMax - domainMin)
val <- x - domainMin
newval <- (val * factor) + rangeMin
if (clip) {
maxval <- max(rangeMax, rangeMin)
minval <- min(rangeMax, rangeMin)
newval[newval > maxval] <- maxval
newval[newval < minval] <- minval
}
newval
}
# Scale val from domain to range. If logbase is present, use log scaling.
scale1D <- function(val, domainMin, domainMax, rangeMin, rangeMax,
logbase = NULL, clip = TRUE) {
if (!is.null(logbase))
val <- log(val, logbase)
mapLinear(val, domainMin, domainMax, rangeMin, rangeMax, clip)
}
# Inverse scale val, from range to domain. If logbase is present, use inverse
# log (power) transformation.
scaleInv1D <- function(val, domainMin, domainMax, rangeMin, rangeMax,
logbase = NULL, clip = TRUE) {
res <- mapLinear(val, rangeMin, rangeMax, domainMin, domainMax, clip)
if (!is.null(logbase))
res <- logbase ^ res
res
}
# Scale x and y coordinates from domain to range, using information in
# scaleinfo. scaleinfo must contain items $domain, $range, and $log. The
# scaleinfo object corresponds to one element from the coordmap object generated
# by getPrevPlotCoordmap or getGgplotCoordmap; it is the scaling information for
# one panel in a plot.
scaleCoords <- function(x, y, scaleinfo) {
if (is.null(scaleinfo))
return(NULL)
domain <- scaleinfo$domain
range <- scaleinfo$range
log <- scaleinfo$log
list(
x = scale1D(x, domain$left, domain$right, range$left, range$right, log$x),
y = scale1D(y, domain$bottom, domain$top, range$bottom, range$top, log$y)
)
}
# Inverse scale x and y coordinates from range to domain, using information in
# scaleinfo.
scaleInvCoords <- function(x, y, scaleinfo) {
if (is.null(scaleinfo))
return(NULL)
domain <- scaleinfo$domain
range <- scaleinfo$range
log <- scaleinfo$log
list(
x = scaleInv1D(x, domain$left, domain$right, range$left, range$right, log$x),
y = scaleInv1D(y, domain$bottom, domain$top, range$bottom, range$top, log$y)
)
}

View File

@@ -1,53 +1,132 @@
#' Run a plotting function and save the output as a PNG
startPNG <- function(filename, width, height, res, ...) {
pngfun <- if ((getOption('shiny.useragg') %||% TRUE) && is_installed("ragg")) {
ragg::agg_png
} else if (capabilities("aqua")) {
# i.e., png(type = 'quartz')
grDevices::png
} else if ((getOption('shiny.usecairo') %||% TRUE) && is_installed("Cairo")) {
Cairo::CairoPNG
} else {
# i.e., png(type = 'cairo')
grDevices::png
}
args <- list2(filename = filename, width = width, height = height, res = res, ...)
# It's possible for width/height to be NULL/numeric(0) (e.g., when using
# suspendWhenHidden=F w/ tabsetPanel(), see rstudio/shiny#1409), so when
# this happens let the device determine what the default size should be.
if (length(args$width) == 0) args$width <- NULL
if (length(args$height) == 0) args$height <- NULL
# Set a smarter default for the device's bg argument (based on thematic's global state).
# Note that, technically, this is really only needed for CairoPNG, since the other
# devices allow their bg arg to be overridden by par(bg=...), which thematic does prior
# to plot-time, but it shouldn't hurt to inform other the device directly as well
if (is.null(args$bg) && isNamespaceLoaded("thematic")) {
args$bg <- getThematicOption("bg", "white")
# auto vals aren't resolved until plot time, so if we see one, resolve it
if (isTRUE("auto" == args$bg)) {
args$bg <- getCurrentOutputInfo()[["bg"]]()
}
}
# Handle both bg and background device arg
# https://github.com/r-lib/ragg/issues/35
fmls <- names(formals(pngfun))
if (("background" %in% fmls) && (!"bg" %in% fmls)) {
if (is.null(args$background)) {
args$background <- args$bg
}
args$bg <- NULL
}
do.call(pngfun, args)
# Call plot.new() so that even if no plotting operations are performed at
# least we have a blank background. N.B. we need to set the margin to 0
# temporarily before plot.new() because when the plot size is small (e.g.
# 200x50), we will get an error "figure margin too large", which is triggered
# by plot.new() with the default (large) margin. However, this does not
# guarantee user's code in func() will not trigger the error -- they may have
# to set par(mar = smaller_value) before they draw base graphics.
op <- graphics::par(mar = rep(0, 4))
tryCatch(
graphics::plot.new(),
finally = graphics::par(op)
)
grDevices::dev.cur()
}
#' Capture a plot as a PNG file.
#'
#' This function returns the name of the PNG file that it generates. In
#' essence, it calls \code{png()}, then \code{func()}, then \code{dev.off()}.
#' So \code{func} must be a function that will generate a plot when used this
#' way.
#' The PNG graphics device used is determined in the following order:
#' * If the ragg package is installed (and the `shiny.useragg` is not
#' set to `FALSE`), then use [ragg::agg_png()].
#' * If a quartz device is available (i.e., `capabilities("aqua")` is
#' `TRUE`), then use `png(type = "quartz")`.
#' * If the Cairo package is installed (and the `shiny.usecairo` option
#' is not set to `FALSE`), then use [Cairo::CairoPNG()].
#' * Otherwise, use [grDevices::png()]. In this case, Linux and Windows
#' may not antialias some point shapes, resulting in poor quality output.
#'
#' For output, it will try to use the following devices, in this order:
#' quartz (via \code{\link[grDevices]{png}}), then \code{\link[Cairo]{CairoPNG}},
#' and finally \code{\link[grDevices]{png}}. This is in order of quality of
#' output. Notably, plain \code{png} output on Linux and Windows may not
#' antialias some point shapes, resulting in poor quality output.
#' @details
#' A `NULL` value provided to `width` or `height` is ignored (i.e., the
#' default `width` or `height` of the graphics device is used).
#'
#' @param func A function that generates a plot.
#' @param filename The name of the output file. Defaults to a temp file with
#' extension \code{.png}.
#' extension `.png`.
#' @param width Width in pixels.
#' @param height Height in pixels.
#' @param res Resolution in pixels per inch. This value is passed to
#' \code{\link{png}}. Note that this affects the resolution of PNG rendering in
#' @param res Resolution in pixels per inch. This value is passed to the
#' graphics device. Note that this affects the resolution of PNG rendering in
#' R; it won't change the actual ppi of the browser.
#' @param ... Arguments to be passed through to \code{\link[grDevices]{png}}.
#' These can be used to set the width, height, background color, etc.
#' @param ... Arguments to be passed through to the graphics device. These can
#' be used to set the width, height, background color, etc.
#'
#' @return A path to the newly generated PNG file.
#'
#' @export
plotPNG <- function(func, filename=tempfile(fileext='.png'),
width=400, height=400, res=72, ...) {
# If quartz is available, use png() (which will default to quartz).
# Otherwise, if the Cairo package is installed, use CairoPNG().
# Finally, if neither quartz nor Cairo, use png().
if (capabilities("aqua")) {
pngfun <- png
} else if (nchar(system.file(package = "Cairo"))) {
require(Cairo)
# Workaround for issue #140: Cairo ignores res and dpi settings. Need to
# use regular png function.
if (res == 72) {
pngfun <- Cairo::CairoPNG
} else {
pngfun <- png
}
} else {
pngfun <- png
}
do.call(pngfun, c(filename=filename, width=width, height=height, res=res, list(...)))
tryCatch(
func(),
finally=dev.off())
dv <- startPNG(filename, width, height, res, ...)
on.exit(grDevices::dev.off(dv), add = TRUE)
func()
filename
}
createGraphicsDevicePromiseDomain <- function(which = dev.cur()) {
force(which)
new_promise_domain(
wrapOnFulfilled = function(onFulfilled) {
force(onFulfilled)
function(...) {
old <- dev.cur()
dev.set(which)
on.exit(dev.set(old))
onFulfilled(...)
}
},
wrapOnRejected = function(onRejected) {
force(onRejected)
function(...) {
old <- dev.cur()
dev.set(which)
on.exit(dev.set(old))
onRejected(...)
}
},
wrapSync = function(expr) {
old <- dev.cur()
dev.set(which)
on.exit(dev.set(old))
force(expr)
}
)
}

122
R/input-action.R Normal file
View File

@@ -0,0 +1,122 @@
#' Action button/link
#'
#' Creates an action button or link whose value is initially zero, and increments by one
#' each time it is pressed.
#'
#' @inheritParams textInput
#' @param label The contents of the button or link--usually a text label, but
#' you could also use any other HTML, like an image.
#' @param icon An optional [icon()] to appear on the button.
#' @param disabled If `TRUE`, the button will not be clickable. Use
#' [updateActionButton()] to dynamically enable/disable the button.
#' @param ... Named attributes to be applied to the button or link.
#'
#' @family input elements
#' @examples
#' ## Only run examples in interactive R sessions
#' if (interactive()) {
#'
#' ui <- fluidPage(
#' sliderInput("obs", "Number of observations", 0, 1000, 500),
#' actionButton("goButton", "Go!", class = "btn-success"),
#' plotOutput("distPlot")
#' )
#'
#' server <- function(input, output) {
#' output$distPlot <- renderPlot({
#' # Take a dependency on input$goButton. This will run once initially,
#' # because the value changes from NULL to 0.
#' input$goButton
#'
#' # Use isolate() to avoid dependency on input$obs
#' dist <- isolate(rnorm(input$obs))
#' hist(dist)
#' })
#' }
#'
#' shinyApp(ui, server)
#'
#' }
#'
#' ## Example of adding extra class values
#' actionButton("largeButton", "Large Primary Button", class = "btn-primary btn-lg")
#' actionLink("infoLink", "Information Link", class = "btn-info")
#'
#' @seealso [observeEvent()] and [eventReactive()]
#'
#' @section Server value:
#' An integer of class `"shinyActionButtonValue"`. This class differs from
#' ordinary integers in that a value of 0 is considered "falsy".
#' This implies two things:
#' * Event handlers (e.g., [observeEvent()], [eventReactive()]) won't execute on initial load.
#' * Input validation (e.g., [req()], [need()]) will fail on initial load.
#' @export
actionButton <- function(inputId, label, icon = NULL, width = NULL,
disabled = FALSE, ...) {
value <- restoreInput(id = inputId, default = NULL)
icon <- validateIcon(icon)
if (!is.null(icon)) {
icon <- span(icon, class = "action-icon")
}
if (!is.null(label)) {
label <- span(label, class = "action-label")
}
tags$button(
id = inputId,
style = css(width = validateCssUnit(width)),
type = "button",
class = "btn btn-default action-button",
`data-val` = value,
disabled = if (isTRUE(disabled)) NA else NULL,
icon, label,
...
)
}
#' @rdname actionButton
#' @export
actionLink <- function(inputId, label, icon = NULL, ...) {
value <- restoreInput(id = inputId, default = NULL)
icon <- validateIcon(icon)
if (!is.null(icon)) {
icon <- span(icon, class = "action-icon")
}
if (!is.null(label)) {
label <- span(label, class = "action-label")
}
tags$a(
id = inputId,
href = "#",
class = "action-button action-link",
`data-val` = value,
icon, label,
...
)
}
# Throw an informative warning if icon isn't html-ish
validateIcon <- function(icon) {
if (length(icon) == 0) {
return(icon)
}
if (!isTagLike(icon)) {
rlang::warn(
c(
"It appears that a non-HTML value was provided to `icon`.",
i = "Try using a `shiny::icon()` (or an equivalent) to get an icon."
),
class = "shiny-validate-icon"
)
}
icon
}

44
R/input-checkbox.R Normal file
View File

@@ -0,0 +1,44 @@
#' Checkbox Input Control
#'
#' Create a checkbox that can be used to specify logical values.
#'
#' @inheritParams textInput
#' @param value Initial value (`TRUE` or `FALSE`).
#' @return A checkbox control that can be added to a UI definition.
#'
#' @family input elements
#' @seealso [checkboxGroupInput()], [updateCheckboxInput()]
#'
#' @examples
#' ## Only run examples in interactive R sessions
#' if (interactive()) {
#'
#' ui <- fluidPage(
#' checkboxInput("somevalue", "Some value", FALSE),
#' verbatimTextOutput("value")
#' )
#' server <- function(input, output) {
#' output$value <- renderText({ input$somevalue })
#' }
#' shinyApp(ui, server)
#' }
#'
#' @section Server value:
#' `TRUE` if checked, `FALSE` otherwise.
#'
#' @export
checkboxInput <- function(inputId, label, value = FALSE, width = NULL) {
value <- restoreInput(id = inputId, default = value)
inputTag <- tags$input(id = inputId, type="checkbox", class = "shiny-input-checkbox")
if (!is.null(value) && value)
inputTag$attribs$checked <- "checked"
div(class = "form-group shiny-input-container",
style = css(width = validateCssUnit(width)),
div(class = "checkbox",
tags$label(inputTag, tags$span(label))
)
)
}

107
R/input-checkboxgroup.R Normal file
View File

@@ -0,0 +1,107 @@
#' Checkbox Group Input Control
#'
#' Create a group of checkboxes that can be used to toggle multiple choices
#' independently. The server will receive the input as a character vector of the
#' selected values.
#'
#' @inheritParams textInput
#' @param choices List of values to show checkboxes for. If elements of the list
#' are named then that name rather than the value is displayed to the user. If
#' this argument is provided, then `choiceNames` and `choiceValues`
#' must not be provided, and vice-versa. The values should be strings; other
#' types (such as logicals and numbers) will be coerced to strings.
#' @param selected The values that should be initially selected, if any.
#' @param inline If `TRUE`, render the choices inline (i.e. horizontally)
#' @param choiceNames,choiceValues List of names and values, respectively,
#' that are displayed to the user in the app and correspond to the each
#' choice (for this reason, `choiceNames` and `choiceValues`
#' must have the same length). If either of these arguments is
#' provided, then the other *must* be provided and `choices`
#' *must not* be provided. The advantage of using both of these over
#' a named list for `choices` is that `choiceNames` allows any
#' type of UI object to be passed through (tag objects, icons, HTML code,
#' ...), instead of just simple text. See Examples.
#'
#' @return A list of HTML elements that can be added to a UI definition.
#'
#' @family input elements
#' @seealso [checkboxInput()], [updateCheckboxGroupInput()]
#'
#' @examples
#' ## Only run examples in interactive R sessions
#' if (interactive()) {
#'
#' ui <- fluidPage(
#' checkboxGroupInput("variable", "Variables to show:",
#' c("Cylinders" = "cyl",
#' "Transmission" = "am",
#' "Gears" = "gear")),
#' tableOutput("data")
#' )
#'
#' server <- function(input, output, session) {
#' output$data <- renderTable({
#' mtcars[, c("mpg", input$variable), drop = FALSE]
#' }, rownames = TRUE)
#' }
#'
#' shinyApp(ui, server)
#'
#' ui <- fluidPage(
#' checkboxGroupInput("icons", "Choose icons:",
#' choiceNames =
#' list(icon("calendar"), icon("bed"),
#' icon("cog"), icon("bug")),
#' choiceValues =
#' list("calendar", "bed", "cog", "bug")
#' ),
#' textOutput("txt")
#' )
#'
#' server <- function(input, output, session) {
#' output$txt <- renderText({
#' icons <- paste(input$icons, collapse = ", ")
#' paste("You chose", icons)
#' })
#' }
#'
#' shinyApp(ui, server)
#' }
#' @section Server value:
#' Character vector of values corresponding to the boxes that are checked.
#'
#' @export
checkboxGroupInput <- function(inputId, label, choices = NULL, selected = NULL,
inline = FALSE, width = NULL, choiceNames = NULL, choiceValues = NULL) {
# keep backward compatibility with Shiny < 1.0.1 (see #1649)
if (is.null(choices) && is.null(choiceNames) && is.null(choiceValues)) {
choices <- character(0)
}
args <- normalizeChoicesArgs(choices, choiceNames, choiceValues)
selected <- restoreInput(id = inputId, default = selected)
# default value if it's not specified
if (!is.null(selected)) selected <- as.character(selected)
options <- generateOptions(inputId, selected, inline,
'checkbox', args$choiceNames, args$choiceValues)
divClass <- "form-group shiny-input-checkboxgroup shiny-input-container"
if (inline)
divClass <- paste(divClass, "shiny-input-container-inline")
# return label and select tag
inputLabel <- shinyInputLabel(inputId, label)
tags$div(id = inputId,
style = css(width = validateCssUnit(width)),
class = divClass,
# https://www.w3.org/TR/wai-aria-practices/examples/checkbox/checkbox-1/checkbox-1.html
role = "group",
`aria-labelledby` = inputLabel$attribs$id,
inputLabel,
options
)
}

180
R/input-date.R Normal file
View File

@@ -0,0 +1,180 @@
#' Create date input
#'
#' Creates a text input which, when clicked on, brings up a calendar that
#' the user can click on to select dates.
#'
#' The date `format` string specifies how the date will be displayed in
#' the browser. It allows the following values:
#'
#' \itemize{
#' \item `yy` Year without century (12)
#' \item `yyyy` Year with century (2012)
#' \item `mm` Month number, with leading zero (01-12)
#' \item `m` Month number, without leading zero (1-12)
#' \item `M` Abbreviated month name
#' \item `MM` Full month name
#' \item `dd` Day of month with leading zero
#' \item `d` Day of month without leading zero
#' \item `D` Abbreviated weekday name
#' \item `DD` Full weekday name
#' }
#'
#' @inheritParams textInput
#' @param value The starting date. Either a Date object, or a string in
#' `yyyy-mm-dd` format. If NULL (the default), will use the current date
#' in the client's time zone.
#' @param min The minimum allowed date. Either a Date object, or a string in
#' `yyyy-mm-dd` format.
#' @param max The maximum allowed date. Either a Date object, or a string in
#' `yyyy-mm-dd` format.
#' @param format The format of the date to display in the browser. Defaults to
#' `"yyyy-mm-dd"`.
#' @param startview The date range shown when the input object is first clicked.
#' Can be "month" (the default), "year", or "decade".
#' @param weekstart Which day is the start of the week. Should be an integer
#' from 0 (Sunday) to 6 (Saturday).
#' @param language The language used for month and day names. Default is "en".
#' Other valid values include "ar", "az", "bg", "bs", "ca", "cs", "cy", "da",
#' "de", "el", "en-AU", "en-GB", "eo", "es", "et", "eu", "fa", "fi", "fo",
#' "fr-CH", "fr", "gl", "he", "hr", "hu", "hy", "id", "is", "it-CH", "it",
#' "ja", "ka", "kh", "kk", "ko", "kr", "lt", "lv", "me", "mk", "mn", "ms",
#' "nb", "nl-BE", "nl", "no", "pl", "pt-BR", "pt", "ro", "rs-latin", "rs",
#' "ru", "sk", "sl", "sq", "sr-latin", "sr", "sv", "sw", "th", "tr", "uk",
#' "vi", "zh-CN", and "zh-TW".
#' @param autoclose Whether or not to close the datepicker immediately when a
#' date is selected.
#' @param datesdisabled Which dates should be disabled. Either a Date object,
#' or a string in `yyyy-mm-dd` format.
#' @param daysofweekdisabled Days of the week that should be disabled. Should be
#' a integer vector with values from 0 (Sunday) to 6 (Saturday).
#'
#' @family input elements
#' @seealso [dateRangeInput()], [updateDateInput()]
#'
#' @examples
#' ## Only run examples in interactive R sessions
#' if (interactive()) {
#'
#' ui <- fluidPage(
#' dateInput("date1", "Date:", value = "2012-02-29"),
#'
#' # Default value is the date in client's time zone
#' dateInput("date2", "Date:"),
#'
#' # value is always yyyy-mm-dd, even if the display format is different
#' dateInput("date3", "Date:", value = "2012-02-29", format = "mm/dd/yy"),
#'
#' # Pass in a Date object
#' dateInput("date4", "Date:", value = Sys.Date()-10),
#'
#' # Use different language and different first day of week
#' dateInput("date5", "Date:",
#' language = "ru",
#' weekstart = 1),
#'
#' # Start with decade view instead of default month view
#' dateInput("date6", "Date:",
#' startview = "decade"),
#'
#' # Disable Mondays and Tuesdays.
#' dateInput("date7", "Date:", daysofweekdisabled = c(1,2)),
#'
#' # Disable specific dates.
#' dateInput("date8", "Date:", value = "2012-02-29",
#' datesdisabled = c("2012-03-01", "2012-03-02"))
#' )
#'
#' shinyApp(ui, server = function(input, output) { })
#' }
#'
#' @section Server value:
#' A [Date] vector of length 1.
#'
#' @export
dateInput <- function(inputId, label, value = NULL, min = NULL, max = NULL,
format = "yyyy-mm-dd", startview = "month", weekstart = 0,
language = "en", width = NULL, autoclose = TRUE,
datesdisabled = NULL, daysofweekdisabled = NULL) {
value <- dateYMD(value, "value")
min <- dateYMD(min, "min")
max <- dateYMD(max, "max")
datesdisabled <- dateYMD(datesdisabled, "datesdisabled")
value <- restoreInput(id = inputId, default = value)
tags$div(id = inputId,
class = "shiny-date-input form-group shiny-input-container",
style = css(width = validateCssUnit(width)),
shinyInputLabel(inputId, label),
tags$input(type = "text",
class = "form-control",
# `aria-labelledby` attribute is required for accessibility to avoid doubled labels (#2951).
`aria-labelledby` = paste0(inputId, "-label"),
# title attribute is announced for screen readers for date format.
title = paste("Date format:", format),
`data-date-language` = language,
`data-date-week-start` = weekstart,
`data-date-format` = format,
`data-date-start-view` = startview,
`data-min-date` = min,
`data-max-date` = max,
`data-initial-date` = value,
`data-date-autoclose` = if (autoclose) "true" else "false",
`data-date-dates-disabled` =
# Ensure NULL is not sent as `{}` but as 'null'
jsonlite::toJSON(datesdisabled, null = 'null'),
`data-date-days-of-week-disabled` =
jsonlite::toJSON(daysofweekdisabled, null = 'null')
),
datePickerDependency()
)
}
datePickerDependency <- function(theme) {
list(
htmlDependency(
name = "bootstrap-datepicker-js",
version = version_bs_date_picker,
src = "www/shared/datepicker",
package = "shiny",
script = if (getOption("shiny.minified", TRUE)) "js/bootstrap-datepicker.min.js"
else "js/bootstrap-datepicker.js",
# Need to enable noConflict mode. See #1346.
head = "<script>(function() {
var datepicker = $.fn.datepicker.noConflict();
$.fn.bsDatepicker = datepicker;
})();
</script>"
),
bslib::bs_dependency_defer(datePickerCSS)
)
}
datePickerSass <- function() {
sass::sass_file(
system_file(package = "shiny", "www/shared/datepicker/scss/build3.scss")
)
}
datePickerCSS <- function(theme) {
if (!is_bs_theme(theme)) {
return(htmlDependency(
name = "bootstrap-datepicker-css",
version = version_bs_date_picker,
src = "www/shared/datepicker",
package = "shiny",
stylesheet = "css/bootstrap-datepicker3.min.css"
))
}
bslib::bs_dependency(
input = datePickerSass(),
theme = theme,
name = "bootstrap-datepicker",
version = version_bs_date_picker,
cache_key_extra = get_package_version("shiny")
)
}

142
R/input-daterange.R Normal file
View File

@@ -0,0 +1,142 @@
#' Create date range input
#'
#' Creates a pair of text inputs which, when clicked on, bring up calendars that
#' the user can click on to select dates.
#'
#' The date `format` string specifies how the date will be displayed in
#' the browser. It allows the following values:
#'
#' \itemize{
#' \item `yy` Year without century (12)
#' \item `yyyy` Year with century (2012)
#' \item `mm` Month number, with leading zero (01-12)
#' \item `m` Month number, without leading zero (1-12)
#' \item `M` Abbreviated month name
#' \item `MM` Full month name
#' \item `dd` Day of month with leading zero
#' \item `d` Day of month without leading zero
#' \item `D` Abbreviated weekday name
#' \item `DD` Full weekday name
#' }
#'
#' @inheritParams dateInput
#' @param start The initial start date. Either a Date object, or a string in
#' `yyyy-mm-dd` format. If NULL (the default), will use the current
#' date in the client's time zone.
#' @param end The initial end date. Either a Date object, or a string in
#' `yyyy-mm-dd` format. If NULL (the default), will use the current
#' date in the client's time zone.
#' @param separator String to display between the start and end input boxes.
#'
#' @family input elements
#' @seealso [dateInput()], [updateDateRangeInput()]
#'
#' @examples
#' ## Only run examples in interactive R sessions
#' if (interactive()) {
#'
#' ui <- fluidPage(
#' dateRangeInput("daterange1", "Date range:",
#' start = "2001-01-01",
#' end = "2010-12-31"),
#'
#' # Default start and end is the current date in the client's time zone
#' dateRangeInput("daterange2", "Date range:"),
#'
#' # start and end are always specified in yyyy-mm-dd, even if the display
#' # format is different
#' dateRangeInput("daterange3", "Date range:",
#' start = "2001-01-01",
#' end = "2010-12-31",
#' min = "2001-01-01",
#' max = "2012-12-21",
#' format = "mm/dd/yy",
#' separator = " - "),
#'
#' # Pass in Date objects
#' dateRangeInput("daterange4", "Date range:",
#' start = Sys.Date()-10,
#' end = Sys.Date()+10),
#'
#' # Use different language and different first day of week
#' dateRangeInput("daterange5", "Date range:",
#' language = "de",
#' weekstart = 1),
#'
#' # Start with decade view instead of default month view
#' dateRangeInput("daterange6", "Date range:",
#' startview = "decade")
#' )
#'
#' shinyApp(ui, server = function(input, output) { })
#' }
#'
#' @section Server value:
#' A [Date] vector of length 2.
#'
#' @export
dateRangeInput <- function(inputId, label, start = NULL, end = NULL,
min = NULL, max = NULL, format = "yyyy-mm-dd", startview = "month",
weekstart = 0, language = "en", separator = " to ", width = NULL,
autoclose = TRUE) {
start <- dateYMD(start, "start")
end <- dateYMD(end, "end")
min <- dateYMD(min, "min")
max <- dateYMD(max, "max")
restored <- restoreInput(id = inputId, default = list(start, end))
start <- restored[[1]]
end <- restored[[2]]
attachDependencies(
div(id = inputId,
class = "shiny-date-range-input form-group shiny-input-container",
style = css(width = validateCssUnit(width)),
shinyInputLabel(inputId, label),
# input-daterange class is needed for dropdown behavior
div(class = "input-daterange input-group input-group-sm",
tags$input(
class = "form-control",
type = "text",
# `aria-labelledby` attribute is required for accessibility to avoid doubled labels (#2951).
`aria-labelledby` = paste0(inputId, "-label"),
# title attribute is announced for screen readers for date format.
title = paste("Date format:", format),
`data-date-language` = language,
`data-date-week-start` = weekstart,
`data-date-format` = format,
`data-date-start-view` = startview,
`data-min-date` = min,
`data-max-date` = max,
`data-initial-date` = start,
`data-date-autoclose` = if (autoclose) "true" else "false"
),
# input-group-prepend and input-group-append are for bootstrap 4 forward compat
span(class = "input-group-addon input-group-prepend input-group-append",
span(class = "input-group-text",
separator
)
),
tags$input(
class = "form-control",
type = "text",
# `aria-labelledby` attribute is required for accessibility to avoid doubled labels (#2951).
`aria-labelledby` = paste0(inputId, "-label"),
# title attribute is announced for screen readers for date format.
title = paste("Date format:", format),
`data-date-language` = language,
`data-date-week-start` = weekstart,
`data-date-format` = format,
`data-date-start-view` = startview,
`data-min-date` = min,
`data-max-date` = max,
`data-initial-date` = end,
`data-date-autoclose` = if (autoclose) "true" else "false"
)
)
),
datePickerDependency()
)
}

151
R/input-file.R Normal file
View File

@@ -0,0 +1,151 @@
#' File Upload Control
#'
#' Create a file upload control that can be used to upload one or more files.
#'
#' Whenever a file upload completes, the corresponding input variable is set to
#' a dataframe. See the `Server value` section.
#'
#' Each time files are uploaded, they are written to a new random subdirectory
#' inside of R's process-level temporary directory. The Shiny user session keeps
#' track of all uploads in the session, and when the session ends, Shiny deletes
#' all of the subdirectories where files where uploaded to.
#'
#' @family input elements
#'
#' @inheritParams textInput
#' @param multiple Whether the user should be allowed to select and upload
#' multiple files at once. **Does not work on older browsers, including
#' Internet Explorer 9 and earlier.**
#' @param accept A character vector of "unique file type specifiers" which gives
#' the browser a hint as to the type of file the server expects. Many browsers
#' use this prevent the user from selecting an invalid file.
#'
#' A unique file type specifier can be:
#' * A case insensitive extension like `.csv` or `.rds`.
#' * A valid MIME type, like `text/plain` or `application/pdf`
#' * One of `audio/*`, `video/*`, or `image/*` meaning any audio, video,
#' or image type, respectively.
#' @param buttonLabel The label used on the button. Can be text or an HTML tag
#' object.
#' @param placeholder The text to show before a file has been uploaded.
#' @param capture What source to use for capturing image, audio or video data.
#' This attribute facilitates user access to a device's media capture
#' mechanism, such as a camera, or microphone, from within a file upload
#' control.
#'
#' A value of `user` indicates that the user-facing camera and/or microphone
#' should be used. A value of `environment` specifies that the outward-facing
#' camera and/or microphone should be used.
#'
#' By default on most phones, this will accept still photos or video. For
#' still photos only, also use `accept="image/*"`. For video only, use
#' `accept="video/*"`.
#' @examples
#' ## Only run examples in interactive R sessions
#' if (interactive()) {
#'
#' ui <- fluidPage(
#' sidebarLayout(
#' sidebarPanel(
#' fileInput("file1", "Choose CSV File", accept = ".csv"),
#' checkboxInput("header", "Header", TRUE)
#' ),
#' mainPanel(
#' tableOutput("contents")
#' )
#' )
#' )
#'
#' server <- function(input, output) {
#' output$contents <- renderTable({
#' file <- input$file1
#' ext <- tools::file_ext(file$datapath)
#'
#' req(file)
#' validate(need(ext == "csv", "Please upload a csv file"))
#'
#' read.csv(file$datapath, header = input$header)
#' })
#' }
#'
#' shinyApp(ui, server)
#' }
#'
#' @section Server value:
#'
#' A `data.frame` that contains one row for each selected file, and following
#' columns:
#' \describe{
#' \item{`name`}{The filename provided by the web browser. This is
#' **not** the path to read to get at the actual data that was uploaded
#' (see
#' `datapath` column).}
#' \item{`size`}{The size of the uploaded data, in
#' bytes.}
#' \item{`type`}{The MIME type reported by the browser (for example,
#' `text/plain`), or empty string if the browser didn't know.}
#' \item{`datapath`}{The path to a temp file that contains the data that was
#' uploaded. This file may be deleted if the user performs another upload
#' operation.}
#' }
#'
#' @export
fileInput <- function(inputId, label, multiple = FALSE, accept = NULL,
width = NULL, buttonLabel = "Browse...", placeholder = "No file selected",
capture = NULL) {
restoredValue <- restoreInput(id = inputId, default = NULL)
# Catch potential edge case - ensure that it's either NULL or a data frame.
if (!is.null(restoredValue) && !is.data.frame(restoredValue)) {
warning("Restored value for ", inputId, " has incorrect format.")
restoredValue <- NULL
}
if (!is.null(restoredValue)) {
restoredValue <- toJSON(restoredValue, strict_atomic = FALSE)
}
inputTag <- tags$input(
id = inputId,
class = "shiny-input-file",
name = inputId,
type = "file",
# Don't use "display: none;" style, which causes keyboard accessibility issue; instead use the following workaround: https://css-tricks.com/places-its-tempting-to-use-display-none-but-dont/
style = "position: absolute !important; top: -99999px !important; left: -99999px !important;",
`data-restore` = restoredValue
)
if (multiple)
inputTag$attribs$multiple <- "multiple"
if (length(accept) > 0)
inputTag$attribs$accept <- paste(accept, collapse=',')
if (!is.null(capture)) {
inputTag$attribs$capture <- capture
}
div(class = "form-group shiny-input-container",
style = css(width = validateCssUnit(width)),
shinyInputLabel(inputId, label),
div(class = "input-group",
# input-group-prepend is for bootstrap 4 compat
tags$label(class = "input-group-btn input-group-prepend",
span(class = "btn btn-default btn-file",
buttonLabel,
inputTag
)
),
tags$input(type = "text", class = "form-control",
placeholder = placeholder, readonly = "readonly"
)
),
tags$div(
id=paste(inputId, "_progress", sep=""),
class="progress active shiny-file-input-progress",
tags$div(class="progress-bar")
)
)
}

66
R/input-numeric.R Normal file
View File

@@ -0,0 +1,66 @@
#' Create a numeric input control
#'
#' Create an input control for entry of numeric values
#'
#' @inheritParams textInput
#' @param min Minimum allowed value
#' @param max Maximum allowed value
#' @param step Interval to use when stepping between min and max
#' @return A numeric input control that can be added to a UI definition.
#'
#' @family input elements
#' @seealso [updateNumericInput()]
#'
#' @examples
#' ## Only run examples in interactive R sessions
#' if (interactive()) {
#'
#' ui <- fluidPage(
#' numericInput("obs", "Observations:", 10, min = 1, max = 100),
#' verbatimTextOutput("value")
#' )
#' server <- function(input, output) {
#' output$value <- renderText({ input$obs })
#' }
#' shinyApp(ui, server)
#' }
#'
#' @section Server value:
#' A numeric vector of length 1.
#'
#' @export
numericInput <- function(
inputId,
label,
value,
min = NA,
max = NA,
step = NA,
width = NULL,
...,
updateOn = c("change", "blur")
) {
rlang::check_dots_empty()
updateOn <- rlang::arg_match(updateOn)
value <- restoreInput(id = inputId, default = value)
# build input tag
inputTag <- tags$input(
id = inputId,
type = "number",
class = "shiny-input-number form-control",
value = formatNoSci(value),
`data-update-on` = updateOn
)
if (!is.na(min)) inputTag$attribs$min = min
if (!is.na(max)) inputTag$attribs$max = max
if (!is.na(step)) inputTag$attribs$step = step
div(
class = "form-group shiny-input-container",
style = css(width = validateCssUnit(width)),
shinyInputLabel(inputId, label),
inputTag
)
}

58
R/input-password.R Normal file
View File

@@ -0,0 +1,58 @@
#' Create a password input control
#'
#' Create an password control for entry of passwords.
#'
#' @inheritParams textInput
#' @return A text input control that can be added to a UI definition.
#'
#' @family input elements
#' @seealso [updateTextInput()]
#'
#' @section Server value:
#' A character string of the password input. The default value is `""`
#' unless `value` is provided.
#'
#' @examples
#' ## Only run examples in interactive R sessions
#' if (interactive()) {
#'
#' ui <- fluidPage(
#' passwordInput("password", "Password:"),
#' actionButton("go", "Go"),
#' verbatimTextOutput("value")
#' )
#' server <- function(input, output) {
#' output$value <- renderText({
#' req(input$go)
#' isolate(input$password)
#' })
#' }
#' shinyApp(ui, server)
#' }
#' @export
passwordInput <- function(
inputId,
label,
value = "",
width = NULL,
placeholder = NULL,
...,
updateOn = c("change", "blur")
) {
rlang::check_dots_empty()
updateOn <- rlang::arg_match(updateOn)
div(
class = "form-group shiny-input-container",
style = css(width = validateCssUnit(width)),
shinyInputLabel(inputId, label),
tags$input(
id = inputId,
type = "password",
class = "shiny-input-password form-control",
value = value,
placeholder = placeholder,
`data-update-on` = updateOn
)
)
}

117
R/input-radiobuttons.R Normal file
View File

@@ -0,0 +1,117 @@
#' Create radio buttons
#'
#' Create a set of radio buttons used to select an item from a list.
#'
#' If you need to represent a "None selected" state, it's possible to default
#' the radio buttons to have no options selected by using `selected =
#' character(0)`. However, this is not recommended, as it gives the user no way
#' to return to that state once they've made a selection. Instead, consider
#' having the first of your choices be `c("None selected" = "")`.
#'
#' @inheritParams textInput
#' @param choices List of values to select from (if elements of the list are
#' named then that name rather than the value is displayed to the user). If
#' this argument is provided, then `choiceNames` and `choiceValues` must not
#' be provided, and vice-versa. The values should be strings; other types
#' (such as logicals and numbers) will be coerced to strings.
#' @param selected The initially selected value. If not specified, then it
#' defaults to the first item in `choices`. To start with no items selected,
#' use `character(0)`.
#' @param inline If `TRUE`, render the choices inline (i.e. horizontally)
#' @return A set of radio buttons that can be added to a UI definition.
#' @param choiceNames,choiceValues List of names and values, respectively, that
#' are displayed to the user in the app and correspond to the each choice (for
#' this reason, `choiceNames` and `choiceValues` must have the same length).
#' If either of these arguments is provided, then the other *must* be provided
#' and `choices` *must not* be provided. The advantage of using both of these
#' over a named list for `choices` is that `choiceNames` allows any type of UI
#' object to be passed through (tag objects, icons, HTML code, ...), instead
#' of just simple text. See Examples.
#'
#' @family input elements
#' @seealso [updateRadioButtons()]
#'
#' @examples
#' ## Only run examples in interactive R sessions
#' if (interactive()) {
#'
#' ui <- fluidPage(
#' radioButtons("dist", "Distribution type:",
#' c("Normal" = "norm",
#' "Uniform" = "unif",
#' "Log-normal" = "lnorm",
#' "Exponential" = "exp")),
#' plotOutput("distPlot")
#' )
#'
#' server <- function(input, output) {
#' output$distPlot <- renderPlot({
#' dist <- switch(input$dist,
#' norm = rnorm,
#' unif = runif,
#' lnorm = rlnorm,
#' exp = rexp,
#' rnorm)
#'
#' hist(dist(500))
#' })
#' }
#'
#' shinyApp(ui, server)
#'
#' ui <- fluidPage(
#' radioButtons("rb", "Choose one:",
#' choiceNames = list(
#' icon("calendar"),
#' HTML("<p style='color:red;'>Red Text</p>"),
#' "Normal text"
#' ),
#' choiceValues = list(
#' "icon", "html", "text"
#' )),
#' textOutput("txt")
#' )
#'
#' server <- function(input, output) {
#' output$txt <- renderText({
#' paste("You chose", input$rb)
#' })
#' }
#'
#' shinyApp(ui, server)
#' }
#'
#' @section Server value:
#'
#' A character string containing the value of the selected button.
#'
#' @export
radioButtons <- function(inputId, label, choices = NULL, selected = NULL,
inline = FALSE, width = NULL, choiceNames = NULL, choiceValues = NULL) {
args <- normalizeChoicesArgs(choices, choiceNames, choiceValues)
selected <- restoreInput(id = inputId, default = selected)
# default value if it's not specified
selected <- if (is.null(selected)) args$choiceValues[[1]] else as.character(selected)
if (length(selected) > 1) stop("The 'selected' argument must be of length 1")
options <- generateOptions(inputId, selected, inline,
'radio', args$choiceNames, args$choiceValues)
divClass <- "form-group shiny-input-radiogroup shiny-input-container"
if (inline) divClass <- paste(divClass, "shiny-input-container-inline")
inputLabel <- shinyInputLabel(inputId, label)
tags$div(id = inputId,
style = css(width = validateCssUnit(width)),
class = divClass,
# https://www.w3.org/TR/2017/WD-wai-aria-practices-1.1-20170628/examples/radio/radio-1/radio-1.html
role = "radiogroup",
`aria-labelledby` = inputLabel$attribs$id,
inputLabel,
options
)
}

421
R/input-select.R Normal file
View File

@@ -0,0 +1,421 @@
#' Create a select list input control
#'
#' Create a select list that can be used to choose a single or multiple items
#' from a list of values.
#'
#' By default, `selectInput()` and `selectizeInput()` use the JavaScript library
#' \pkg{selectize.js} (<https://selectize.dev/>) instead of
#' the basic select input element. To use the standard HTML select input
#' element, use `selectInput()` with `selectize=FALSE`.
#'
#' In selectize mode, if the first element in `choices` has a value of `""`, its
#' name will be treated as a placeholder prompt. For example:
#' `selectInput("letter", "Letter", c("Choose one" = "", LETTERS))`
#'
#' **Performance note:** `selectInput()` and `selectizeInput()` can slow down
#' significantly when thousands of choices are used; with legacy browsers like
#' Internet Explorer, the user interface may hang for many seconds. For large
#' numbers of choices, Shiny offers a "server-side selectize" option that
#' massively improves performance and efficiency; see
#' [this selectize article](https://shiny.rstudio.com/articles/selectize.html)
#' on the Shiny Dev Center for details.
#'
#' @inheritParams textInput
#' @param choices List of values to select from. If elements of the list are
#' named, then that name --- rather than the value --- is displayed to the
#' user. It's also possible to group related inputs by providing a named list
#' whose elements are (either named or unnamed) lists, vectors, or factors. In
#' this case, the outermost names will be used as the group labels (leveraging
#' the `<optgroup>` HTML tag) for the elements in the respective sublist. See
#' the example section for a small demo of this feature.
#' @param selected The initially selected value (or multiple values if `multiple
#' = TRUE`). If not specified then defaults to the first value for
#' single-select lists and no values for multiple select lists.
#' @param multiple Is selection of multiple items allowed?
#' @param selectize Whether to use \pkg{selectize.js} or not.
#' @param size Number of items to show in the selection box; a larger number
#' will result in a taller box. Not compatible with `selectize=TRUE`.
#' Normally, when `multiple=FALSE`, a select input will be a drop-down list,
#' but when `size` is set, it will be a box instead.
#' @return A select list control that can be added to a UI definition.
#'
#' @family input elements
#' @seealso [updateSelectInput()] [varSelectInput()]
#'
#' @examples
#' ## Only run examples in interactive R sessions
#' if (interactive()) {
#'
#' # basic example
#' shinyApp(
#' ui = fluidPage(
#' selectInput("variable", "Variable:",
#' c("Cylinders" = "cyl",
#' "Transmission" = "am",
#' "Gears" = "gear")),
#' tableOutput("data")
#' ),
#' server = function(input, output) {
#' output$data <- renderTable({
#' mtcars[, c("mpg", input$variable), drop = FALSE]
#' }, rownames = TRUE)
#' }
#' )
#'
#' # demoing group support in the `choices` arg
#' shinyApp(
#' ui = fluidPage(
#' selectInput("state", "Choose a state:",
#' list(`East Coast` = list("NY", "NJ", "CT"),
#' `West Coast` = list("WA", "OR", "CA"),
#' `Midwest` = list("MN", "WI", "IA"))
#' ),
#' textOutput("result")
#' ),
#' server = function(input, output) {
#' output$result <- renderText({
#' paste("You chose", input$state)
#' })
#' }
#' )
#' }
#'
#' @section Server value: A vector of character strings, usually of length
#' 1, with the value of the selected items. When `multiple=TRUE` and
#' nothing is selected, this value will be `NULL`.
#'
#' @export
selectInput <- function(inputId, label, choices, selected = NULL,
multiple = FALSE, selectize = TRUE, width = NULL,
size = NULL) {
selected <- restoreInput(id = inputId, default = selected)
# resolve names
choices <- choicesWithNames(choices)
# default value if it's not specified
if (is.null(selected)) {
if (!multiple) selected <- firstChoice(choices)
} else selected <- as.character(selected)
if (!is.null(size) && selectize) {
stop("'size' argument is incompatible with 'selectize=TRUE'.")
}
# create select tag and add options
selectTag <- tags$select(
id = inputId,
class = "shiny-input-select",
class = if (!selectize) "form-control",
size = size,
selectOptions(choices, selected, inputId, selectize)
)
if (multiple)
selectTag$attribs$multiple <- "multiple"
# return label and select tag
res <- div(
class = "form-group shiny-input-container",
style = css(width = validateCssUnit(width)),
shinyInputLabel(inputId, label),
div(selectTag)
)
if (!selectize) return(res)
selectizeIt(inputId, res, NULL, nonempty = !multiple && !("" %in% choices))
}
firstChoice <- function(choices) {
if (length(choices) == 0L) return()
choice <- choices[[1]]
if (is.list(choice)) firstChoice(choice) else choice
}
# Create tags for each of the options; use <optgroup> if necessary.
# This returns a HTML string instead of tags for performance reasons.
selectOptions <- function(choices, selected = NULL, inputId, perfWarning = FALSE) {
if (length(choices) >= 1000) {
warning("The select input \"", inputId, "\" contains a large number of ",
"options; consider using server-side selectize for massively improved ",
"performance. See the Details section of the ?selectizeInput help topic.",
call. = FALSE)
}
html <- mapply(choices, names(choices), FUN = function(choice, label) {
if (is.list(choice)) {
# If sub-list, create an optgroup and recurse into the sublist
sprintf(
'<optgroup label="%s">\n%s\n</optgroup>',
htmlEscape(label, TRUE),
selectOptions(choice, selected, inputId, perfWarning)
)
} else {
# If single item, just return option string
sprintf(
'<option value="%s"%s>%s</option>',
htmlEscape(choice, TRUE),
if (choice %in% selected) ' selected' else '',
htmlEscape(label)
)
}
})
HTML(paste(html, collapse = '\n'))
}
# need <optgroup> when choices contains sub-lists
needOptgroup <- function(choices) {
any(vapply(choices, is.list, logical(1)))
}
#' @rdname selectInput
#' @param ... Arguments passed to `selectInput()`.
#' @param options A list of options. See the documentation of \pkg{selectize.js}(<https://selectize.dev/docs/usage>)
#' for possible options (character option values inside [base::I()] will
#' be treated as literal JavaScript code; see [renderDataTable()]
#' for details).
#' @param width The width of the input, e.g. `'400px'`, or `'100%'`;
#' see [validateCssUnit()].
#' @note The selectize input created from `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
#' \pkg{selectize.js}. However, the selectize input created from
#' `selectInput(..., selectize = TRUE)` will ignore the empty string
#' value when it is a single choice input and the empty string is not in the
#' `choices` argument. This is to keep compatibility with
#' `selectInput(..., selectize = FALSE)`.
#' @export
selectizeInput <- function(inputId, ..., options = NULL, width = NULL) {
selectizeIt(
inputId,
selectInput(inputId, ..., selectize = FALSE, width = width),
options
)
}
# given a select input and its id, selectize it
selectizeIt <- function(inputId, select, options, nonempty = FALSE) {
if (length(options) == 0) {
# For NULL and empty unnamed list, replace with an empty named list, so that
# it will get translated to {} in JSON later on.
options <- empty_named_list()
}
# Make sure accessibility plugin is included
if (!('selectize-plugin-a11y' %in% options$plugins)) {
options$plugins <- c(options$plugins, list('selectize-plugin-a11y'))
}
res <- checkAsIs(options)
deps <- list(selectizeDependency())
if ('drag_drop' %in% options$plugins) {
deps[[length(deps) + 1]] <- jqueryuiDependency()
}
# Insert script on same level as <select> tag
select$children[[2]] <- tagAppendChild(
select$children[[2]],
tags$script(
type = 'application/json',
`data-for` = inputId, `data-nonempty` = if (nonempty) '',
`data-eval` = if (length(res$eval)) HTML(toJSON(res$eval)),
HTML(toJSON(res$options))
)
)
attachDependencies(select, deps)
}
selectizeDependency <- function() {
bslib::bs_dependency_defer(selectizeDependencyFunc)
}
selectizeDependencyFunc <- function(theme) {
if (!is_bs_theme(theme)) {
return(selectizeStaticDependency(version_selectize))
}
bs_version <- bslib::theme_version(theme)
# It'd be cleaner to ship the JS in a separate, href-based,
# HTML dependency (which we currently do for other themable widgets),
# but DT, crosstalk, and maybe other pkgs include selectize JS/CSS
# in HTML dependency named selectize, so if we were to change that
# name, the JS/CSS would be loaded/included twice, which leads to
# strange issues, especially since we now include a 3rd party
# accessibility plugin https://github.com/rstudio/shiny/pull/3153
selectizeDir <- system_file(package = "shiny", "www/shared/selectize/")
script <- file.path(selectizeDir, selectizeScripts())
bslib::bs_dependency(
input = selectizeSass(bs_version),
theme = theme,
name = "selectize",
version = version_selectize,
cache_key_extra = get_package_version("shiny"),
.dep_args = list(script = script)
)
}
selectizeSass <- function(bs_version) {
selectizeDir <- system_file(package = "shiny", "www/shared/selectize/")
stylesheet <- file.path(
selectizeDir, "scss", paste0("selectize.bootstrap", bs_version, ".scss")
)
sass::sass_file(stylesheet)
}
selectizeStaticDependency <- function(version) {
htmlDependency(
"selectize",
version,
src = "www/shared/selectize",
package = "shiny",
stylesheet = "css/selectize.bootstrap3.css",
script = selectizeScripts()
)
}
selectizeScripts <- function() {
isMinified <- isTRUE(get_devmode_option("shiny.minified", TRUE))
paste0(
c(
"js/selectize",
"accessibility/js/selectize-plugin-a11y"
),
if (isMinified) ".min.js" else ".js"
)
}
#' Select variables from a data frame
#'
#' Create a select list that can be used to choose a single or multiple items
#' from the column names of a data frame.
#'
#' By default, `varSelectInput()` and `selectizeInput()` use the
#' JavaScript library \pkg{selectize.js}
#' (<https://selectize.dev/>) to instead of the basic
#' select input element. To use the standard HTML select input element, use
#' `selectInput()` with `selectize=FALSE`.
#'
#' @inheritParams selectInput
#' @param data A data frame. Used to retrieve the column names as choices for a [selectInput()]
#' @return A variable select list control that can be added to a UI definition.
#'
#' @family input elements
#' @seealso [updateSelectInput()]
#'
#' @section Server value:
#' The resulting server `input` value will be returned as:
#'
#' * A symbol if `multiple = FALSE`. The `input` value should be
#' used with rlang's [rlang::!!()]. For example,
#' `ggplot2::aes(!!input$variable)`.
#' * A list of symbols if `multiple = TRUE`. The `input` value
#' should be used with rlang's [rlang::!!!()] to expand
#' the symbol list as individual arguments. For example,
#' `dplyr::select(mtcars, !!!input$variabls)` which is
#' equivalent to `dplyr::select(mtcars, !!input$variabls[[1]], !!input$variabls[[2]], ..., !!input$variabls[[length(input$variabls)]])`.
#'
#' @examples
#'
#' ## Only run examples in interactive R sessions
#' if (interactive()) {
#'
#' library(ggplot2)
#'
#' # single selection
#' shinyApp(
#' ui = fluidPage(
#' varSelectInput("variable", "Variable:", mtcars),
#' plotOutput("data")
#' ),
#' server = function(input, output) {
#' output$data <- renderPlot({
#' ggplot(mtcars, aes(!!input$variable)) + geom_histogram()
#' })
#' }
#' )
#'
#'
#' # multiple selections
#' \dontrun{
#' shinyApp(
#' ui = fluidPage(
#' varSelectInput("variables", "Variable:", mtcars, multiple = TRUE),
#' tableOutput("data")
#' ),
#' server = function(input, output) {
#' output$data <- renderTable({
#' if (length(input$variables) == 0) return(mtcars)
#' mtcars %>% dplyr::select(!!!input$variables)
#' }, rownames = TRUE)
#' }
#' )}
#'
#' }
#' @export
varSelectInput <- function(
inputId, label, data, selected = NULL,
multiple = FALSE, selectize = TRUE, width = NULL,
size = NULL
) {
# no place holders
choices <- colnames(data)
selectInputVal <- selectInput(
inputId = inputId,
label = label,
choices = choices,
selected = selected,
multiple = multiple,
selectize = selectize,
width = width,
size = size
)
# set the select tag class to be "symbol"
selectClass <- selectInputVal$children[[2]]$children[[1]]$attribs$class
if (is.null(selectClass)) {
newClass <- "symbol"
} else {
newClass <- paste(selectClass, "symbol", sep = " ")
}
selectInputVal$children[[2]]$children[[1]]$attribs$class <- newClass
selectInputVal
}
#' @rdname varSelectInput
#' @param ... Arguments passed to `varSelectInput()`.
#' @param options A list of options. See the documentation of \pkg{selectize.js}(<https://selectize.dev/docs/usage>)
#' for possible options (character option values inside [base::I()] will
#' be treated as literal JavaScript code; see [renderDataTable()]
#' for details).
#' @param width The width of the input, e.g. `'400px'`, or `'100%'`;
#' see [validateCssUnit()].
#' @note The variable selectize input created from `varSelectizeInput()` 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
#' \pkg{selectize.js}. However, the selectize input created from
#' `selectInput(..., selectize = TRUE)` will ignore the empty string
#' value when it is a single choice input and the empty string is not in the
#' `choices` argument. This is to keep compatibility with
#' `selectInput(..., selectize = FALSE)`.
#' @export
varSelectizeInput <- function(inputId, ..., options = NULL, width = NULL) {
selectizeIt(
inputId,
varSelectInput(inputId, ..., selectize = FALSE, width = width),
options
)
}

336
R/input-slider.R Normal file
View File

@@ -0,0 +1,336 @@
#' Slider Input Widget
#'
#' Constructs a slider widget to select a number, date, or date-time from a
#' range.
#'
#' @inheritParams textInput
#' @param min,max The minimum and maximum values (inclusive) that can be
#' selected.
#' @param value The initial value of the slider, either a number, a date
#' (class Date), or a date-time (class POSIXt). A length one vector will
#' create a regular slider; a length two vector will create a double-ended
#' range slider. Must lie between `min` and `max`.
#' @param step Specifies the interval between each selectable value on the
#' slider. Either `NULL`, the default, which uses a heuristic to determine the
#' step size or a single number. If the values are dates, `step` is in days;
#' if the values are date-times, `step` is in seconds.
#' @param round `TRUE` to round all values to the nearest integer;
#' `FALSE` if no rounding is desired; or an integer to round to that
#' number of digits (for example, 1 will round to the nearest 10, and -2 will
#' round to the nearest .01). Any rounding will be applied after snapping to
#' the nearest step.
#' @param ticks `FALSE` to hide tick marks, `TRUE` to show them
#' according to some simple heuristics.
#' @param animate `TRUE` to show simple animation controls with default
#' settings; `FALSE` not to; or a custom settings list, such as those
#' created using [animationOptions()].
#' @param sep Separator between thousands places in numbers.
#' @param pre A prefix string to put in front of the value.
#' @param post A suffix string to put after the value.
#' @param dragRange This option is used only if it is a range slider (with two
#' values). If `TRUE` (the default), the range can be dragged. In other
#' words, the min and max can be dragged together. If `FALSE`, the range
#' cannot be dragged.
#' @param timeFormat Only used if the values are Date or POSIXt objects. A time
#' format string, to be passed to the Javascript strftime library. See
#' <https://github.com/samsonjs/strftime> for more details. The allowed
#' format specifications are very similar, but not identical, to those for R's
#' [base::strftime()] function. For Dates, the default is `"%F"`
#' (like `"2015-07-01"`), and for POSIXt, the default is `"%F %T"`
#' (like `"2015-07-01 15:32:10"`).
#' @param timezone Only used if the values are POSIXt objects. A string
#' specifying the time zone offset for the displayed times, in the format
#' `"+HHMM"` or `"-HHMM"`. If `NULL` (the default), times will
#' be displayed in the browser's time zone. The value `"+0000"` will
#' result in UTC time.
#' @inheritParams selectizeInput
#' @family input elements
#' @seealso [updateSliderInput()]
#'
#' @examples
#' ## Only run examples in interactive R sessions
#' if (interactive()) {
#' options(device.ask.default = FALSE)
#'
#' ui <- fluidPage(
#' sliderInput("obs", "Number of observations:",
#' min = 0, max = 1000, value = 500
#' ),
#' plotOutput("distPlot")
#' )
#'
#' # Server logic
#' server <- function(input, output) {
#' output$distPlot <- renderPlot({
#' hist(rnorm(input$obs))
#' })
#' }
#'
#' # Complete app with UI and server components
#' shinyApp(ui, server)
#' }
#'
#' @section Server value:
#' A number, date, or date-time (depending on the class of `value`), or
#' in the case of slider range, a vector of two numbers/dates/date-times.
#'
#' @export
sliderInput <- function(inputId, label, min, max, value, step = NULL,
round = FALSE, ticks = TRUE, animate = FALSE,
width = NULL, sep = ",", pre = NULL, post = NULL,
timeFormat = NULL, timezone = NULL, dragRange = TRUE) {
validate_slider_value(min, max, value, "sliderInput")
dataType <- getSliderType(min, max, value)
if (is.null(timeFormat)) {
timeFormat <- switch(dataType, date = "%F", datetime = "%F %T", number = NULL)
}
# Restore bookmarked values here, after doing the type checking, because the
# restored value will be a character vector instead of Date or POSIXct, and we can do
# the conversion to correct type next.
value <- restoreInput(id = inputId, default = value)
if (is.character(value)) {
# If we got here, the value was restored from a URL-encoded bookmark.
if (dataType == "date") {
value <- as.Date(value, format = "%Y-%m-%d")
} else if (dataType == "datetime") {
# Date-times will have a format like "2018-02-28T03:46:26Z"
value <- as.POSIXct(value, format = "%Y-%m-%dT%H:%M:%SZ", tz = "UTC")
}
}
step <- findStepSize(min, max, step)
if (dataType %in% c("date", "datetime")) {
# For Dates, this conversion uses midnight on that date in UTC
to_ms <- function(x) 1000 * as.numeric(as.POSIXct(x))
# Convert values to milliseconds since epoch (this is the value JS uses)
# Find step size in ms
step <- to_ms(max) - to_ms(max - step)
min <- to_ms(min)
max <- to_ms(max)
value <- to_ms(value)
}
range <- max - min
# Try to get a sane number of tick marks
if (ticks) {
n_steps <- range / step
# Make sure there are <= 10 steps.
# n_ticks can be a noninteger, which is good when the range is not an
# integer multiple of the step size, e.g., min=1, max=10, step=4
scale_factor <- ceiling(n_steps / 10)
n_ticks <- n_steps / scale_factor
} else {
n_ticks <- NULL
}
sliderProps <- dropNulls(list(
class = "js-range-slider",
id = inputId,
`data-skin` = "shiny",
`data-type` = if (length(value) > 1) "double",
`data-min` = formatNoSci(min),
`data-max` = formatNoSci(max),
`data-from` = formatNoSci(value[1]),
`data-to` = if (length(value) > 1) formatNoSci(value[2]),
`data-step` = formatNoSci(step),
`data-grid` = ticks,
`data-grid-num` = n_ticks,
`data-grid-snap` = FALSE,
`data-prettify-separator` = sep,
`data-prettify-enabled` = (sep != ""),
`data-prefix` = pre,
`data-postfix` = post,
`data-keyboard` = TRUE,
# This value is only relevant for range sliders; for non-range sliders it
# causes problems since ion.RangeSlider 2.1.2 (issue #1605).
`data-drag-interval` = if (length(value) > 1) dragRange,
# The following are ignored by the ion.rangeSlider, but are used by Shiny.
`data-data-type` = dataType,
`data-time-format` = timeFormat,
`data-timezone` = timezone
))
# Replace any TRUE and FALSE with "true" and "false"
sliderProps <- lapply(sliderProps, function(x) {
if (identical(x, TRUE)) "true"
else if (identical(x, FALSE)) "false"
else x
})
sliderTag <- div(class = "form-group shiny-input-container",
style = css(width = validateCssUnit(width)),
shinyInputLabel(inputId, label),
do.call(tags$input, sliderProps)
)
# Add animation buttons
if (identical(animate, TRUE))
animate <- animationOptions()
if (!is.null(animate) && !identical(animate, FALSE)) {
if (is.null(animate$playButton))
animate$playButton <- icon('play', lib = 'glyphicon')
if (is.null(animate$pauseButton))
animate$pauseButton <- icon('pause', lib = 'glyphicon')
sliderTag <- tagAppendChild(
sliderTag,
tags$div(class='slider-animate-container',
tags$a(href='#',
class='slider-animate-button',
'data-target-id'=inputId,
'data-interval'=animate$interval,
'data-loop'=animate$loop,
span(class = 'play', animate$playButton),
span(class = 'pause', animate$pauseButton)
)
)
)
}
attachDependencies(sliderTag, ionRangeSliderDependency())
}
ionRangeSliderDependency <- function() {
list(
# ion.rangeSlider also needs normalize.css, which is already included in Bootstrap.
htmlDependency(
"ionrangeslider-javascript",
version_ion_range_slider,
src = "www/shared/ionrangeslider",
package = "shiny",
script = "js/ion.rangeSlider.min.js"
),
htmlDependency(
"strftime",
version_strftime,
src = "www/shared/strftime",
package = "shiny",
script = "strftime-min.js"
),
bslib::bs_dependency_defer(ionRangeSliderDependencyCSS)
)
}
ionRangeSliderDependencySass <- function() {
list(
list(accent = "$component-active-bg"),
sass::sass_file(
system_file(package = "shiny", "www/shared/ionrangeslider/scss/shiny.scss")
)
)
}
ionRangeSliderDependencyCSS <- function(theme) {
if (!is_bs_theme(theme)) {
return(htmlDependency(
"ionrangeslider-css",
version_ion_range_slider,
src = "www/shared/ionrangeslider",
package = "shiny",
stylesheet = "css/ion.rangeSlider.css"
))
}
bslib::bs_dependency(
input = ionRangeSliderDependencySass(),
theme = theme,
name = "ionRangeSlider",
version = version_ion_range_slider,
cache_key_extra = get_package_version("shiny")
)
}
hasDecimals <- function(value) {
truncatedValue <- round(value)
return (!identical(value, truncatedValue))
}
# If step is NULL, use heuristic to set the step size.
findStepSize <- function(min, max, step) {
if (!is.null(step)) return(step)
range <- max - min
# If short range or decimals, use continuous decimal with ~100 points
if (range < 2 || hasDecimals(min) || hasDecimals(max)) {
# Workaround for rounding errors (#1006): the intervals between the items
# returned by pretty() can have rounding errors. To avoid this, we'll use
# pretty() to find the min, max, and number of steps, and then use those
# values to calculate the step size.
pretty_steps <- pretty(c(min, max), n = 100)
n_steps <- length(pretty_steps) - 1
# Fix for #2061: Windows has low-significance digits (like 17 digits out)
# even at the boundaries of pretty()'s output. Use signif(digits = 10),
# which should be way way less significant than any data we'd want to keep.
# It might make sense to use signif(steps[2] - steps[1], 10) instead, but
# for now trying to make the minimal change.
signif(digits = 10, (max(pretty_steps) - min(pretty_steps)) / n_steps)
} else {
1
}
}
# Throw a warning if ever `value` is not in the [`min`, `max`] range
validate_slider_value <- function(min, max, value, fun) {
if (length(min) != 1 || is_na(min) ||
length(max) != 1 || is_na(max) ||
length(value) < 1 || length(value) > 2 || any(is.na(value)))
{
stop(call. = FALSE,
sprintf("In %s(): `min`, `max`, and `value` cannot be NULL, NA, or empty.", fun)
)
}
if (min(value) < min) {
warning(call. = FALSE,
sprintf(
"In %s(): `value` should be greater than or equal to `min` (value = %s, min = %s).",
fun, paste(value, collapse = ", "), min
)
)
}
if (max(value) > max) {
warning(
noBreaks. = TRUE, call. = FALSE,
sprintf(
"In %s(): `value` should be less than or equal to `max` (value = %s, max = %s).",
fun, paste(value, collapse = ", "), max
)
)
}
}
#' @rdname sliderInput
#'
#' @param interval The interval, in milliseconds, between each animation step.
#' @param loop `TRUE` to automatically restart the animation when it
#' reaches the end.
#' @param playButton Specifies the appearance of the play button. Valid values
#' are a one-element character vector (for a simple text label), an HTML tag
#' or list of tags (using [tag()] and friends), or raw HTML (using
#' [HTML()]).
#' @param pauseButton Similar to `playButton`, but for the pause button.
#' @export
animationOptions <- function(interval=1000,
loop=FALSE,
playButton=NULL,
pauseButton=NULL) {
list(interval=interval,
loop=loop,
playButton=playButton,
pauseButton=pauseButton)
}

65
R/input-submit.R Normal file
View File

@@ -0,0 +1,65 @@
#' Create a submit button
#'
#' Create a submit button for an app. Apps that include a submit
#' button do not automatically update their outputs when inputs change,
#' rather they wait until the user explicitly clicks the submit button.
#' The use of `submitButton` is generally discouraged in favor of
#' the more versatile [actionButton()] (see details below).
#'
#' Submit buttons are unusual Shiny inputs, and we recommend using
#' [actionButton()] instead of `submitButton` when you
#' want to delay a reaction.
#' See [this
#' article](https://shiny.rstudio.com/articles/action-buttons.html) for more information (including a demo of how to "translate"
#' code using a `submitButton` to code using an `actionButton`).
#'
#' In essence, the presence of a submit button stops all inputs from
#' sending their values automatically to the server. This means, for
#' instance, that if there are *two* submit buttons in the same app,
#' clicking either one will cause all inputs in the app to send their
#' values to the server. This is probably not what you'd want, which is
#' why submit button are unwieldy for all but the simplest apps. There
#' are other problems with submit buttons: for example, dynamically
#' created submit buttons (for example, with [renderUI()]
#' or [insertUI()]) will not work.
#'
#' @param text Button caption
#' @param icon Optional [icon()] to appear on the button
#' @param width The width of the button, e.g. `'400px'`, or `'100%'`;
#' see [validateCssUnit()].
#' @return A submit button that can be added to a UI definition.
#'
#' @family input elements
#'
#' @examples
#' if (interactive()) {
#'
#' shinyApp(
#' ui = basicPage(
#' numericInput("num", label = "Make changes", value = 1),
#' submitButton("Update View", icon("refresh")),
#' helpText("When you click the button above, you should see",
#' "the output below update to reflect the value you",
#' "entered at the top:"),
#' verbatimTextOutput("value")
#' ),
#' server = function(input, output) {
#'
#' # submit buttons do not have a value of their own,
#' # they control when the app accesses values of other widgets.
#' # input$num is the value of the number widget.
#' output$value <- renderPrint({ input$num })
#' }
#' )
#' }
#' @export
submitButton <- function(text = "Apply Changes", icon = NULL, width = NULL) {
div(
tags$button(
type="submit",
class="btn btn-primary shiny-submit-button",
style = css(width = validateCssUnit(width)),
list(icon, text)
)
)
}

72
R/input-text.R Normal file
View File

@@ -0,0 +1,72 @@
#' Create a text input control
#'
#' Create an input control for entry of unstructured text values
#'
#' @param inputId The `input` slot that will be used to access the value.
#' @param label Display label for the control, or `NULL` for no label.
#' @param value Initial value.
#' @param width The width of the input, e.g. `'400px'`, or `'100%'`;
#' see [validateCssUnit()].
#' @param placeholder A character string giving the user a hint as to what can
#' be entered into the control. Internet Explorer 8 and 9 do not support this
#' option.
#' @param ... Ignored, included to require named arguments and for future
#' feature expansion.
#' @param updateOn A character vector specifying when the input should be
#' updated. Options are `"change"` (default) and `"blur"`. Use `"change"` to
#' update the input immediately whenever the value changes. Use `"blur"`to
#' delay the input update until the input loses focus (the user moves away
#' from the input), or when Enter is pressed (or Cmd/Ctrl + Enter for
#' [textAreaInput()]).
#' @return A text input control that can be added to a UI definition.
#'
#' @family input elements
#' @seealso [updateTextInput()]
#'
#' @examples
#' ## Only run examples in interactive R sessions
#' if (interactive()) {
#'
#' ui <- fluidPage(
#' textInput("caption", "Caption", "Data Summary"),
#' verbatimTextOutput("value")
#' )
#' server <- function(input, output) {
#' output$value <- renderText({ input$caption })
#' }
#' shinyApp(ui, server)
#' }
#'
#' @section Server value:
#' A character string of the text input. The default value is `""`
#' unless `value` is provided.
#'
#' @export
textInput <- function(
inputId,
label,
value = "",
width = NULL,
placeholder = NULL,
...,
updateOn = c("change", "blur")
) {
rlang::check_dots_empty()
updateOn <- rlang::arg_match(updateOn)
value <- restoreInput(id = inputId, default = value)
div(
class = "form-group shiny-input-container",
style = css(width = validateCssUnit(width)),
shinyInputLabel(inputId, label),
tags$input(
id = inputId,
type = "text",
class = "shiny-input-text form-control",
value = value,
placeholder = placeholder,
`data-update-on` = updateOn
)
)
}

96
R/input-textarea.R Normal file
View File

@@ -0,0 +1,96 @@
#' Create a textarea input control
#'
#' Create a textarea input control for entry of unstructured text values.
#'
#' @inheritParams textInput
#' @param height The height of the input, e.g. `'400px'`, or `'100%'`; see
#' [validateCssUnit()].
#' @param cols Value of the visible character columns of the input, e.g. `80`.
#' This argument will only take effect if there is not a CSS `width` rule
#' defined for this element; such a rule could come from the `width` argument
#' of this function or from a containing page layout such as
#' [fluidPage()].
#' @param rows The value of the visible character rows of the input, e.g. `6`.
#' If the `height` argument is specified, `height` will take precedence in the
#' browser's rendering.
#' @param resize Which directions the textarea box can be resized. Can be one of
#' `"both"`, `"none"`, `"vertical"`, and `"horizontal"`. The default, `NULL`,
#' will use the client browser's default setting for resizing textareas.
#' @param autoresize If `TRUE`, the textarea will automatically resize to fit
#' the input text.
#' @return A textarea input control that can be added to a UI definition.
#'
#' @family input elements
#' @seealso [updateTextAreaInput()]
#'
#' @examples
#' ## Only run examples in interactive R sessions
#' if (interactive()) {
#'
#' ui <- fluidPage(
#' textAreaInput("caption", "Caption", "Data Summary", width = "1000px"),
#' verbatimTextOutput("value")
#' )
#' server <- function(input, output) {
#' output$value <- renderText({ input$caption })
#' }
#' shinyApp(ui, server)
#'
#' }
#'
#' @section Server value:
#' A character string of the text input. The default value is `""`
#' unless `value` is provided.
#'
#' @export
textAreaInput <- function(
inputId,
label,
value = "",
width = NULL,
height = NULL,
cols = NULL,
rows = NULL,
placeholder = NULL,
resize = NULL,
...,
autoresize = FALSE,
updateOn = c("change", "blur")
) {
rlang::check_dots_empty()
updateOn <- rlang::arg_match(updateOn)
value <- restoreInput(id = inputId, default = value)
if (!is.null(resize)) {
resize <- match.arg(resize, c("both", "none", "vertical", "horizontal"))
}
classes <- "form-control"
if (autoresize) {
classes <- c(classes, "textarea-autoresize")
if (is.null(rows)) {
rows <- 1
}
}
div(
class = "shiny-input-textarea form-group shiny-input-container",
style = css(width = validateCssUnit(width)),
shinyInputLabel(inputId, label),
tags$textarea(
id = inputId,
class = classes,
placeholder = placeholder,
style = css(
width = if (!is.null(width)) "100%",
height = validateCssUnit(height),
resize = resize
),
rows = rows,
cols = cols,
`data-update-on` = updateOn,
value
)
)
}

174
R/input-utils.R Normal file
View File

@@ -0,0 +1,174 @@
shinyInputLabel <- function(inputId, label = NULL) {
tags$label(
label,
class = "control-label",
class = if (is.null(label)) "shiny-label-null",
# `id` attribute is required for `aria-labelledby` used by screen readers:
id = paste0(inputId, "-label"),
`for` = inputId
)
}
# This function takes in either a list or vector for `choices` (and
# `choiceNames` and `choiceValues` are passed in as NULL) OR it takes
# in a list or vector for both `choiceNames` and `choiceValues` (and
# `choices` is passed as NULL) and returns a list of two elements:
# - `choiceNames` is a vector or list that holds the options names
# (each element can be arbitrary UI, or simple text)
# - `choiceValues` is a vector or list that holds the options values
# (each element must be simple text)
normalizeChoicesArgs <- function(choices, choiceNames, choiceValues,
mustExist = TRUE) {
# if-else to check that either choices OR (choiceNames + choiceValues)
# were correctly provided
if (is.null(choices)) {
if (is.null(choiceNames) || is.null(choiceValues)) {
if (mustExist) {
stop("Please specify a non-empty vector for `choices` (or, ",
"alternatively, for both `choiceNames` AND `choiceValues`).")
} else {
if (is.null(choiceNames) && is.null(choiceValues)) {
# this is useful when we call this function from `updateInputOptions()`
# in which case, all three `choices`, `choiceNames` and `choiceValues`
# may legitimately be NULL
return(list(choiceNames = NULL, choiceValues = NULL))
} else {
stop("One of `choiceNames` or `choiceValues` was set to ",
"NULL, but either both or none should be NULL.")
}
}
}
if (length(choiceNames) != length(choiceValues)) {
stop("`choiceNames` and `choiceValues` must have the same length.")
}
if (any_named(choiceNames) || any_named(choiceValues)) {
stop("`choiceNames` and `choiceValues` must not be named.")
}
} else {
if (!is.null(choiceNames) || !is.null(choiceValues)) {
warning("Using `choices` argument; ignoring `choiceNames` and `choiceValues`.")
}
choices <- choicesWithNames(choices) # resolve names if not specified
choiceNames <- names(choices)
choiceValues <- unname(choices)
}
return(list(choiceNames = as.list(choiceNames),
choiceValues = as.list(as.character(choiceValues))))
}
# generate options for radio buttons and checkbox groups (type = 'checkbox' or
# 'radio')
generateOptions <- function(inputId, selected, inline, type = 'checkbox',
choiceNames, choiceValues,
session = getDefaultReactiveDomain()) {
# generate a list of <input type=? [checked] />
options <- mapply(
choiceValues, choiceNames,
FUN = function(value, name) {
inputTag <- tags$input(
type = type, name = inputId, value = value
)
if (value %in% selected)
inputTag$attribs$checked <- "checked"
# in case, the options include UI code other than text
# (arbitrary HTML using the tags() function or equivalent)
pd <- processDeps(name, session)
# If inline, there's no wrapper div, and the label needs a class like
# checkbox-inline.
if (inline) {
tags$label(class = paste0(type, "-inline"), inputTag,
tags$span(pd$html, pd$deps))
} else {
tags$div(class = type, tags$label(inputTag,
tags$span(pd$html, pd$deps)))
}
},
SIMPLIFY = FALSE, USE.NAMES = FALSE
)
div(class = "shiny-options-group", options)
}
# True when a choice list item represents a group of related inputs.
isGroup <- function(choice) {
is.list(choice) ||
!is.null(names(choice)) ||
length(choice) > 1 ||
length(choice) == 0
}
# True when choices is a list and contains at least one group of related inputs.
hasGroups <- function(choices) {
is.list(choices) && any(vapply(choices, isGroup, logical(1)))
}
# Assigns empty names to x if it's unnamed, and then fills any empty names with
# the corresponding value coerced to a character(1).
setDefaultNames <- function(x) {
x <- asNamed(x)
emptyNames <- names(x) == ""
names(x)[emptyNames] <- as.character(x)[emptyNames]
x
}
# Makes a character vector out of x in a way that preserves names.
asCharacter <- function(x) {
stats::setNames(as.character(x), names(x))
}
# Processes a "flat" set of choices, or a collection of choices not containing
# any named groups. choices should be a list without any list children, or an
# atomic vector. choices may be named or unnamed. Any empty names are replaced
# with the corresponding value coerced to a character.
processFlatChoices <- function(choices) {
choices <- setDefaultNames(asCharacter(choices))
as.list(choices)
}
# Processes a "nested" set of choices, or a collection of choices that contains
# one or more named groups of related choices and zero or more "flat" choices.
# choices should be a named list, and any choice group must have a non-empty
# name. Empty names of remaining "flat" choices are replaced with that choice's
# value coerced to a character.
processGroupedChoices <- function(choices) {
# We assert choices is a list, since only a list may contain a group.
stopifnot(is.list(choices))
# The list might be unnamed by this point. We add default names of "" so that
# names(choices) is not zero-length and mapply can work. Within mapply, we
# error if any group's name is ""
choices <- asNamed(choices)
choices <- mapply(function(name, choice) {
choiceIsGroup <- isGroup(choice)
if (choiceIsGroup && name == "") {
# If the choice is a group, and if its name is empty, produce an error. We
# error here because the composite nature of the choice prevents us from
# meaningfully automatically naming it. Note that while not documented,
# groups are not necessarily lists (aka generic vectors) but can also be
# any named atomic vector, or any atomic vector of length > 1.
stop('All sub-lists in "choices" must be named.')
} else if (choiceIsGroup) {
# The choice is a group, but it is named. Process it using the same
# function we use for "top level" choices.
processFlatChoices(choice)
} else {
# The choice was not named and is not a group; it is a "leaf".
as.character(choice)
}
}, names(choices), choices, SIMPLIFY = FALSE)
# By this point, any leaves in the choices list might still have empty names,
# so we're sure to automatically name them.
setDefaultNames(choices)
}
# Takes a vector/list/factor, and adds names (same as the value) to any entries
# without names. Coerces all leaf nodes to `character`.
choicesWithNames <- function(choices) {
if (hasGroups(choices)) {
processGroupedChoices(choices)
} else {
processFlatChoices(choices)
}
}

261
R/insert-tab.R Normal file
View File

@@ -0,0 +1,261 @@
#' Dynamically insert/remove a tabPanel
#'
#' Dynamically insert or remove a [tabPanel()] (or a
#' [navbarMenu()]) from an existing [tabsetPanel()],
#' [navlistPanel()] or [navbarPage()].
#'
#' When you want to insert a new tab before or after an existing tab, you
#' should use `insertTab`. When you want to prepend a tab (i.e. add a
#' tab to the beginning of the `tabsetPanel`), use `prependTab`.
#' When you want to append a tab (i.e. add a tab to the end of the
#' `tabsetPanel`), use `appendTab`.
#'
#' For `navbarPage`, you can insert/remove conventional
#' `tabPanel`s (whether at the top level or nested inside a
#' `navbarMenu`), as well as an entire [navbarMenu()].
#' For the latter case, `target` should be the `menuName` that
#' you gave your `navbarMenu` when you first created it (by default,
#' this is equal to the value of the `title` argument).
#'
#' @param inputId The `id` of the `tabsetPanel` (or
#' `navlistPanel` or `navbarPage`) into which `tab` will
#' be inserted/removed.
#'
#' @param tab The item to be added (must be created with `tabPanel`,
#' or with `navbarMenu`).
#'
#' @param target If inserting: the `value` of an existing
#' `tabPanel`, next to which `tab` will be added.
#' If removing: the `value` of the `tabPanel` that
#' you want to remove. See Details if you want to insert next to/remove
#' an entire `navbarMenu` instead.
#'
#' @param position Should `tab` be added before or after the
#' `target` tab?
#'
#' @param select Should `tab` be selected upon being inserted?
#'
#' @param session The shiny session within which to call this function.
#'
#' @seealso [showTab()]
#'
#' @examples
#' ## Only run this example in interactive R sessions
#' if (interactive()) {
#'
#' # example app for inserting/removing a tab
#' ui <- fluidPage(
#' sidebarLayout(
#' sidebarPanel(
#' actionButton("add", "Add 'Dynamic' tab"),
#' actionButton("remove", "Remove 'Foo' tab")
#' ),
#' mainPanel(
#' tabsetPanel(id = "tabs",
#' tabPanel("Hello", "This is the hello tab"),
#' tabPanel("Foo", "This is the foo tab"),
#' tabPanel("Bar", "This is the bar tab")
#' )
#' )
#' )
#' )
#' server <- function(input, output, session) {
#' observeEvent(input$add, {
#' insertTab(inputId = "tabs",
#' tabPanel("Dynamic", "This a dynamically-added tab"),
#' target = "Bar"
#' )
#' })
#' observeEvent(input$remove, {
#' removeTab(inputId = "tabs", target = "Foo")
#' })
#' }
#'
#' shinyApp(ui, server)
#'
#'
#' # example app for prepending/appending a navbarMenu
#' ui <- navbarPage("Navbar page", id = "tabs",
#' tabPanel("Home",
#' actionButton("prepend", "Prepend a navbarMenu"),
#' actionButton("append", "Append a navbarMenu")
#' )
#' )
#' server <- function(input, output, session) {
#' observeEvent(input$prepend, {
#' id <- paste0("Dropdown", input$prepend, "p")
#' prependTab(inputId = "tabs",
#' navbarMenu(id,
#' tabPanel("Drop1", paste("Drop1 page from", id)),
#' tabPanel("Drop2", paste("Drop2 page from", id)),
#' "------",
#' "Header",
#' tabPanel("Drop3", paste("Drop3 page from", id))
#' )
#' )
#' })
#' observeEvent(input$append, {
#' id <- paste0("Dropdown", input$append, "a")
#' appendTab(inputId = "tabs",
#' navbarMenu(id,
#' tabPanel("Drop1", paste("Drop1 page from", id)),
#' tabPanel("Drop2", paste("Drop2 page from", id)),
#' "------",
#' "Header",
#' tabPanel("Drop3", paste("Drop3 page from", id))
#' )
#' )
#' })
#' }
#'
#' shinyApp(ui, server)
#'
#' }
#' @export
insertTab <- function(inputId, tab, target = NULL,
position = c("after", "before"), select = FALSE,
session = getDefaultReactiveDomain()) {
bslib::nav_insert(
inputId, tab, target,
match.arg(position), select, session
)
}
#' @param menuName This argument should only be used when you want to
#' prepend (or append) `tab` to the beginning (or end) of an
#' existing [navbarMenu()] (which must itself be part of
#' an existing [navbarPage()]). In this case, this argument
#' should be the `menuName` that you gave your `navbarMenu`
#' when you first created it (by default, this is equal to the value
#' of the `title` argument). Note that you still need to set the
#' `inputId` argument to whatever the `id` of the parent
#' `navbarPage` is. If `menuName` is left as `NULL`,
#' `tab` will be prepended (or appended) to whatever
#' `inputId` is.
#'
#' @rdname insertTab
#' @export
prependTab <- function(inputId, tab, select = FALSE, menuName = NULL,
session = getDefaultReactiveDomain()) {
bslib::nav_prepend(inputId, tab, menu_title = menuName, select = select, session = session)
}
#' @rdname insertTab
#' @export
appendTab <- function(inputId, tab, select = FALSE, menuName = NULL,
session = getDefaultReactiveDomain()) {
bslib::nav_append(inputId, tab, menu_title = menuName, select = select, session = session)
}
#' @rdname insertTab
#' @export
removeTab <- function(inputId, target,
session = getDefaultReactiveDomain()) {
bslib::nav_remove(inputId, target, session)
}
#' Dynamically hide/show a tabPanel
#'
#' Dynamically hide or show a [tabPanel()] (or a
#' [navbarMenu()])from an existing [tabsetPanel()],
#' [navlistPanel()] or [navbarPage()].
#'
#' For `navbarPage`, you can hide/show conventional
#' `tabPanel`s (whether at the top level or nested inside a
#' `navbarMenu`), as well as an entire [navbarMenu()].
#' For the latter case, `target` should be the `menuName` that
#' you gave your `navbarMenu` when you first created it (by default,
#' this is equal to the value of the `title` argument).
#'
#' @param inputId The `id` of the `tabsetPanel` (or
#' `navlistPanel` or `navbarPage`) in which to find
#' `target`.
#'
#' @param target The `value` of the `tabPanel` to be
#' hidden/shown. See Details if you want to hide/show an entire
#' `navbarMenu` instead.
#'
#' @param select Should `target` be selected upon being shown?
#'
#' @param session The shiny session within which to call this function.
#'
#' @seealso [insertTab()]
#'
#' @examples
#' ## Only run this example in interactive R sessions
#' if (interactive()) {
#'
#' ui <- navbarPage("Navbar page", id = "tabs",
#' tabPanel("Home",
#' actionButton("hideTab", "Hide 'Foo' tab"),
#' actionButton("showTab", "Show 'Foo' tab"),
#' actionButton("hideMenu", "Hide 'More' navbarMenu"),
#' actionButton("showMenu", "Show 'More' navbarMenu")
#' ),
#' tabPanel("Foo", "This is the foo tab"),
#' tabPanel("Bar", "This is the bar tab"),
#' navbarMenu("More",
#' tabPanel("Table", "Table page"),
#' tabPanel("About", "About page"),
#' "------",
#' "Even more!",
#' tabPanel("Email", "Email page")
#' )
#' )
#'
#' server <- function(input, output, session) {
#' observeEvent(input$hideTab, {
#' hideTab(inputId = "tabs", target = "Foo")
#' })
#'
#' observeEvent(input$showTab, {
#' showTab(inputId = "tabs", target = "Foo")
#' })
#'
#' observeEvent(input$hideMenu, {
#' hideTab(inputId = "tabs", target = "More")
#' })
#'
#' observeEvent(input$showMenu, {
#' showTab(inputId = "tabs", target = "More")
#' })
#' }
#'
#' shinyApp(ui, server)
#' }
#'
#' @export
showTab <- function(inputId, target, select = FALSE,
session = getDefaultReactiveDomain()) {
force(target)
if (select) updateTabsetPanel(session, inputId, selected = target)
inputId <- session$ns(inputId)
callback <- function() {
session$sendChangeTabVisibility(
inputId = inputId,
target = target,
type = "show"
)
}
session$onFlush(callback, once = TRUE)
}
#' @rdname showTab
#' @export
hideTab <- function(inputId, target,
session = getDefaultReactiveDomain()) {
force(target)
inputId <- session$ns(inputId)
callback <- function() {
session$sendChangeTabVisibility(
inputId = inputId,
target = target,
type = "hide"
)
}
session$onFlush(callback, once = TRUE)
}

140
R/insert-ui.R Normal file
View File

@@ -0,0 +1,140 @@
#' Insert and remove UI objects
#'
#' These functions allow you to dynamically add and remove arbitrary UI
#' into your app, whenever you want, as many times as you want.
#' Unlike [renderUI()], the UI generated with `insertUI()` is persistent:
#' once it's created, it stays there until removed by `removeUI()`. Each
#' new call to `insertUI()` creates more UI objects, in addition to
#' the ones already there (all independent from one another). To
#' update a part of the UI (ex: an input object), you must use the
#' appropriate `render` function or a customized `reactive`
#' function.
#'
#' It's particularly useful to pair `removeUI` with `insertUI()`, but there is
#' no restriction on what you can use it on. Any element that can be selected
#' through a jQuery selector can be removed through this function.
#'
#' @param selector A string that is accepted by jQuery's selector
#' (i.e. the string `s` to be placed in a `$(s)` jQuery call).
#'
#' For `insertUI()` this determines the element(s) relative to which you
#' want to insert your UI object. For `removeUI()` this determine the
#' element(s) to be removed. If you want to remove a Shiny input or output,
#' note that many of these are wrapped in `<div>`s, so you may need to use a
#' somewhat complex selector --- see the Examples below. (Alternatively, you
#' could also wrap the inputs/outputs that you want to be able to remove
#' easily in a `<div>` with an id.)
#' @param where Where your UI object should go relative to the selector:
#' \describe{
#' \item{`beforeBegin`}{Before the selector element itself}
#' \item{`afterBegin`}{Just inside the selector element, before its
#' first child}
#' \item{`beforeEnd`}{Just inside the selector element, after its
#' last child (default)}
#' \item{`afterEnd`}{After the selector element itself}
#' }
#' Adapted from <https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML>.
#' @param ui The UI object you want to insert. This can be anything that
#' you usually put inside your apps's `ui` function. If you're inserting
#' multiple elements in one call, make sure to wrap them in either a
#' `tagList()` or a `tags$div()` (the latter option has the
#' advantage that you can give it an `id` to make it easier to
#' reference or remove it later on). If you want to insert raw html, use
#' `ui = HTML()`.
#' @param multiple In case your selector matches more than one element,
#' `multiple` determines whether Shiny should insert the UI object
#' relative to all matched elements or just relative to the first
#' matched element (default).
#' @param immediate Whether the UI object should be immediately inserted
#' or removed, or whether Shiny should wait until all outputs have been
#' updated and all observers have been run (default).
#' @param session The shiny session. Advanced use only.
#' @examples
#' ## Only run this example in interactive R sessions
#' if (interactive()) {
#' # Define UI
#' ui <- fluidPage(
#' actionButton("add", "Add UI")
#' )
#'
#' # Server logic
#' server <- function(input, output, session) {
#' observeEvent(input$add, {
#' insertUI(
#' selector = "#add",
#' where = "afterEnd",
#' ui = textInput(paste0("txt", input$add),
#' "Insert some text")
#' )
#' })
#' }
#'
#' # Complete app with UI and server components
#' shinyApp(ui, server)
#' }
#'
#' if (interactive()) {
#' # Define UI
#' ui <- fluidPage(
#' actionButton("rmv", "Remove UI"),
#' textInput("txt", "This is no longer useful")
#' )
#'
#' # Server logic
#' server <- function(input, output, session) {
#' observeEvent(input$rmv, {
#' removeUI(
#' selector = "div:has(> #txt)"
#' )
#' })
#' }
#'
#' # Complete app with UI and server components
#' shinyApp(ui, server)
#' }
#' @export
insertUI <- function(selector,
where = c("beforeBegin", "afterBegin", "beforeEnd", "afterEnd"),
ui,
multiple = FALSE,
immediate = FALSE,
session = getDefaultReactiveDomain()) {
force(selector)
force(ui)
force(session)
force(multiple)
if (missing(where)) where <- "beforeEnd"
where <- match.arg(where)
callback <- function() {
session$sendInsertUI(selector = selector,
multiple = multiple,
where = where,
content = processDeps(ui, session))
}
if (!immediate) session$onFlushed(callback, once = TRUE)
else callback()
}
#' @rdname insertUI
#' @export
removeUI <- function(selector,
multiple = FALSE,
immediate = FALSE,
session = getDefaultReactiveDomain()) {
force(selector)
force(multiple)
force(session)
callback <- function() {
session$sendRemoveUI(selector = selector,
multiple = multiple)
}
if (!immediate) session$onFlushed(callback, once = TRUE)
else callback()
}

116
R/jqueryui.R Normal file
View File

@@ -0,0 +1,116 @@
#' Panel with absolute positioning
#'
#' Creates a panel whose contents are absolutely positioned.
#'
#' The `absolutePanel` function creates a `<div>` tag whose CSS
#' position is set to `absolute` (or fixed if `fixed = TRUE`). The way
#' absolute positioning works in HTML is that absolute coordinates are specified
#' relative to its nearest parent element whose position is not set to
#' `static` (which is the default), and if no such parent is found, then
#' relative to the page borders. If you're not sure what that means, just keep
#' in mind that you may get strange results if you use `absolutePanel` from
#' inside of certain types of panels.
#'
#' The `fixedPanel` function is the same as `absolutePanel` with
#' `fixed = TRUE`.
#'
#' The position (`top`, `left`, `right`, `bottom`) and size
#' (`width`, `height`) parameters are all optional, but you should
#' specify exactly two of `top`, `bottom`, and `height` and
#' exactly two of `left`, `right`, and `width` for predictable
#' results.
#'
#' Like most other distance parameters in Shiny, the position and size
#' parameters take a number (interpreted as pixels) or a valid CSS size string,
#' such as `"100px"` (100 pixels) or `"25%"`.
#'
#' For arcane HTML reasons, to have the panel fill the page or parent you should
#' specify `0` for `top`, `left`, `right`, and `bottom`
#' rather than the more obvious `width = "100%"` and `height =
#' "100%"`.
#'
#' @param ... Attributes (named arguments) or children (unnamed arguments) that
#' should be included in the panel.
#'
#' @param top Distance between the top of the panel, and the top of the page or
#' parent container.
#' @param left Distance between the left side of the panel, and the left of the
#' page or parent container.
#' @param right Distance between the right side of the panel, and the right of
#' the page or parent container.
#' @param bottom Distance between the bottom of the panel, and the bottom of the
#' page or parent container.
#' @param width Width of the panel.
#' @param height Height of the panel.
#' @param draggable If `TRUE`, allows the user to move the panel by
#' clicking and dragging.
#' @param fixed Positions the panel relative to the browser window and prevents
#' it from being scrolled with the rest of the page.
#' @param cursor The type of cursor that should appear when the user mouses over
#' the panel. Use `"move"` for a north-east-south-west icon,
#' `"default"` for the usual cursor arrow, or `"inherit"` for the
#' usual cursor behavior (including changing to an I-beam when the cursor is
#' over text). The default is `"auto"`, which is equivalent to
#' `ifelse(draggable, "move", "inherit")`.
#' @return An HTML element or list of elements.
#' @export
absolutePanel <- function(...,
top = NULL, left = NULL, right = NULL, bottom = NULL,
width = NULL, height = NULL,
draggable = FALSE, fixed = FALSE,
cursor = c('auto', 'move', 'default', 'inherit')) {
cssProps <- list(
top = top,
left = left,
right = right,
bottom = bottom,
width = width,
height = height
)
cssProps <- cssProps[!sapply(cssProps, is.null)]
cssProps <- sapply(cssProps, validateCssUnit)
cssProps[['position']] <- ifelse(fixed, 'fixed', 'absolute')
cssProps[['cursor']] <- match.arg(cursor)
if (identical(cssProps[['cursor']], 'auto'))
cssProps[['cursor']] <- ifelse(draggable, 'move', 'inherit')
style <- paste(paste(names(cssProps), cssProps, sep = ':', collapse = ';'), ';', sep='')
divTag <- tags$div(style=style, ...)
if (identical(draggable, FALSE)) {
return(divTag)
}
# Add Shiny inputs and htmlwidgets to 'non-draggable' elements
# Cf. https://api.jqueryui.com/draggable/#option-cancel
dragOpts <- '{cancel: ".shiny-input-container,.html-widget,input,textarea,button,select,option"}'
dragJS <- sprintf('$(".draggable").draggable(%s);', dragOpts)
tagList(
tagAppendAttributes(divTag, class='draggable'),
jqueryuiDependency(),
tags$script(HTML(dragJS))
)
}
#' @rdname absolutePanel
#' @export
fixedPanel <- function(...,
top = NULL, left = NULL, right = NULL, bottom = NULL,
width = NULL, height = NULL,
draggable = FALSE,
cursor = c('auto', 'move', 'default', 'inherit')) {
absolutePanel(..., top=top, left=left, right=right, bottom=bottom,
width=width, height=height, draggable=draggable, cursor=match.arg(cursor),
fixed=TRUE)
}
jqueryuiDependency <- function() {
htmlDependency(
"jqueryui",
version_jqueryui,
src = "www/shared/jqueryui",
package = "shiny",
script = "jquery-ui.min.js"
)
}

81
R/knitr.R Normal file
View File

@@ -0,0 +1,81 @@
#' Knitr S3 methods
#'
#' These S3 methods are necessary to help Shiny applications and UI chunks embed
#' themselves in knitr/rmarkdown documents.
#'
#' @name knitr_methods
#' @keywords internal
#' @param x Object to knit_print
#' @param ... Additional knit_print arguments
NULL
# If there's an R Markdown runtime option set but it isn't set to Shiny, then
# return a warning indicating the runtime is inappropriate for this object.
# Returns NULL in all other cases.
shiny_rmd_warning <- function() {
runtime <- knitr::opts_knit$get("rmarkdown.runtime")
if (!is.null(runtime) && runtime != "shiny")
# note that the RStudio IDE checks for this specific string to detect Shiny
# applications in static document
list(structure(
"Shiny application in a static R Markdown document",
class = "rmd_warning"))
else
NULL
}
#' @rdname knitr_methods
knit_print.shiny.appobj <- function(x, ...) {
opts <- x$options %||% list()
width <- if (is.null(opts$width)) "100%" else opts$width
height <- if (is.null(opts$height)) "400" else opts$height
runtime <- knitr::opts_knit$get("rmarkdown.runtime")
if (!is.null(runtime) && runtime != "shiny") {
# If not rendering to a Shiny document, create a box exactly the same
# dimensions as the Shiny app would have had (so the document continues to
# flow as it would have with the app), and display a diagnostic message
width <- validateCssUnit(width)
height <- validateCssUnit(height)
output <- tags$div(
style=paste("width:", width, "; height:", height, "; text-align: center;",
"box-sizing: border-box;", "-moz-box-sizing: border-box;",
"-webkit-box-sizing: border-box;"),
class="muted well",
"Shiny applications not supported in static R Markdown documents")
}
else {
path <- addSubApp(x)
output <- deferredIFrame(path, width, height)
}
# If embedded Shiny apps ever have JS/CSS dependencies (like pym.js) we'll
# 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(htmlPreserve(format(output, indent=FALSE)),
meta = shiny_rmd_warning(), cacheable = FALSE)
}
# Let us use a nicer syntax in knitr chunks than literally
# calling output$value <- renderFoo(...) and fooOutput().
#' @rdname knitr_methods
#' @param inline Whether the object is printed inline.
knit_print.shiny.render.function <- function(x, ..., inline = FALSE) {
x <- htmltools::as.tags(x, inline = inline)
output <- knitr::knit_print(tagList(x), ..., inline = inline)
attr(output, "knit_cacheable") <- FALSE
attr(output, "knit_meta") <- append(attr(output, "knit_meta"),
shiny_rmd_warning())
output
}
# Lets us drop reactive expressions directly into a knitr chunk and have the
# value printed out! Nice for teaching if nothing else.
#' @rdname knitr_methods
knit_print.reactive <- function(x, ..., inline = FALSE) {
renderFunc <- if (inline) renderText else renderPrint
knitr::knit_print(renderFunc({
x()
}), ..., inline = inline)
}

82
R/map.R
View File

@@ -1,71 +1,59 @@
# TESTS
# Simple set/get
# Simple remove
# Simple containsKey
# Simple keys
# Simple values
# Simple clear
# Get of unknown key returns NULL
# Remove of unknown key does nothing
# Setting a key twice always results in last-one-wins
# /TESTS
Map <- setRefClass(
Map <- R6Class(
'Map',
fields = list(
.env = 'environment'
),
methods = list(
portable = FALSE,
public = list(
initialize = function() {
.env <<- new.env(parent=emptyenv())
private$map <<- fastmap()
},
get = function(key) {
if (.self$containsKey(key))
return(base::get(key, pos=.env, inherits=FALSE))
else
return(NULL)
map$get(key)
},
set = function(key, value) {
assign(key, value, pos=.env, inherits=FALSE)
return(value)
map$set(key, value)
value
},
mget = function(keys) {
map$mget(keys)
},
mset = function(...) {
args <- list(...)
for (key in names(args))
set(key, args[[key]])
return()
map$mset(...)
},
remove = function(key) {
if (.self$containsKey(key)) {
result <- .self$get(key)
rm(list = key, pos=.env, inherits=FALSE)
return(result)
}
return(NULL)
if (!map$has(key))
return(NULL)
result <- map$get(key)
map$remove(key)
result
},
containsKey = function(key) {
exists(key, where=.env, inherits=FALSE)
map$has(key)
},
keys = function() {
ls(envir=.env, all.names=TRUE)
keys = function(sort = FALSE) {
map$keys(sort = sort)
},
values = function() {
mget(.self$keys(), envir=.env, inherits=FALSE)
values = function(sort = FALSE) {
map$as_list(sort = sort)
},
clear = function() {
.env <<- new.env(parent=emptyenv())
invisible(NULL)
map$reset()
},
size = function() {
length(.env)
map$size()
}
),
private = list(
map = NULL
)
)
as.list.Map <- function(map) {
sapply(map$keys(),
map$get,
simplify=FALSE)
#' @export
as.list.Map <- function(x, ...) {
x$values()
}
length.Map <- function(map) {
map$size()
#' @export
length.Map <- function(x) {
x$size()
}

88
R/middleware-shiny.R Normal file
View File

@@ -0,0 +1,88 @@
#' @include globals.R
NULL
reactLogHandler <- function(req) {
if (! rLog$isLogging()) {
if (
identical(req$PATH_INFO, "/reactlog/mark") ||
identical(req$PATH_INFO, "/reactlog")
) {
# is not logging, but is a reactlog path...
return(
httpResponse(
# Not Implemented
# - The server either does not recognize the request method, or it lacks the ability to fulfil the request.
status = 501,
content_type = "text/plain; charset=utf-8",
content = "To enable reactlog, set the following option before running the application: \n\noptions(shiny.reactlog = TRUE)"
)
)
} else {
# continue on like normal
return(NULL)
}
}
if (identical(req$PATH_INFO, "/reactlog/mark")) {
sessionToken <- parseQueryString(req$QUERY_STRING)$s
shinysession <- appsByToken$get(sessionToken)
# log time
withReactiveDomain(shinysession, {
rLog$userMark(getDefaultReactiveDomain())
})
return(httpResponse(
status = 200,
content = "marked",
content_type = "text/plain"
))
} else if (identical(req$PATH_INFO, "/reactlog")){
sessionToken <- parseQueryString(req$QUERY_STRING)$s
# `renderReactLog` will check/throw if reactlog doesn't exist
reactlogFile <- renderReactlog(sessionToken)
return(httpResponse(
status = 200,
content = list(
file = reactlogFile,
owned = TRUE
)
))
} else {
# continue on like normal
return(NULL)
}
}
sessionHandler <- function(req) {
path <- req$PATH_INFO
if (is.null(path))
return(NULL)
matches <- regmatches(path, regexec('^(/session/([0-9a-f]+))(/.*)$', path))
if (length(matches[[1]]) == 0)
return(NULL)
session <- matches[[1]][3]
subpath <- matches[[1]][4]
shinysession <- appsByToken$get(session)
if (is.null(shinysession))
return(NULL)
subreq <- as.environment(as.list(req, all.names=TRUE))
subreq$PATH_INFO <- subpath
subreq$SCRIPT_NAME <- paste(subreq$SCRIPT_NAME, matches[[1]][2], sep='')
withReactiveDomain(shinysession, {
shinysession$handleRequest(subreq)
})
}

477
R/middleware.R Normal file
View File

@@ -0,0 +1,477 @@
# This file contains a general toolkit for routing and combining bits of
# HTTP-handling logic. It is similar in spirit to Rook (and Rack, and WSGI, and
# Connect, and...) but adds cascading and routing.
#
# This file is called "middleware" because that's the term used for these bits
# of logic in these other frameworks. However, our code uses the word "handler"
# so we'll stick to that for the rest of this document; just know that they're
# basically the same concept.
#
# ## Intro to handlers
#
# A **handler** (or sometimes, **httpHandler**) is a function that takes a
# `req` parameter--a request object as described in the Rook specification--and
# returns `NULL`, or an `httpResponse`.
#
## ------------------------------------------------------------------------
#' Create an HTTP response object
#'
#' @param status HTTP status code for the response.
#' @param content_type The value for the `Content-Type` header.
#' @param content The body of the response, given as a single-element character
#' vector (will be encoded as UTF-8) or a raw vector.
#' @param headers A named list of additional headers to include. Do not include
#' `Content-Length` (as it is automatically calculated) or `Content-Type` (the
#' `content_type` argument is used instead).
#'
#' @examples
#' httpResponse(status = 405L,
#' content_type = "text/plain",
#' content = "The requested method was not allowed"
#' )
#'
#' @keywords internal
#' @export
httpResponse <- function(status = 200L,
content_type = "text/html; charset=UTF-8",
content = "",
headers = list()) {
# Make sure it's a list, not a vector
headers <- as.list(headers)
if (is.null(headers$`X-UA-Compatible`))
headers$`X-UA-Compatible` <- "IE=edge,chrome=1"
resp <- list(status = status, content_type = content_type, content = content,
headers = headers)
class(resp) <- 'httpResponse'
return(resp)
}
#
# You can think of a web application as being simply an aggregation of these
# functions, each of which performs one kind of duty. Each handler in turn gets
# a look at the request and can decide whether it knows how to handle it. If
# so, it returns an `httpResponse` and processing terminates; if not, it
# returns `NULL` and the next handler gets to execute. If the final handler
# returns `NULL`, a 404 response should be returned.
#
# We have a similar construct for websockets: **websocket handlers** or
# **wsHandlers**. These take a single `ws` argument which is the websocket
# connection that was just opened, and they can either return `TRUE` if they
# are handling the connection, and `NULL` to pass responsibility on to the next
# wsHandler.
#
# ### Combining handlers
#
# Since it's so common for httpHandlers to be invoked in this "cascading"
# fashion, we'll introduce a function that takes zero or more handlers and
# returns a single handler. And while we're at it, making a directory of static
# content available is such a common thing to do, we'll allow strings
# representing paths to be used instead of handlers; any such strings we
# encounter will be converted into `staticHandler` objects.
#
## ------------------------------------------------------------------------
joinHandlers <- function(handlers) {
# Zero handlers; return a null handler
if (length(handlers) == 0)
return(function(req) NULL)
# Just one handler (function)? Return it.
if (is.function(handlers))
return(handlers)
handlers <- lapply(handlers, function(h) {
if (is.character(h))
return(staticHandler(h))
else
return(h)
})
# Filter out NULL
handlers <- handlers[!sapply(handlers, is.null)]
if (length(handlers) == 0)
return(function(req) NULL)
if (length(handlers) == 1)
return(handlers[[1]])
function(req) {
for (handler in handlers) {
response <- handler(req)
if (!is.null(response))
return(response)
}
return(NULL)
}
}
#
# Note that we don't have an equivalent of `joinHandlers` for wsHandlers. It's
# easy to imagine it, we just haven't needed one.
#
# ### Handler routing
#
# Handlers do not have a built-in notion of routing. Conceptually, given a list
# of handlers, all the handlers are peers and they all get to see every request
# (well, up until the point that a handler returns a response).
#
# You could implement routing in each handler by checking the request's
# `PATH_INFO` field, but since it's such a common need, let's make it simple by
# introducing a `routeHandler` function. This is a handler
# [decorator](http://en.wikipedia.org/wiki/Decorator_pattern) and it's
# responsible for 1) filtering out requests that don't match the given route,
# and 2) temporarily modifying the request object to take the matched part of
# the route off of the `PATH_INFO` (and add it to the end of `SCRIPT_NAME`).
# This way, the handler doesn't need to figure out about what part of its URL
# path has already been matched via routing.
#
# (BTW, it's safe for `routeHandler` calls to nest.)
#
## ------------------------------------------------------------------------
routeHandler <- function(prefix, handler) {
force(prefix)
force(handler)
if (identical("", prefix))
return(handler)
if (length(prefix) != 1 || !isTRUE(grepl("^/[^\\]+$", prefix))) {
stop("Invalid URL prefix \"", prefix, "\"")
}
pathPattern <- paste("^\\Q", prefix, "\\E/", sep = "")
function(req) {
if (isTRUE(grepl(pathPattern, req$PATH_INFO))) {
origScript <- req$SCRIPT_NAME
origPath <- req$PATH_INFO
on.exit({
req$SCRIPT_NAME <- origScript
req$PATH_INFO <- origPath
}, add = TRUE)
pathInfo <- substr(req$PATH_INFO, nchar(prefix)+1, nchar(req$PATH_INFO))
req$SCRIPT_NAME <- paste(req$SCRIPT_NAME, prefix, sep = "")
req$PATH_INFO <- pathInfo
return(handler(req))
} else {
return(NULL)
}
}
}
#
# We have a version for websocket handlers as well. Pity about the copy/paste
# job.
#
## ------------------------------------------------------------------------
routeWSHandler <- function(prefix, wshandler) {
force(prefix)
force(wshandler)
if (identical("", prefix))
return(wshandler)
if (length(prefix) != 1 || !isTRUE(grepl("^/[^\\]+$", prefix))) {
stop("Invalid URL prefix \"", prefix, "\"")
}
pathPattern <- paste("^\\Q", prefix, "\\E/", sep = "")
function(ws) {
req <- ws$request
if (isTRUE(grepl(pathPattern, req$PATH_INFO))) {
origScript <- req$SCRIPT_NAME
origPath <- req$PATH_INFO
on.exit({
req$SCRIPT_NAME <- origScript
req$PATH_INFO <- origPath
}, add = TRUE)
pathInfo <- substr(req$PATH_INFO, nchar(prefix)+1, nchar(req$PATH_INFO))
req$SCRIPT_NAME <- paste(req$SCRIPT_NAME, prefix, sep = "")
req$PATH_INFO <- pathInfo
return(wshandler(ws))
} else {
return(NULL)
}
}
}
#
# ### Handler implementations
#
# Now let's actually write some handlers. Note that these functions aren't
# *themselves* handlers, you call them and they *return* a handler. Handler
# factory functions, if you will.
#
# Here's one that serves up static assets from a directory.
#
## ------------------------------------------------------------------------
staticHandler <- function(root) {
force(root)
return(function(req) {
if (!identical(req$REQUEST_METHOD, 'GET'))
return(NULL)
path <- URLdecode(req$PATH_INFO)
if (is.null(path))
return(httpResponse(400, content="<h1>Bad Request</h1>"))
if (path == '/')
path <- '/index.html'
if (grepl('\\', path, fixed = TRUE))
return(NULL)
abs.path <- resolve(root, path)
if (is.null(abs.path))
return(NULL)
content.type <- getContentType(abs.path)
response.content <- readBin(abs.path, 'raw', n=file.info(abs.path)$size)
return(httpResponse(200, content.type, response.content))
})
}
#
# ## Handler manager
#
# The handler manager gives you a place to register handlers (of both http and
# websocket varieties) and provides an httpuv-compatible set of callbacks for
# invoking them.
#
# Create one of these, make zero or more calls to `addHandler` and
# `addWSHandler` methods (order matters--first one wins!), and then pass the
# return value of `createHttpuvApp` to httpuv's `startServer` function.
#
## ------------------------------------------------------------------------
HandlerList <- R6Class("HandlerList",
portable = FALSE,
class = FALSE,
public = list(
handlers = list(),
add = function(handler, key, tail = FALSE) {
if (!is.null(handlers[[key]]))
stop("Key ", key, " already in use")
newList <- structure(names=key, list(handler))
if (length(handlers) == 0)
handlers <<- newList
else if (tail)
handlers <<- c(handlers, newList)
else
handlers <<- c(newList, handlers)
},
remove = function(key) {
handlers[key] <<- NULL
},
clear = function() {
handlers <<- list()
},
invoke = function(...) {
for (handler in handlers) {
result <- handler(...)
if (!is.null(result))
return(result)
}
return(NULL)
}
)
)
HandlerManager <- R6Class("HandlerManager",
portable = FALSE,
class = FALSE,
public = list(
handlers = "HandlerList",
wsHandlers = "HandlerList",
initialize = function() {
handlers <<- HandlerList$new()
wsHandlers <<- HandlerList$new()
},
addHandler = function(handler, key, tail = FALSE) {
handlers$add(handler, key, tail)
},
removeHandler = function(key) {
handlers$remove(key)
},
addWSHandler = function(wsHandler, key, tail = FALSE) {
wsHandlers$add(wsHandler, key, tail)
},
removeWSHandler = function(key) {
wsHandlers$remove(key)
},
clear = function() {
handlers$clear()
wsHandlers$clear()
},
createHttpuvApp = function() {
list(
onHeaders = function(req) {
maxSize <- getOption('shiny.maxRequestSize') %||% (5 * 1024 * 1024)
if (maxSize <= 0)
return(NULL)
reqSize <- 0
if (length(req$CONTENT_LENGTH) > 0)
reqSize <- as.numeric(req$CONTENT_LENGTH)
else if (length(req$HTTP_TRANSFER_ENCODING) > 0)
reqSize <- Inf
if (reqSize > maxSize) {
return(list(status = 413L,
headers = list('Content-Type' = 'text/plain'),
body = 'Maximum upload size exceeded'))
}
else {
return(NULL)
}
},
call = .httpServer(
function (req) {
hybrid_chain(
hybrid_chain(
withCallingHandlers(withLogErrors(handlers$invoke(req)),
error = function(cond) {
sanitizeErrors <- getOption('shiny.sanitize.errors', FALSE)
if (inherits(cond, 'shiny.custom.error') || !sanitizeErrors) {
stop(cond$message, call. = FALSE)
} else {
stop(paste("An error has occurred. Check your logs or",
"contact the app author for clarification."),
call. = FALSE)
}
}
),
catch = function(err) {
httpResponse(status = 500L,
content_type = "text/html; charset=UTF-8",
content = as.character(htmltools::htmlTemplate(
system_file("template", "error.html", package = "shiny"),
message = conditionMessage(err)
))
)
}
),
function(resp) {
maybeInjectAutoreload(resp)
}
)
},
loadSharedSecret()
),
onWSOpen = function(ws) {
return(wsHandlers$invoke(ws))
}
)
},
.httpServer = function(handler, checkSharedSecret) {
filter <- getOption('shiny.http.response.filter')
if (is.null(filter))
filter <- function(req, response) response
function(req) {
if (!checkSharedSecret(req$HTTP_SHINY_SHARED_SECRET)) {
return(list(status=403,
body='<h1>403 Forbidden</h1><p>Shared secret mismatch</p>',
headers=list('Content-Type' = 'text/html')))
}
# Catch HEAD requests. For the purposes of handler functions, they
# should be treated like GET. The difference is that they shouldn't
# return a body in the http response.
head_request <- FALSE
if (identical(req$REQUEST_METHOD, "HEAD")) {
head_request <- TRUE
req$REQUEST_METHOD <- "GET"
}
response <- handler(req)
res <- hybrid_chain(response, function(response) {
if (is.null(response))
response <- httpResponse(404, content="<h1>Not Found</h1>")
if (inherits(response, "httpResponse")) {
headers <- as.list(response$headers)
headers$'Content-Type' <- response$content_type
response <- filter(req, response)
if (head_request) {
headers$`Content-Length` <- getResponseContentLength(response, deleteOwnedContent = TRUE)
return(list(
status = response$status,
body = "",
headers = headers
))
} else {
return(list(
status = response$status,
body = response$content,
headers = headers
))
}
} else {
# Assume it's a Rook-compatible response
return(response)
}
})
}
}
)
)
maybeInjectAutoreload <- function(resp) {
if (get_devmode_option("shiny.autoreload", FALSE) &&
isTRUE(grepl("^text/html($|;)", resp$content_type)) &&
is.character(resp$content)) {
resp$content <- gsub(
"</head>",
"<script src=\"shared/shiny-autoreload.js\"></script>\n</head>",
resp$content,
fixed = TRUE
)
}
resp
}
# Safely get the Content-Length of a Rook response, or NULL if the length cannot
# be determined for whatever reason (probably malformed response$content).
# If deleteOwnedContent is TRUE, then the function should delete response
# content that is of the form list(file=..., owned=TRUE).
getResponseContentLength <- function(response, deleteOwnedContent) {
force(deleteOwnedContent)
result <- if (is.character(response$content) && length(response$content) == 1) {
nchar(response$content, type = "bytes")
} else if (is.raw(response$content)) {
length(response$content)
} else if (is.list(response$content) && !is.null(response$content$file)) {
if (deleteOwnedContent && isTRUE(response$content$owned)) {
on.exit(unlink(response$content$file, recursive = FALSE, force = FALSE), add = TRUE)
}
file.info(response$content$file)$size
} else {
warning("HEAD request for unexpected content class ", class(response$content)[[1]])
NULL
}
if (is.na(result)) {
# Mostly for missing file case
return(NULL)
} else {
return(result)
}
}
#
# ## Next steps
#
# See server.R and middleware-shiny.R to see actual implementation and usage of
# handlers in the context of Shiny.

745
R/mock-session.R Normal file
View File

@@ -0,0 +1,745 @@
# Promise helpers taken from:
# https://github.com/rstudio/promises/blob/main/tests/testthat/common.R
# Block until all pending later tasks have executed
wait_for_it <- function() {
while (!later::loop_empty()) {
later::run_now(0.1)
}
}
# Block until the promise is resolved/rejected. If resolved, return the value.
# If rejected, throw (yes throw, not return) the error.
extract <- function(promise) {
promise_value <- NULL
error <- NULL
promise %...>%
(function(value) promise_value <<- value) %...!%
(function(reason) error <<- reason)
wait_for_it()
if (!is.null(error))
stop(error)
else
promise_value
}
# TODO: is there a way to get this behavior without exporting these functions? R6?
# TODO: clientData is documented as a reactiveValues, which this is not. Is it possible that
# users are currently assigning into clientData? That would not work as expected here.
#' @noRd
#' @export
`$.mockclientdata` <- function(x, name) {
if (name == "pixelratio") { return(1) }
if (name == "url_protocol") { return("http:") }
if (name == "url_hostname") { return("mocksession") }
if (name == "url_port") { return(1234) }
if (name == "url_pathname") { return("/mockpath") }
if (name == "url_hash") { return("#mockhash") }
if (name == "url_hash_initial") { return("#mockhash") }
if (name == "url_search") { return("?mocksearch=1") }
clientRE <- "^output_(.+)_([^_]+)$"
if(grepl(clientRE, name)) {
# TODO: use proper regex group matching here instead of redundantly parsing
el <- sub(clientRE, "\\1", name)
att <- sub(clientRE, "\\2", name)
if (att == "width") {
return(600)
} else if (att == "height") {
return(400)
} else if (att == "hidden") {
return(FALSE)
}
}
warning("Unexpected clientdata attribute accessed: ", name)
return(NULL)
}
#' @noRd
#' @export
`[[.mockclientdata` <- `$.mockclientdata`
#' @noRd
#' @export
`[.mockclientdata` <- function(values, name) {
stop("Single-bracket indexing of mockclientdata is not allowed.")
}
#' @noRd
mapNames <- function(func, vals) {
names(vals) <- vapply(names(vals), func, character(1))
vals
}
#' Returns a noop implementation of the public method `name` of ShinySession.
#' @include shiny.R
#' @noRd
makeNoop <- function(name, msg = paste0(name, " is a noop.")) {
if (!(name %in% names(ShinySession$public_methods)))
stop(name, " is not public method of ShinySession.")
impl <- ShinySession$public_methods[[name]]
body(impl) <- rlang::expr({
# Force arguments
!!lapply(formalArgs(impl), rlang::sym)
# Evade "no visible binding" note for reference to `private`
(!!as.symbol("private"))$noopWarn(!!name, !!msg)
invisible()
})
impl
}
#' Accepts a series of symbols as arguments and generates corresponding noop
#' implementations.
#' @noRd
makeWarnNoops <- function(...) {
methods <- as.character(list(...))
names(methods) <- methods
lapply(methods, makeNoop)
}
#' Returns an implementation of a ShinySession public method that signals an
#' error.
#' @include shiny.R
#' @noRd
makeError <- function(name, msg = paste0(name, " is for internal use only.")) {
if (!(name %in% names(ShinySession$public_methods)))
stop(name, " is not public method of ShinySession.")
impl <- ShinySession$public_methods[[name]]
body(impl) <- rlang::expr({
base::stop(!!msg)
})
impl
}
#' Accepts a series of named arguments. Each name corresponds to a ShinySession
#' public method that should signal an error, and each argument corresponds to
#' an error message.
#' @noRd
makeErrors <- function(...) {
errors <- rlang::list2(...)
mapply(makeError, names(errors), errors, USE.NAMES = TRUE, SIMPLIFY = FALSE)
}
#' @noRd
makeExtraMethods <- function() {
c(makeWarnNoops(
"allowReconnect",
"decrementBusyCount",
"doBookmark",
"exportTestValues",
"flushOutput",
"getBookmarkExclude",
"getTestSnapshotUrl",
"incrementBusyCount",
"manageHiddenOutputs",
"manageInputs",
"onBookmark",
"onBookmarked",
"onInputReceived",
"onRestore",
"onRestored",
"outputOptions",
"reactlog",
# TODO Consider implementing this. Would require a new method like
# session$getDataObj() to access in a test expression.
"registerDataObj",
"reload",
"resetBrush",
"sendBinaryMessage",
"sendChangeTabVisibility",
"sendCustomMessage",
"sendInputMessage",
"sendInsertTab",
"sendInsertUI",
"sendModal",
"setCurrentTheme",
"getCurrentTheme",
"sendNotification",
"sendProgress",
"sendRemoveTab",
"sendRemoveUI",
"setBookmarkExclude",
"setShowcase",
"showProgress",
"updateQueryString"
), makeErrors(
`@uploadEnd` = "for internal use only",
`@uploadInit` = "for internal use only",
createBookmarkObservers = "for internal use only",
dispatch = "for internal use only",
handleRequest = "for internal use only",
requestFlush = "for internal use only",
startTiming = "for internal use only",
wsClosed = "for internal use only"
))
}
#' @description Adds generated instance methods to a MockShinySession instance.
#' Note that `lock_objects = FALSE` must be set in the call to `R6Class()`
#' that produced the generator object of the instance.
#' @param instance instance of an R6 object, generally a `MockShinySession`.
#' @param methods named list of method names to method implementation functions.
#' In our typical usage, each function is derived from a public method of
#' `ShinySession`. The environment of each implementation function is set to
#' `instance$.__enclos_env` before the method is added.
#' @noRd
addGeneratedInstanceMethods <- function(instance, methods = makeExtraMethods()) {
mapply(function(name, impl) {
environment(impl) <- instance$.__enclos_env__
instance[[name]] <- impl
}, names(methods), methods)
}
#' Mock Shiny Session
#'
#' @description An R6 class suitable for testing purposes. Simulates, to the
#' extent possible, the behavior of the `ShinySession` class. The `session`
#' parameter provided to Shiny server functions and modules is an instance of
#' a `ShinySession` in normal operation.
#'
#' Most kinds of module and server testing do not require this class be
#' instantiated manually. See instead [testServer()].
#'
#' In order to support advanced usage, instances of `MockShinySession` are
#' **unlocked** so that public methods and fields of instances may be
#' modified. For example, in order to test authentication workflows, the
#' `user` or `groups` fields may be overridden. Modified instances of
#' `MockShinySession` may then be passed explicitly as the `session` argument
#' of [testServer()].
#'
#' @include timer.R
#' @export
MockShinySession <- R6Class(
'MockShinySession',
portable = FALSE,
lock_objects = FALSE,
public = list(
#' @field env The environment associated with the session.
env = NULL,
#' @field returned The value returned by the module under test.
returned = NULL,
#' @field singletons Hardcoded as empty. Needed for rendering HTML (i.e. renderUI).
singletons = character(0),
#' @field clientData Mock client data that always returns a size for plots.
clientData = structure(list(), class="mockclientdata"),
#' @field output The shinyoutputs associated with the session.
output = NULL,
#' @field input The reactive inputs associated with the session.
input = NULL,
#' @field userData An environment initialized as empty.
userData = NULL,
#' @field progressStack A stack of progress objects.
progressStack = 'Stack',
#' @field token On a real `ShinySession`, used to identify this instance in URLs.
token = 'character',
#' @field cache The session cache object.
cache = NULL,
#' @field appcache The app cache object.
appcache = NULL,
#' @field restoreContext Part of bookmarking support in a real
#' `ShinySession` but always `NULL` for a `MockShinySession`.
restoreContext = NULL,
#' @field groups Character vector of groups associated with an authenticated
#' user. Always `NULL` for a `MockShinySesion`.
groups = NULL,
#' @field user The username of an authenticated user. Always `NULL` for a
#' `MockShinySession`.
user = NULL,
#' @field options A list containing session-level shinyOptions.
options = NULL,
#' @description Create a new MockShinySession.
initialize = function() {
private$.input <- ReactiveValues$new(dedupe = FALSE, label = "input")
private$flushCBs <- Callbacks$new()
private$flushedCBs <- Callbacks$new()
private$endedCBs <- Callbacks$new()
private$file_generators <- fastmap()
private$timer <- MockableTimerCallbacks$new()
self$progressStack <- fastmap::faststack()
self$userData <- new.env(parent=emptyenv())
# create output
out <- .createOutputWriter(self)
class(out) <- "shinyoutput"
self$output <- out
# Create a read-only copy of the inputs reactive.
self$input <- .createReactiveValues(private$.input, readonly = TRUE)
self$token <- createUniqueId(16)
# Copy app-level options
self$options <- getCurrentAppState()$options
self$cache <- cachem::cache_mem()
self$appcache <- cachem::cache_mem()
# Adds various generated noop and error-producing method implementations.
# Note that noop methods can be configured to produce warnings by setting
# the option shiny.mocksession.warn = TRUE; see $noopWarn() for details.
addGeneratedInstanceMethods(self)
},
#' @description Define a callback to be invoked before a reactive flush
#' @param fun The function to invoke
#' @param once If `TRUE`, will only run once. Otherwise, will run every time reactives are flushed.
onFlush = function(fun, once=TRUE) {
if (!isTRUE(once)) {
return(private$flushCBs$register(fun))
} else {
dereg <- private$flushCBs$register(function() {
dereg()
fun()
})
return(dereg)
}
},
#' @description Define a callback to be invoked after a reactive flush
#' @param fun The function to invoke
#' @param once If `TRUE`, will only run once. Otherwise, will run every time reactives are flushed.
onFlushed = function(fun, once=TRUE) {
if (!isTRUE(once)) {
return(private$flushedCBs$register(fun))
} else {
dereg <- private$flushedCBs$register(function() {
dereg()
fun()
})
return(dereg)
}
},
#' @description Define a callback to be invoked when the session ends
#' @param sessionEndedCallback The callback to invoke when the session has ended.
onEnded = function(sessionEndedCallback) {
private$endedCBs$register(sessionEndedCallback)
},
#' @description Returns `FALSE` if the session has not yet been closed
isEnded = function(){ private$was_closed },
#' @description Returns `FALSE` if the session has not yet been closed
isClosed = function(){ private$was_closed },
#' @description Closes the session
close = function(){
for (output in private$output) {
output$suspend()
}
withReactiveDomain(self, {
private$endedCBs$invoke(onError = printError, ..stacktraceon = TRUE)
})
private$was_closed <- TRUE
},
#FIXME: this is wrong. Will need to be more complex.
#' @description Unsophisticated mock implementation that merely invokes
# the given callback immediately.
#' @param callback The callback to be invoked.
cycleStartAction = function(callback){ callback() },
#' @description Base64-encode the given file. Needed for image rendering.
#' @param name Not used
#' @param file The file to be encoded
#' @param contentType The content type of the base64-encoded string
fileUrl = function(name, file, contentType='application/octet-stream') {
bytes <- file.info(file)$size
if (is.na(bytes))
return(NULL)
fileData <- readBin(file, 'raw', n=bytes)
b64 <- rawToBase64(fileData)
return(paste('data:', contentType, ';base64,', b64, sep=''))
},
#' @description Sets reactive values associated with the `session$inputs`
#' object and flushes the reactives.
#' @param ... The inputs to set. These arguments are processed with
#' [rlang::list2()] and so are _[dynamic][rlang::dyn-dots]_. Input names
#' may not be duplicated.
#' @examples
#' \dontrun{
#' session$setInputs(x=1, y=2)
#' }
setInputs = function(...) {
vals <- rlang::dots_list(..., .homonyms = "error")
mapply(names(vals), vals, FUN = function(name, value) {
private$.input$set(name, value)
})
private$flush()
},
#' @description An internal method which shouldn't be used by others.
#' Schedules `callback` for execution after some number of `millis`
#' milliseconds.
#' @param millis The number of milliseconds on which to schedule a callback
#' @param callback The function to schedule.
.scheduleTask = function(millis, callback) {
id <- private$timer$schedule(millis, callback)
# Return a deregistration callback
function() {
invisible(private$timer$unschedule(id))
}
},
#' @description Simulate the passing of time by the given number of milliseconds.
#' @param millis The number of milliseconds to advance time.
elapse = function(millis) {
msLeft <- millis
while (msLeft > 0){
t <- private$timer$timeToNextEvent()
if (is.infinite(t) || t <= 0 || msLeft < t){
# Either there's no good upcoming event or we can't make it to it in the allotted time.
break
}
msLeft <- msLeft - t
private$timer$elapse(t)
# timerCallbacks must run before flushReact.
private$timer$executeElapsed()
private$flush()
}
private$timer$elapse(msLeft)
# Run again in case our callbacks resulted in a scheduled
# function that needs executing.
private$timer$executeElapsed()
private$flush()
},
#' @description An internal method which shouldn't be used by others.
#' @return Elapsed time in milliseconds.
.now = function() {
private$timer$getElapsed()
},
#' @description An internal method which shouldn't be used by others.
#' Defines an output in a way that sets private$currentOutputName
#' appropriately.
#' @param name The name of the output.
#' @param func The render definition.
#' @param label Not used.
defineOutput = function(name, func, label) {
force(name)
if (!is.null(private$outs[[name]]$obs)) {
private$outs[[name]]$obs$destroy()
}
if (is.null(func)) func <- missingOutput
if (!is.function(func))
stop(paste("Unexpected", class(func), "output for", name))
with_no_otel_collect({
obs <- observe({
# We could just stash the promise, but we get an "unhandled promise error". This bypasses
prom <- NULL
tryCatch({
v <- private$withCurrentOutput(name, func(self, name))
if (!is.promise(v)){
# Make our sync value into a promise
prom <- promise_resolve(v)
} else {
prom <- v
}
}, error=function(e){
# Error running value()
prom <<- promise_reject(e)
})
private$outs[[name]]$promise <- hybrid_chain(
prom,
function(v){
list(val = v, err = NULL)
}, catch=function(e){
if (
!inherits(e, c("shiny.custom.error", "shiny.output.cancel", "shiny.output.progress", "shiny.silent.error"))
) {
self$unhandledError(e, close = FALSE)
}
list(val = NULL, err = e)
})
})
})
private$outs[[name]] <- list(obs = obs, func = func, promise = NULL)
},
#' @description An internal method which shouldn't be used by others. Forces
#' evaluation of any reactive dependencies of the output function.
#' @param name The name of the output.
#' @return The return value of the function responsible for rendering the
#' output.
getOutput = function(name) {
# Unlike the real outputs, we're going to return the last value rather than the unevaluated function
if (is.null(private$outs[[name]])) {
stop("The test referenced an output that hasn't been defined yet: output$", name)
}
if (is.null(private$outs[[name]]$promise)) {
# Means the output was defined but the observer hasn't had a chance to run
# yet. Run flushReact() now to force the observer to run.
flushReact()
if (is.null(private$outs[[name]]$promise)) {
stop("output$", name, " encountered an unexpected error resolving its promise")
}
}
# Make promise return
v <- extract(private$outs[[name]]$promise)
if (!is.null(v$err)){
stop(v$err)
} else if (private$file_generators$has(self$ns(name))) {
download <- private$file_generators$get(self$ns(name))
private$renderFile(self$ns(name), download)
} else {
v$val
}
},
#' @description Returns the given id prefixed by this namespace's id.
#' @param id The id to prefix with a namespace id.
#' @return The id with a namespace prefix.
ns = function(id) {
NS(private$nsPrefix, id)
},
#' @description Trigger a reactive flush right now.
flushReact = function(){
private$flush()
},
#' @description Create and return a namespace-specific session proxy.
#' @param namespace Character vector indicating a namespace.
#' @return A new session proxy.
makeScope = function(namespace) {
ns <- NS(namespace)
createSessionProxy(
self,
input = .createReactiveValues(private$.input, readonly = TRUE, ns = ns),
output = structure(.createOutputWriter(self, ns = ns), class = "shinyoutput"),
makeScope = function(namespace) self$makeScope(ns(namespace)),
ns = function(namespace) ns(namespace),
setInputs = function(...) {
self$setInputs(!!!mapNames(ns, rlang::dots_list(..., .homonyms = "error")))
}
)
},
#' @description Set the environment associated with a testServer() call, but
#' only if it has not previously been set. This ensures that only the
#' environment of the outermost module under test is the one retained. In
#' other words, the first assignment wins.
#' @param env The environment to retain.
#' @return The provided `env`.
setEnv = function(env) {
if (is.null(self$env)) {
stopifnot(all(c("input", "output", "session") %in% ls(env)))
self$env <- env
}
},
#' @description Set the value returned by the module call and proactively
#' flush. Note that this method may be called multiple times if modules
#' are nested. The last assignment, corresponding to an invocation of
#' setReturned() in the outermost module, wins.
#' @param value The value returned from the module
#' @return The provided `value`.
setReturned = function(value) {
self$returned <- value
value
},
#' @description Get the value returned by the module call.
#' @return The value returned by the module call
getReturned = function() self$returned,
#' @description Generate a distinct character identifier for use as a proxy
#' namespace.
#' @return A character identifier unique to the current session.
genId = function() {
private$idCounter <- private$idCounter + 1
paste0("proxy", private$idCounter)
},
#' @description Provides a way to access the root `MockShinySession` from
#' any descendant proxy.
#' @return The root `MockShinySession`.
rootScope = function() {
self
},
#' @description Add an unhandled error callback.
#' @param callback The callback to add, which should accept an error object
#' as its first argument.
#' @return A deregistration function.
onUnhandledError = function(callback) {
private$unhandledErrorCallbacks$register(callback)
},
#' @description Called by observers when a reactive expression errors.
#' @param e An error object.
#' @param close If `TRUE`, the session will be closed after the error is
#' handled, defaults to `FALSE`.
unhandledError = function(e, close = TRUE) {
if (close) {
class(e) <- c("shiny.error.fatal", class(e))
}
private$unhandledErrorCallbacks$invoke(e, onError = printError)
.globals$onUnhandledErrorCallbacks$invoke(e, onError = printError)
if (close) self$close()
},
#' @description Freeze a value until the flush cycle completes.
#' @param x A `ReactiveValues` object.
#' @param name The name of a reactive value within `x`.
freezeValue = function(x, name) {
if (!is.reactivevalues(x))
stop("x must be a reactivevalues object")
impl <- .subset2(x, 'impl')
key <- .subset2(x, 'ns')(name)
impl$freeze(key)
self$onFlushed(function() impl$thaw(key))
},
#' @description Registers the given callback to be invoked when the session
#' is closed (i.e. the connection to the client has been severed). The
#' return value is a function which unregisters the callback. If multiple
#' callbacks are registered, the order in which they are invoked is not
#' guaranteed.
#' @param sessionEndedCallback Function to call when the session ends.
onSessionEnded = function(sessionEndedCallback) {
self$onEnded(sessionEndedCallback)
},
#' @description Associated a downloadable file with the session.
#' @param name The un-namespaced output name to associate with the
#' downloadable file.
#' @param filename A string or function designating the name of the file.
#' @param contentType A string of the content type of the file. Not used by
#' `MockShinySession`.
#' @param content A function that takes a single argument file that is a
#' file path (string) of a nonexistent temp file, and writes the content
#' to that file path. (Reactive values and functions may be used from this
#' function.)
registerDownload = function(name, filename, contentType, content) {
private$file_generators$set(self$ns(name), list(
filename = if (is.function(filename)) filename else function() filename,
content = content
))
},
#' @description Get information about the output that is currently being
#' executed.
#' @return A list with with the `name` of the output. If no output is
#' currently being executed, this will return `NULL`.
getCurrentOutputInfo = function() {
name <- private$currentOutputName
if (is.null(name)) NULL else list(name = name)
}
),
private = list(
# @field .input Internal ReactiveValues object for normal input sent from client.
.input = NULL,
# @field flushCBs `Callbacks` called before flush.
flushCBs = NULL,
# @field flushedCBs `Callbacks` called after flush.
flushedCBs = NULL,
# @field endedCBs `Callbacks` called when session ends.
endedCBs = NULL,
# @field unhandledErrorCallbacks `Callbacks` called when an unhandled error
# occurs.
unhandledErrorCallbacks = Callbacks$new(),
# @field timer `MockableTimerCallbacks` called at particular times.
timer = NULL,
# @field was_closed Set to `TRUE` once the session is closed.
was_closed = FALSE,
# @field outs List of namespaced output names.
outs = list(),
# @field nsPrefix Prefix with which to namespace inputs and outputs.
nsPrefix = "mock-session",
# @field idCounter Incremented every time `$genId()` is called.
idCounter = 0,
# @field file_generators Map of namespaced output names to lists with
# `filename` and `output` elements, each a function. Updated by
# `$registerDownload()` and read by `$getOutput()`. Files are generated
# on demand when the output is accessed.
file_generators = NULL,
# @field currentOutputName Namespaced name of the currently executing
#' output, or `NULL` if no output is currently executing.
currentOutputName = NULL,
# @description Writes a downloadable file to disk. If the `content` function
# associated with a download handler does not write a file, an error is
# signaled. Created files are deleted upon session close.
# @param name The eamespaced output name associated with the downloadable
# file.
# @param download List with two names, `filename` and `content`. Both should
# be functions. `filename` should take no arguments and return a string.
# `content` should accept a path argument and create a file at that path.
# @return A path to a temp file.
renderFile = function(name, download) {
# We make our own tempdir here because it's not safe to delete the result
# of tempdir().
tmpd <- tempfile()
dir.create(tmpd, recursive = TRUE)
self$onSessionEnded(function() unlink(tmpd, recursive = TRUE))
file <- file.path(tmpd, download$filename())
download$content(file)
if (!file.exists(file))
error("downloadHandler for ", name, " did not write a file.")
file
},
# @description Calls `shiny:::flushReact()` and executes all callbacks
# related to reactivity.
flush = function(){
isolate(private$flushCBs$invoke(..stacktraceon = TRUE))
shiny:::flushReact() # namespace to avoid calling our own method
isolate(private$flushedCBs$invoke(..stacktraceon = TRUE))
later::run_now()
},
# @description Produces a warning if the option `shiny.mocksession.warn` is
# unset and not `FALSE`.
# @param name The name of the mocked method.
# @param msg A message describing why the method is not implemented.
noopWarn = function(name, msg) {
if (getOption("shiny.mocksession.warn", FALSE) == FALSE)
return(invisible())
out <- paste0(name, " is not fully implemented by MockShinySession: ", msg)
out <- paste0(out, "\n", "To disable messages like this, run `options(shiny.mocksession.warn=FALSE)`")
warning(out, call. = FALSE)
},
# @description Binds a domain to `expr` and uses `createVarPromiseDomain()`
# to ensure `private$currentOutputName` is set to `name` around any of
# the promise's callbacks. Domains are something like dynamic scopes but
# for promise chains instead of the call stack.
# @return A promise.
withCurrentOutput = function(name, expr) {
if (!is.null(private$currentOutputName)) {
stop("Nested calls to withCurrentOutput() are not allowed.")
}
with_promise_domain(
createVarPromiseDomain(private, "currentOutputName", name),
expr
)
}
),
active = list(
#' @field files For internal use only.
files = function() stop("$files is for internal use only."),
#' @field downloads For internal use only.
downloads = function() stop("$downloads is for internal use only."),
#' @field closed Deprecated in `ShinySession` and signals an error.
closed = function() stop("$closed is deprecated"),
#' @field session Deprecated in ShinySession and signals an error.
session = function() stop("$session is deprecated"),
#' @field request An empty environment where the request should be. The request isn't meaningfully mocked currently.
request = function(value) {
if (!missing(value)){
stop("session$request can't be assigned to")
}
warning("session$request doesn't currently simulate a realistic request on MockShinySession")
new.env(parent=emptyenv())
}
)
)

206
R/modal.R Normal file
View File

@@ -0,0 +1,206 @@
#' Show or remove a modal dialog
#'
#' This causes a modal dialog to be displayed in the client browser, and is
#' typically used with [modalDialog()].
#'
#' @param ui UI content to show in the modal.
#' @param session The `session` object passed to function given to
#' `shinyServer`.
#'
#' @seealso [modalDialog()] for examples.
#' @export
showModal <- function(ui, session = getDefaultReactiveDomain()) {
res <- processDeps(ui, session)
session$sendModal("show",
list(
html = res$html,
deps = res$deps
)
)
}
#' @rdname showModal
#' @export
removeModal <- function(session = getDefaultReactiveDomain()) {
session$sendModal("remove", NULL)
}
#' Create a modal dialog UI
#'
#' @description
#' `modalDialog()` creates the UI for a modal dialog, using Bootstrap's modal
#' class. Modals are typically used for showing important messages, or for
#' presenting UI that requires input from the user, such as a user name and
#' password input.
#'
#' `modalButton()` creates a button that will dismiss the dialog when clicked,
#' typically used when customising the `footer`.
#'
#' @inheritParams actionButton
#' @param ... UI elements for the body of the modal dialog box.
#' @param title An optional title for the dialog.
#' @param footer UI for footer. Use `NULL` for no footer.
#' @param size One of `"s"` for small, `"m"` (the default) for medium,
#' `"l"` for large, or `"xl"` for extra large. Note that `"xl"` only
#' works with Bootstrap 4 and above (to opt-in to Bootstrap 4+,
#' pass [bslib::bs_theme()] to the `theme` argument of a page container
#' like [fluidPage()]).
#' @param easyClose If `TRUE`, the modal dialog can be dismissed by
#' clicking outside the dialog box, or be pressing the Escape key. If
#' `FALSE` (the default), the modal dialog can't be dismissed in those
#' ways; instead it must be dismissed by clicking on a `modalButton()`, or
#' from a call to [removeModal()] on the server.
#' @param fade If `FALSE`, the modal dialog will have no fade-in animation
#' (it will simply appear rather than fade in to view).
#'
#' @examples
#' if (interactive()) {
#' # Display an important message that can be dismissed only by clicking the
#' # dismiss button.
#' shinyApp(
#' ui = basicPage(
#' actionButton("show", "Show modal dialog")
#' ),
#' server = function(input, output) {
#' observeEvent(input$show, {
#' showModal(modalDialog(
#' title = "Important message",
#' "This is an important message!"
#' ))
#' })
#' }
#' )
#'
#'
#' # Display a message that can be dismissed by clicking outside the modal dialog,
#' # or by pressing Esc.
#' shinyApp(
#' ui = basicPage(
#' actionButton("show", "Show modal dialog")
#' ),
#' server = function(input, output) {
#' observeEvent(input$show, {
#' showModal(modalDialog(
#' title = "Somewhat important message",
#' "This is a somewhat important message.",
#' easyClose = TRUE,
#' footer = NULL
#' ))
#' })
#' }
#' )
#'
#'
#' # Display a modal that requires valid input before continuing.
#' shinyApp(
#' ui = basicPage(
#' actionButton("show", "Show modal dialog"),
#' verbatimTextOutput("dataInfo")
#' ),
#'
#' server = function(input, output) {
#' # reactiveValues object for storing current data set.
#' vals <- reactiveValues(data = NULL)
#'
#' # Return the UI for a modal dialog with data selection input. If 'failed' is
#' # TRUE, then display a message that the previous value was invalid.
#' dataModal <- function(failed = FALSE) {
#' modalDialog(
#' textInput("dataset", "Choose data set",
#' placeholder = 'Try "mtcars" or "abc"'
#' ),
#' span('(Try the name of a valid data object like "mtcars", ',
#' 'then a name of a non-existent object like "abc")'),
#' if (failed)
#' div(tags$b("Invalid name of data object", style = "color: red;")),
#'
#' footer = tagList(
#' modalButton("Cancel"),
#' actionButton("ok", "OK")
#' )
#' )
#' }
#'
#' # Show modal when button is clicked.
#' observeEvent(input$show, {
#' showModal(dataModal())
#' })
#'
#' # When OK button is pressed, attempt to load the data set. If successful,
#' # remove the modal. If not show another modal, but this time with a failure
#' # message.
#' observeEvent(input$ok, {
#' # Check that data object exists and is data frame.
#' if (!is.null(input$dataset) && nzchar(input$dataset) &&
#' exists(input$dataset) && is.data.frame(get(input$dataset))) {
#' vals$data <- get(input$dataset)
#' removeModal()
#' } else {
#' showModal(dataModal(failed = TRUE))
#' }
#' })
#'
#' # Display information about selected data
#' output$dataInfo <- renderPrint({
#' if (is.null(vals$data))
#' "No data selected"
#' else
#' summary(vals$data)
#' })
#' }
#' )
#' }
#' @export
modalDialog <- function(..., title = NULL, footer = modalButton("Dismiss"),
size = c("m", "s", "l", "xl"), easyClose = FALSE, fade = TRUE) {
size <- match.arg(size)
backdrop <- if (!easyClose) "static"
keyboard <- if (!easyClose) "false"
div(
id = "shiny-modal",
class = "modal",
class = if (fade) "fade",
tabindex = "-1",
`data-backdrop` = backdrop,
`data-bs-backdrop` = backdrop,
`data-keyboard` = keyboard,
`data-bs-keyboard` = keyboard,
div(
class = "modal-dialog",
class = switch(size, s = "modal-sm", m = NULL, l = "modal-lg", xl = "modal-xl"),
div(class = "modal-content",
if (!is.null(title)) div(class = "modal-header",
tags$h4(class = "modal-title", title)
),
div(class = "modal-body", ...),
if (!is.null(footer)) div(class = "modal-footer", footer)
)
),
# jQuery plugin doesn't work in Bootstrap 5, but vanilla JS doesn't work in Bootstrap 4 :sob:
tags$script(HTML(
"if (window.bootstrap && !window.bootstrap.Modal.VERSION.match(/^4\\./)) {
var modal = new bootstrap.Modal(document.getElementById('shiny-modal'));
modal.show();
} else {
$('#shiny-modal').modal().focus();
}"
))
)
}
#' @export
#' @rdname modalDialog
modalButton <- function(label, icon = NULL) {
tags$button(
type = "button",
class = "btn btn-default",
`data-dismiss` = "modal",
`data-bs-dismiss` = "modal",
validateIcon(icon), label
)
}

199
R/modules.R Normal file
View File

@@ -0,0 +1,199 @@
# Creates an object whose $ and [[ pass through to the parent
# session, unless the name is matched in ..., in which case
# that value is returned instead. (See Decorator pattern.)
createSessionProxy <- function(parentSession, ...) {
e <- new.env(parent = emptyenv())
e$parent <- parentSession
e$overrides <- list(...)
structure(
e,
class = "session_proxy"
)
}
#' @export
`$.session_proxy` <- function(x, name) {
if (name %in% names(.subset2(x, "overrides")))
.subset2(x, "overrides")[[name]]
else
.subset2(x, "parent")[[name]]
}
#' @export
`[[.session_proxy` <- `$.session_proxy`
#' @export
`$<-.session_proxy` <- function(x, name, value) {
# this line allows users to write into session$userData
# (e.g. it allows something like `session$userData$x <- TRUE`,
# but not `session$userData <- TRUE`) from within a module
# without any hacks (see PR #1732)
if (identical(x[[name]], value)) return(x)
# Special case for $options (issue #3112)
if (name == "options") {
session <- find_ancestor_session(x)
session[[name]] <- value
return(x)
}
stop("Attempted to assign value on session proxy.")
}
`[[<-.session_proxy` <- `$<-.session_proxy`
# Given a session_proxy, search `parent` recursively to find the real
# ShinySession object. If given a ShinySession, simply return it.
find_ancestor_session <- function(x, depth = 20) {
if (depth < 0) {
stop("ShinySession not found")
}
if (inherits(x, "ShinySession")) {
return(x)
}
if (inherits(x, "session_proxy")) {
return(find_ancestor_session(.subset2(x, "parent"), depth-1))
}
stop("ShinySession not found")
}
#' Shiny modules
#'
#' Shiny's module feature lets you break complicated UI and server logic into
#' smaller, self-contained pieces. Compared to large monolithic Shiny apps,
#' modules are easier to reuse and easier to reason about. See the article at
#' <https://shiny.rstudio.com/articles/modules.html> to learn more.
#'
#' Starting in Shiny 1.5.0, we recommend using `moduleServer` instead of
#' [`callModule()`], because the syntax is a little easier
#' to understand, and modules created with `moduleServer` can be tested with
#' [`testServer()`].
#'
#' @param module A Shiny module server function.
#' @param id An ID string that corresponds with the ID used to call the module's
#' UI function.
#' @param session Session from which to make a child scope (the default should
#' almost always be used).
#'
#' @return The return value, if any, from executing the module server function
#' @seealso <https://shiny.rstudio.com/articles/modules.html>
#'
#' @examples
#' # Define the UI for a module
#' counterUI <- function(id, label = "Counter") {
#' ns <- NS(id)
#' tagList(
#' actionButton(ns("button"), label = label),
#' verbatimTextOutput(ns("out"))
#' )
#' }
#'
#' # Define the server logic for a module
#' counterServer <- function(id) {
#' moduleServer(
#' id,
#' function(input, output, session) {
#' count <- reactiveVal(0)
#' observeEvent(input$button, {
#' count(count() + 1)
#' })
#' output$out <- renderText({
#' count()
#' })
#' count
#' }
#' )
#' }
#'
#' # Use the module in an app
#' ui <- fluidPage(
#' counterUI("counter1", "Counter #1"),
#' counterUI("counter2", "Counter #2")
#' )
#' server <- function(input, output, session) {
#' counterServer("counter1")
#' counterServer("counter2")
#' }
#' if (interactive()) {
#' shinyApp(ui, server)
#' }
#'
#'
#'
#' # If you want to pass extra parameters to the module's server logic, you can
#' # add them to your function. In this case `prefix` is text that will be
#' # printed before the count.
#' counterServer2 <- function(id, prefix = NULL) {
#' moduleServer(
#' id,
#' function(input, output, session) {
#' count <- reactiveVal(0)
#' observeEvent(input$button, {
#' count(count() + 1)
#' })
#' output$out <- renderText({
#' paste0(prefix, count())
#' })
#' count
#' }
#' )
#' }
#'
#' ui <- fluidPage(
#' counterUI("counter", "Counter"),
#' )
#' server <- function(input, output, session) {
#' counterServer2("counter", "The current count is: ")
#' }
#' if (interactive()) {
#' shinyApp(ui, server)
#' }
#'
#' @export
moduleServer <- function(id, module, session = getDefaultReactiveDomain()) {
if (inherits(session, "MockShinySession")) {
body(module) <- rlang::expr({
session$setEnv(base::environment())
!!body(module)
})
session$setReturned(callModule(module, id, session = session))
} else {
callModule(module, id, session = session)
}
}
#' Invoke a Shiny module
#'
#' Note: As of Shiny 1.5.0, we recommend using [`moduleServer()`] instead of
#' [`callModule()`], because the syntax is a little easier
#' to understand, and modules created with `moduleServer` can be tested with
#' [`testServer()`].
#'
#' @param module A Shiny module server function
#' @param id An ID string that corresponds with the ID used to call the module's
#' UI function
#' @param ... Additional parameters to pass to module server function
#' @param session Session from which to make a child scope (the default should
#' almost always be used)
#'
#' @return The return value, if any, from executing the module server function
#' @export
callModule <- function(module, id, ..., session = getDefaultReactiveDomain()) {
if (!inherits(session, c("ShinySession", "session_proxy", "MockShinySession"))) {
stop("session must be a ShinySession or session_proxy object.")
}
childScope <- session$makeScope(id)
withReactiveDomain(childScope, {
if (!is.function(module)) {
stop("module argument must be a function")
}
module(childScope$input, childScope$output, childScope, ...)
})
}

106
R/notifications.R Normal file
View File

@@ -0,0 +1,106 @@
#' Show or remove a notification
#'
#' These functions show and remove notifications in a Shiny application.
#'
#' @param ui Content of message.
#' @param action Message content that represents an action. For example, this
#' could be a link that the user can click on. This is separate from `ui`
#' so customized layouts can handle the main notification content separately
#' from action content.
#' @param duration Number of seconds to display the message before it
#' disappears. Use `NULL` to make the message not automatically
#' disappear.
#' @param closeButton If `TRUE`, display a button which will make the
#' notification disappear when clicked. If `FALSE` do not display.
#' @param id A unique identifier for the notification.
#'
#' `id` is optional for `showNotification()`: Shiny will automatically create
#' one if needed. If you do supply it, Shiny will update an existing
#' notification if it exists, otherwise it will create a new one.
#'
#' `id` is required for `removeNotification()`.
#' @param type A string which controls the color of the notification. One of
#' "default" (gray), "message" (blue), "warning" (yellow), or "error" (red).
#' @param session Session object to send notification to.
#'
#' @return An ID for the notification.
#'
#' @examples
#' ## Only run examples in interactive R sessions
#' if (interactive()) {
#' # Show a message when button is clicked
#' shinyApp(
#' ui = fluidPage(
#' actionButton("show", "Show")
#' ),
#' server = function(input, output) {
#' observeEvent(input$show, {
#' showNotification("Message text",
#' action = a(href = "javascript:location.reload();", "Reload page")
#' )
#' })
#' }
#' )
#'
#' # App with show and remove buttons
#' shinyApp(
#' ui = fluidPage(
#' actionButton("show", "Show"),
#' actionButton("remove", "Remove")
#' ),
#' server = function(input, output) {
#' # A queue of notification IDs
#' ids <- character(0)
#' # A counter
#' n <- 0
#'
#' observeEvent(input$show, {
#' # Save the ID for removal later
#' id <- showNotification(paste("Message", n), duration = NULL)
#' ids <<- c(ids, id)
#' n <<- n + 1
#' })
#'
#' observeEvent(input$remove, {
#' if (length(ids) > 0)
#' removeNotification(ids[1])
#' ids <<- ids[-1]
#' })
#' }
#' )
#' }
#' @export
showNotification <- function(ui, action = NULL, duration = 5,
closeButton = TRUE, id = NULL,
type = c("default", "message", "warning", "error"),
session = getDefaultReactiveDomain())
{
if (is.null(id))
id <- createUniqueId(8)
res <- processDeps(ui, session)
actionRes <- processDeps(action, session)
session$sendNotification("show",
list(
html = res$html,
action = actionRes$html,
deps = c(res$deps, actionRes$deps),
duration = if (!is.null(duration)) duration * 1000,
closeButton = closeButton,
id = id,
type = match.arg(type)
)
)
id
}
#' @rdname showNotification
#' @export
removeNotification <- function(id, session = getDefaultReactiveDomain()) {
force(id)
session$sendNotification("remove", id)
id
}

65
R/otel-attr-srcref.R Normal file
View File

@@ -0,0 +1,65 @@
# Very similar to srcrefFromShinyCall(),
# however, this works when the function does not have a srcref attr set
otel_srcref_attributes <- function(srcref, fn_name = NULL) {
if (is.function(srcref)) {
srcref <- getSrcRefs(srcref)[[1]][[1]]
}
if (is.null(srcref)) {
return(NULL)
}
stopifnot(inherits(srcref, "srcref"))
# Semantic conventions for code: https://opentelemetry.io/docs/specs/semconv/registry/attributes/code/
#
# Inspiration from https://github.com/r-lib/testthat/pull/2087/files#diff-92de3306849d93d6f7e76c5aaa1b0c037e2d716f72848f8a1c70536e0c8a1564R123-R124
filename <- attr(srcref, "srcfile")$filename
dropNulls(list(
"code.function.name" = fn_name,
# Location attrs
"code.file.path" = filename,
"code.line.number" = srcref[1],
"code.column.number" = srcref[2],
# Remove these deprecated location names once Logfire supports the preferred names
# https://github.com/pydantic/logfire/issues/1559
"code.filepath" = filename,
"code.lineno" = srcref[1],
"code.column" = srcref[2]
))
}
#' Get the srcref for the call at the specified stack level
#'
#' If you need to go farther back in the `sys.call()` stack, supply a larger
#' negative number to `which_offset`. The default of 0 gets the immediate
#' caller. `-1` would get the caller's caller, and so on.
#' @param which_offset The stack level to get the call from. Defaults to -1 (the
#' immediate caller).
#' @return An srcref object, or NULL if none is found.
#' @noRd
get_call_srcref <- function(which_offset = 0) {
# Go back one call to account for this function itself
call <- sys.call(which_offset - 1)
srcref <- attr(call, "srcref", exact = TRUE)
srcref
}
append_otel_srcref_attrs <- function(attrs, call_srcref, fn_name) {
if (is.null(call_srcref)) {
return(attrs)
}
srcref_attrs <- otel_srcref_attributes(call_srcref, fn_name)
if (is.null(srcref_attrs)) {
return(attrs)
}
attrs[names(srcref_attrs)] <- srcref_attrs
attrs
}

55
R/otel-collect.R Normal file
View File

@@ -0,0 +1,55 @@
otel_collect_choices <- c(
"none",
"session",
"reactive_update",
"reactivity",
"all"
)
# Check if the collect level is sufficient
otel_collect_is_enabled <- function(
impl_level,
# Listen to option and fall back to the env var
opt_collect_level = getOption("shiny.otel.collect", Sys.getenv("SHINY_OTEL_COLLECT", "all"))
) {
opt_collect_level <- as_otel_collect(opt_collect_level)
which(opt_collect_level == otel_collect_choices) >=
which(impl_level == otel_collect_choices)
}
# Check if tracing is enabled and if the collect level is sufficient
has_otel_collect <- function(collect) {
# Only check pkg author input iff loaded with pkgload
if (IS_SHINY_LOCAL_PKG) {
stopifnot(length(collect) == 1, any(collect == otel_collect_choices))
}
otel_is_tracing_enabled() && otel_collect_is_enabled(collect)
}
# Run expr with otel collection disabled
with_no_otel_collect <- function(expr) {
withOtelCollect("none", expr)
}
## -- Helpers -----------------------------------------------------
# shiny.otel.collect can be:
# "none"; To do nothing / fully opt-out
# "session" for session/start events
# "reactive_update" (includes "session" features) and reactive_update spans
# "reactivity" (includes "reactive_update" features) and spans for all reactive things
# "all" - Anything that Shiny can do. (Currently equivalent to the "reactivity" level)
as_otel_collect <- function(collect = "all") {
if (!is.character(collect)) {
stop("`collect` must be a character vector.")
}
# Match to collect enum
collect <- match.arg(collect, otel_collect_choices, several.ok = FALSE)
return(collect)
}

194
R/otel-enable.R Normal file
View File

@@ -0,0 +1,194 @@
# # Approach
# Use flags on the reactive object to indicate whether to record OpenTelemetry spans.
#
# Cadence:
# * `$.isRecordingOtel` - Whether to record OpenTelemetry spans for this reactive object
# * `$.otelLabel` - The label to use for the OpenTelemetry span
# * `$.otelAttrs` - Additional attributes to add to the OpenTelemetry span
#' Add OpenTelemetry for reactivity to an object
#'
#' @description
#'
#' `enable_otel_*()` methods add OpenTelemetry flags for [reactive()] expressions
#' and `render*` functions (like [renderText()], [renderTable()], ...).
#'
#' Wrapper to creating an active reactive OpenTelemetry span that closes when
#' the reactive expression is done computing. Typically this is when the
#' reactive expression finishes (synchronous) or when the returned promise is
#' done computing (asynchronous).
#' @section Async with OpenTelemetry:
#'
#' With a reactive expression, the key and/or value expression can be
#' _asynchronous_. In other words, they can be promises --- not regular R
#' promises, but rather objects provided by the
#' \href{https://rstudio.github.io/promises/}{\pkg{promises}} package, which
#' are similar to promises in JavaScript. (See [promises::promise()] for more
#' information.) You can also use [mirai::mirai()] or [future::future()]
#' objects to run code in a separate process or even on a remote machine.
#'
#' When reactive expressions are being calculated in parallel (by having
#' another reactive promise compute in the main process), the currently active
#' OpenTelemetry span will be dynamically swapped out according to the
#' currently active reactive expression. This means that as long as a promise
#' was `then()`ed or `catch()`ed with an active OpenTelemetry span, the span
#' will be correctly propagated to the next step (and subsequently other
#' steps) in the promise chain.
#'
#' While the common case is for a reactive expression to be created
#' synchronously, troubles arise when the reactive expression is created
#' asynchronously. The span **must** be created before the reactive expression
#' is executed, it **must** be active for the duration of the expression, and
#' it **must** not be closed until the reactive expression is done executing.
#' This is not easily achieved with a single function call, so we provide a
#' way to create a reactive expression that is bound to an OpenTelemetry
#' span.
#'
#' @section Span management and performance:
#'
#' Dev note - Barret 2025-10:
#' Typically, an OpenTelemetry span (`otel_span`) will inherit from the parent
#' span. This works well and we can think of the hierarchy as a tree. With
#' `options("shiny.otel.collect" = <value>)`, we are able to control with a sliding
#' dial how much of the tree we are interested in: "none", "session",
#' "reactive_update", "reactivity", and finally "all".
#'
#' Leveraging this hierarchy, we can avoid creating spans that are not needed.
#' The act of making a noop span takes on the order of 10microsec. Handling of
#' the opspan is also in the 10s of microsecond range. We should avoid this when
#' we **know** that we're not interested in the span. Therefore, manually
#' handling spans should be considered for Shiny.
#'
#' * Q:
#' * But what about app author who want the current span? Is there any
#' guarantee that the current span is expected `reactive()` span?
#' * A:
#' * No. The current span is whatever the current span is. If the app author
#' wants a specific span, they should create it themselves.
#' * Proof:
#' ```r
#' noop <- otel::get_active_span()
#' noop$get_context()$get_span_id()
#' #> [1] "0000000000000000"
#' ignore <- otelsdk::with_otel_record({
#' a <- otel::start_local_active_span("a")
#' a$get_context()$get_span_id() |> str()
#' otel::with_active_span(noop, {
#' otel::get_active_span()$get_context()$get_span_id() |> str()
#' })
#' })
#' #> chr "2645e95715841e75"
#' #> chr "2645e95715841e75"
#' # ## It is reasonable to expect the second id to be `0000000000000000`, but it's not.
#' ```
#' Therefore, the app author has no guarantee that the current span is the
#' span they're expecting. If the app author wants a specific span, they should
#' create it themselves and let natural inheritance take over.
#'
#' Given this, I will imagine that app authors will set
#' `options("shiny.otel.collect" = "reactive_update")` as their default behavior.
#' Enough to know things are happening, but not overwhelming from **everything**
#' that is reactive.
#'
#' To _light up_ a specific area, users can call `withr::with_options(list("shiny.otel.collect" = "all"), { ... })`.
#'
#' @param x The object to add caching to.
#' @param ... Future parameter expansion.
#' @noRd
NULL
enable_otel_reactive_val <- function(x) {
impl <- attr(x, ".impl", exact = TRUE)
# Set flag for otel logging when setting the value
impl$.isRecordingOtel <- TRUE
class(x) <- c("reactiveVal.otel", class(x))
x
}
enable_otel_reactive_values <- function(x) {
impl <- .subset2(x, "impl")
# Set flag for otel logging when setting values
impl$.isRecordingOtel <- TRUE
class(x) <- c("reactivevalues.otel", class(x))
x
}
enable_otel_reactive_expr <- function(x) {
domain <- reactive_get_domain(x)
impl <- attr(x, "observable", exact = TRUE)
impl$.isRecordingOtel <- TRUE
# Covers both reactive and reactive.event
impl$.otelLabel <- otel_span_label_reactive(x, domain = impl$.domain)
class(x) <- c("reactiveExpr.otel", class(x))
x
}
enable_otel_observe <- function(x) {
x$.isRecordingOtel <- TRUE
x$.otelLabel <- otel_span_label_observer(x, domain = x$.domain)
class(x) <- c("Observer.otel", class(x))
invisible(x)
}
enable_otel_shiny_render_function <- function(x) {
valueFunc <- force(x)
otel_span_label <- NULL
otel_span_attrs <- NULL
renderFunc <- function(...) {
# Dynamically determine the span label given the current reactive domain
if (is.null(otel_span_label)) {
domain <- getDefaultReactiveDomain()
otel_span_label <<-
otel_span_label_render_function(x, domain = domain)
otel_span_attrs <<- c(
attr(x, "otelAttrs"),
otel_session_id_attrs(domain)
)
}
with_otel_span(
otel_span_label,
{
hybrid_then(
valueFunc(...),
on_failure = set_otel_exception_status_and_throw,
# Must save the error object
tee = FALSE
)
},
attributes = otel_span_attrs
)
}
renderFunc <- addAttributes(renderFunc, renderFunctionAttributes(valueFunc))
class(renderFunc) <- c("shiny.render.function.otel", class(valueFunc))
renderFunc
}
# ## If we ever expose a S3 function, I'd like to add this method.
# bindOtel.function <- function(x, ...) {
# cli::cli_abort(paste0(
# "Don't know how to add OpenTelemetry recording to a plain function. ",
# "If this is a {.code render*()} function for Shiny, it may need to be updated. ",
# "Please see {.help shiny::bindOtel} for more information."
# ))
# }

56
R/otel-error.R Normal file
View File

@@ -0,0 +1,56 @@
has_seen_otel_exception <- function(cnd) {
!is.null(cnd$.shiny_otel_exception)
}
mark_otel_exception_as_seen <- function(cnd) {
cnd$.shiny_otel_exception <- TRUE
cnd
}
set_otel_exception_status_and_throw <- function(cnd) {
cnd <- set_otel_exception_status(cnd)
# Rethrow the (possibly updated) error
signalCondition(cnd)
}
set_otel_exception_status <- function(cnd) {
if (inherits(cnd, "shiny.custom.error")) {
# No-op
} else if (inherits(cnd, "shiny.output.cancel")) {
# No-op
} else if (inherits(cnd, "shiny.output.progress")) {
# No-op
} else if (cnd_inherits(cnd, "shiny.silent.error")) {
# No-op
} else {
# Only when an unknown error occurs do we set the span status to error
span <- otel::get_active_span()
# Only record the exception once at the original point of failure,
# not every reactive expression that it passes through
if (!has_seen_otel_exception(cnd)) {
span$record_exception(
# Record a sanitized error if sanitization is enabled
get_otel_error_obj(cnd)
)
cnd <- mark_otel_exception_as_seen(cnd)
}
# Record the error status on the span for any context touching this error
span$set_status("error")
}
cnd
}
get_otel_error_obj <- function(e) {
# Do not expose errors to otel if sanitization is enabled
if (getOption("shiny.otel.sanitize.errors", TRUE)) {
sanitized_error()
} else {
e
}
}

198
R/otel-label.R Normal file
View File

@@ -0,0 +1,198 @@
# observe mymod:<anonymous>
# observe <anonymous>
# observe mylabel
# -- Reactives --------------------------------------------------------------
#' OpenTelemetry Label Generation Functions
#'
#' Functions for generating formatted labels for OpenTelemetry tracing spans
#' in Shiny applications. These functions handle module namespacing and
#' cache/event modifiers for different Shiny reactive constructs.
#'
#' @param x The object to generate a label for (reactive, observer, etc.)
#' @param label Character string label for reactive values
#' @param key Character string key for reactiveValues operations
#' @param ... Additional arguments (unused)
#' @param domain Shiny domain object containing namespace information
#'
#' @return Character string formatted for OpenTelemetry span labels
#' @name otel_label
#' @noRd
NULL
otel_span_label_reactive <- function(x, ..., domain) {
fn_name <- otel_label_with_modifiers(
x,
"reactive",
cache_class = "reactive.cache",
event_class = "reactive.event"
)
label <- attr(x, "observable", exact = TRUE)[[".label"]]
otel_span_label <- otel_label_upgrade(label, domain = domain)
sprintf("%s %s", fn_name, otel_span_label)
}
otel_span_label_render_function <- function(x, ..., domain) {
fn_name <- otel_label_with_modifiers(
x,
"output",
cache_class = "shiny.render.function.cache",
event_class = "shiny.render.function.event"
)
label <- getCurrentOutputInfo(session = domain)$name %||% "<unknown>"
otel_span_label <- otel_label_upgrade(label, domain = domain)
sprintf("%s %s", fn_name, otel_span_label)
}
otel_span_label_observer <- function(x, ..., domain) {
fn_name <- otel_label_with_modifiers(
x,
"observe",
cache_class = NULL, # Do not match a cache class here
event_class = "Observer.event"
)
otel_span_label <- otel_label_upgrade(x$.label, domain = domain)
sprintf("%s %s", fn_name, otel_span_label)
}
# -- Set reactive value(s) ----------------------------------------------------
otel_log_label_set_reactive_val <- function(label, ..., domain) {
sprintf(
"Set reactiveVal %s",
otel_label_upgrade(label, domain = domain)
)
}
otel_log_label_set_reactive_values <- function(label, key, ..., domain) {
sprintf(
"Set reactiveValues %s$%s",
otel_label_upgrade(label, domain = domain),
key
)
}
# -- ExtendedTask -------------------------------------------------------------
otel_span_label_extended_task <- function(label, suffix = NULL, ..., domain) {
sprintf(
"ExtendedTask %s",
otel_label_upgrade(label, domain = domain)
)
}
otel_log_label_extended_task_add_to_queue <- function(label, ..., domain) {
sprintf(
"ExtendedTask %s add to queue",
otel_label_upgrade(label, domain = domain)
)
}
# -- Debounce / Throttle -------------------------------------------------------
otel_label_debounce <- function(label, ..., domain) {
sprintf(
"debounce %s",
otel_label_upgrade(label, domain = domain)
)
}
otel_label_throttle <- function(label, ..., domain) {
sprintf(
"throttle %s",
otel_label_upgrade(label, domain = domain)
)
}
# ---- Reactive Poll / File Reader -----------------------------------------------
otel_label_reactive_poll <- function(label, ..., domain) {
sprintf(
"reactivePoll %s",
otel_label_upgrade(label, domain = domain)
)
}
otel_label_reactive_file_reader <- function(label, ..., domain) {
sprintf(
"reactiveFileReader %s",
otel_label_upgrade(label, domain = domain)
)
}
# -- Helpers --------------------------------------------------------------
#' Modify function name based on object class modifiers
#'
#' @param x Object to check class of
#' @param fn_name Base function name
#' @param cache_class Optional class name that indicates cache operation
#' @param event_class Optional class name that indicates event operation
#'
#' @return Modified function name with "cache" or "event" suffix if applicable
#' @noRd
otel_label_with_modifiers <- function(
x,
fn_name,
cache_class = NULL,
event_class = NULL
) {
for (x_class in rev(class(x))) {
if (!is.null(cache_class) && x_class == cache_class) {
fn_name <- sprintf("%s cache", fn_name)
} else if (!is.null(event_class) && x_class == event_class) {
fn_name <- sprintf("%s event", fn_name)
}
}
fn_name
}
#' Upgrade and format OpenTelemetry labels with module namespacing
#'
#' Processes labels for OpenTelemetry tracing, replacing default verbose labels
#' with cleaner alternatives and prepending module namespaces when available.
#'
#' @param label Character string label to upgrade
#' @param ... Additional arguments (unused)
#' @param domain Shiny domain object containing namespace information
#'
#' @return Modified label string with module prefix if applicable
#' @noRd
#'
#' @details
#' Module prefix examples:
#' - "" -> ""
#' - "my-nested-mod-" -> "my-nested-mod"
otel_label_upgrade <- function(label, ..., domain) {
# By default, `observe()` sets the label to `observe(CODE)`
# This label is too big and inconsistent.
# Replace it with `<anonymous>`
# (Similar with `eventReactive()` and `observeEvent()`)
if (is_default_label(label) && grepl("(", label, fixed = TRUE)) {
label <- "<anonymous>"
# label <- sprintf("<anonymous> - %s", label)
}
if (is.null(domain)) {
return(label)
}
namespace <- domain$ns("")
if (!nzchar(namespace)) {
return(label)
}
# Remove trailing module separator
mod_ns <- sub(sprintf("%s$", ns.sep), "", namespace)
# Prepend the module name to the label
# Ex: `"mymod:x"`
sprintf("%s:%s", mod_ns, label)
}

114
R/otel-reactive-update.R Normal file
View File

@@ -0,0 +1,114 @@
# * `session$userData[["_otel_span_reactive_update"]]` - The active reactive update span (or `NULL`)
#' Start a `reactive_update` OpenTelemetry span and store it
#'
#' Used when a reactive expression is updated
#' Will only start the span iff the otel tracing is enabled
#' @param ... Ignored
#' @param domain The reactive domain to associate with the span
#' @return Invisibly returns.
#' @seealso `otel_span_reactive_update_teardown()`
#' @noRd
otel_span_reactive_update_init <- function(..., domain) {
if (!has_otel_collect("reactive_update")) return()
# Ensure cleanup is registered only once per session
if (is.null(domain$userData[["_otel_has_reactive_cleanup"]])) {
domain$userData[["_otel_has_reactive_cleanup"]] <- TRUE
# Clean up any dangling reactive spans on an unplanned exit
domain$onSessionEnded(function() {
otel_span_reactive_update_teardown(domain = domain)
})
}
# Safety check
if (is_otel_span(domain$userData[["_otel_span_reactive_update"]])) {
stop("Reactive update span already exists")
}
domain$userData[["_otel_span_reactive_update"]] <-
start_otel_span(
"reactive_update",
...,
attributes = otel_session_id_attrs(domain)
)
invisible()
}
#' End a `reactive_update` OpenTelemetry span and remove it from the session
#' @param ... Ignored
#' @param domain The reactive domain to associate with the span
#' @return Invisibly returns.
#' @seealso `otel_span_reactive_update_init()`
#' @noRd
otel_span_reactive_update_teardown <- function(..., domain) {
ospan <- domain$userData[["_otel_span_reactive_update"]]
if (is_otel_span(ospan)) {
otel::end_span(ospan)
domain$userData[["_otel_span_reactive_update"]] <- NULL
}
invisible()
}
#' Run expr within a `reactive_update` OpenTelemetry span
#'
#' Used to wrap the execution of a reactive expression. Will only
#' require/activate the span iff the otel tracing is enabled
#' @param expr The expression to executed within the span
#' @param ... Ignored
#' @param domain The reactive domain to associate with the span
#' @noRd
with_otel_span_reactive_update <- function(expr, ..., domain) {
ospan <- domain$userData[["_otel_span_reactive_update"]]
if (!is_otel_span(ospan)) {
return(force(expr))
}
# Given the reactive update span is started before and ended when exec count
# is 0, we only need to wrap the expr in the span context
otel::with_active_span(ospan, {force(expr)})
}
#' Run expr within `reactive_update` otel span if not already active
#'
#' If the reactive update otel span is not already active, run the expression
#' within the reactive update otel span context. This ensures that nested calls
#' to reactive expressions do not attempt to re-enter the same span.
#'
#' This method is used within Context `run()` and running an Output's observer
#' implementation
#' @param expr The expression to executed within the span
#' @param ... Ignored
#' @param domain The reactive domain to associate with the span
#' @noRd
maybe_with_otel_span_reactive_update <- function(expr, ..., domain) {
if (is.null(domain$userData[["_otel_reactive_update_is_active"]])) {
domain$userData[["_otel_reactive_update_is_active"]] <- TRUE
# When the expression is done promising, clear the active flag
hybrid_then(
{
with_otel_span_reactive_update(domain = domain, expr)
},
on_success = function(value) {
domain$userData[["_otel_reactive_update_is_active"]] <- NULL
},
on_failure = function(e) {
domain$userData[["_otel_reactive_update_is_active"]] <- NULL
},
# Return the value before the callbacks
tee = TRUE
)
} else {
expr
}
}

96
R/otel-session.R Normal file
View File

@@ -0,0 +1,96 @@
# Semantic conventions for session: https://opentelemetry.io/docs/specs/semconv/general/session/
#' Create and use session span and events
#'
#' If otel is disabled, the session span and events will not be created,
#' however the expression will still be evaluated.
#'
#' Span: `session_start`, `session_end`
#' @param expr Expression to evaluate within the session span
#' @param ... Ignored
#' @param domain The reactive domain
#' @noRd
otel_span_session_start <- function(expr, ..., domain) {
if (!has_otel_collect("session")) {
return(force(expr))
}
# Wrap the server initialization
with_otel_span(
"session_start",
expr,
attributes = otel::as_attributes(c(
otel_session_id_attrs(domain),
otel_session_attrs(domain)
))
)
}
otel_span_session_end <- function(expr, ..., domain) {
if (!has_otel_collect("session")) {
return(force(expr))
}
id_attrs <- otel_session_id_attrs(domain)
with_otel_span(
"session_end",
expr,
attributes = id_attrs
)
}
# -- Helpers -------------------------------
# Occurs when the websocket connection is established
otel_session_attrs <- function(domain) {
# TODO: Future: Posit Connect integration
# > we are still trying to identify all of the information we want to track/expose
#
# * `POSIT_PRODUCT` (Fallback to RSTUDIO_PRODUCT) for host environment
# * `CONNECT_SERVER` envvar to get the `session.address`.
# * `CONNECT_CONTENT_GUID` for the consistent app distinguisher
# * Maybe `CONNECT_CONTENT_JOB_KEY`?
# * Maybe `user.id` to be their user name: https://opentelemetry.io/docs/specs/semconv/registry/attributes/user/
attrs <- list(
server.path =
sub(
"/websocket/$", "/",
domain[["request"]][["PATH_INFO"]] %||% ""
),
server.address = domain[["request"]][["HTTP_HOST"]] %||% "",
server.origin = domain[["request"]][["HTTP_ORIGIN"]] %||% "",
## Currently, Shiny does not expose QUERY_STRING when connecting the websocket
# so we do not provide it here.
# QUERY_STRING = domain[["request"]][["QUERY_STRING"]] %||% "",
server.port = domain[["request"]][["SERVER_PORT"]] %||% NA_integer_
)
# Safely convert SERVER_PORT to integer
# If conversion fails, leave as-is (string or empty)
# This avoids warnings/errors if SERVER_PORT is not a valid integer
server_port <- suppressWarnings(as.integer(attrs$server.port))
if (!is.na(server_port)) {
attrs$server.port <- server_port
}
attrs
}
otel_session_id_attrs <- function(domain) {
token <- domain$token
if (is.null(token)) {
return(list())
}
list(
# Convention for client-side with session.start and session.end events
# https://opentelemetry.io/docs/specs/semconv/general/session/
#
# Since we are the server, we'll add them as an attribute to _every_ span
# within the session as we don't know exactly when they will be called.
# Given it's only a single attribute, the cost should be minimal, but it ties every reactive calculation together.
session.id = token
)
}

127
R/otel-shiny.R Normal file
View File

@@ -0,0 +1,127 @@
# Used by otel to identify the tracer and logger for this package
# https://github.com/r-lib/otel/blob/afc31bc1f4bd177870d44b051ada1d9e4e685346/R/tracer-name.R#L33-L49
# DO NOT CHANGE THIS VALUE without understanding the implications for existing telemetry data!
otel_tracer_name <- "co.posit.r-package.shiny"
init_otel <- function() {
.globals$otel_tracer <- otel::get_tracer()
.globals$otel_is_tracing_enabled <- otel::is_tracing_enabled(.globals$otel_tracer)
.globals$otel_logger <- otel::get_logger()
# .globals$otel_is_logging_enabled <- otel::is_logging_enabled()
}
on_load({init_otel()})
#' Run expr within a Shiny OpenTelemetry recording context
#'
#' Reset the OpenTelemetry tracer and logger for Shiny.
#' Used for testing purposes only.
#' @param expr Expression to evaluate within the recording context
#' @return The result of evaluating `otelsdk::with_otel_record(expr)` with freshly enabled Shiny otel tracer and logger
#' @noRd
with_shiny_otel_record <- function(expr) {
# Only use within internal testthat tests
stopifnot(testthat__is_testing())
withr::defer({ init_otel() })
otelsdk::with_otel_record({
init_otel()
force(expr)
})
}
#' Check if OpenTelemetry tracing is enabled
#'
#' @param tracer The OpenTelemetry tracer to check (default: Shiny otel tracer)
#' @return `TRUE` if tracing is enabled, `FALSE` otherwise
#' @noRd
otel_is_tracing_enabled <- function() {
.globals[["otel_is_tracing_enabled"]]
}
#' Shiny OpenTelemetry logger
#'
#' Used for logging OpenTelemetry events via `otel_log()`
#' @return An OpenTelemetry logger
#' @noRd
shiny_otel_logger <- function() {
.globals[["otel_logger"]]
}
#' Shiny OpenTelemetry tracer
#'
#' Used for creating OpenTelemetry spans via `with_otel_span()` and
#' `start_otel_span()`
#'
#' Inspired by httr2:::get_tracer().
#' @return An OpenTelemetry tracer
#' @noRd
shiny_otel_tracer <- function() {
.globals[["otel_tracer"]]
}
#' Create and use a Shiny OpenTelemetry span
#'
#' If otel is disabled, the span will not be created,
#' however the expression will still be evaluated.
#' @param name Span name
#' @param expr Expression to evaluate within the span
#' @param ... Ignored
#' @param attributes Optional span attributes
#' @return The result of evaluating `expr`
#' @noRd
with_otel_span <- function(name, expr, ..., attributes = NULL) {
promises::with_otel_span(name, expr, ..., attributes = attributes, tracer = shiny_otel_tracer())
}
#' Start a Shiny OpenTelemetry span
#'
#' @param name Span name
#' @param ... Additional arguments passed to `otel::start_span()`
#' @return An OpenTelemetry span
#' @noRd
start_otel_span <- function(name, ...) {
otel::start_span(name, ..., tracer = shiny_otel_tracer())
}
# # TODO: Set attributes on the current active span
# # 5. Set attributes on the current active span
# set_otel_span_attrs(status = 200L)
# -- Helpers --------------------------------------------------------------
is_otel_span <- function(x) {
inherits(x, "otel_span")
}
testthat__is_testing <- function() {
# testthat::is_testing()
identical(Sys.getenv("TESTTHAT"), "true")
}
#' Log a message using the Shiny OpenTelemetry logger
#'
#' @param msg The log message
#' @param ... Additional attributes to add to the log record
#' @param severity The log severity level (default: "info")
#' @param logger The OpenTelemetry logger to use (default: Shiny otel logger)
#' @return Invisibly returns.
#' @noRd
otel_log <- function(
msg,
...,
severity = "info",
logger = shiny_otel_logger()
) {
otel::log(msg, ..., severity = severity, logger = logger)
}

125
R/otel-with.R Normal file
View File

@@ -0,0 +1,125 @@
#' Temporarily set OpenTelemetry (OTel) collection level
#'
#' @description
#' Control Shiny's OTel collection level for particular reactive expression(s).
#'
#' `withOtelCollect()` sets the OpenTelemetry collection level for
#' the duration of evaluating `expr`. `localOtelCollect()` sets the collection
#' level for the remainder of the current function scope.
#'
#' @details
#' Note that `"session"` and `"reactive_update"` levels are not permitted as
#' these are runtime-specific levels that should only be set permanently via
#' `options(shiny.otel.collect = ...)` or the `SHINY_OTEL_COLLECT` environment
#' variable, not temporarily during reactive expression creation.
#'
#' @section Best practice:
#'
#' Best practice is to set the collection level for code that *creates* reactive
#' expressions, not code that *runs* them. For instance:
#'
#' ```r
#' # Disable telemetry for a reactive expression
#' withOtelCollect("none", {
#' my_reactive <- reactive({ ... })
#' })
#'
#' # Disable telemetry for a render function
#' withOtelCollect("none", {
#' output$my_plot <- renderPlot({ ... })
#' })
#'
#' #' # Disable telemetry for an observer
#' withOtelCollect("none", {
#' observe({ ... }))
#' })
#'
#' # Disable telemetry for an entire module
#' withOtelCollect("none", {
#' my_result <- my_module("my_id")
#' })
#' # Use `my_result` as normal here
#' ```
#'
#' NOTE: It's not recommended to pipe existing reactive objects into
#' `withOtelCollect()` since they won't inherit their intended OTel settings,
#' leading to confusion.
#'
#' @param collect Character string specifying the OpenTelemetry collection level.
#' Must be one of the following:
#'
#' * `"none"` - No telemetry data collected
#' * `"reactivity"` - Collect reactive execution spans (includes session and
#' reactive update events)
#' * `"all"` - All available telemetry (currently equivalent to `"reactivity"`)
#' @param expr Expression to evaluate with the specified collection level
#' (for `withOtelCollect()`).
#' @param envir Environment where the collection level should be set
#' (for `localOtelCollect()`). Defaults to the parent frame.
#'
#' @return
#' * `withOtelCollect()` returns the value of `expr`.
#' * `localOtelCollect()` is called for its side effect and returns the previous
#' `collect` value invisibly.
#'
#' @seealso See the `shiny.otel.collect` option within [`shinyOptions`]. Setting
#' this value will globally control OpenTelemetry collection levels.
#'
#' @examples
#' \dontrun{
#' # Temporarily disable telemetry collection
#' withOtelCollect("none", {
#' # Code here won't generate telemetry
#' reactive({ input$x + 1 })
#' })
#'
#' # Collect reactivity telemetry but not other events
#' withOtelCollect("reactivity", {
#' # Reactive execution will be traced
#' observe({ print(input$x) })
#' })
#'
#' # Use local variant in a function
#' my_function <- function() {
#' localOtelCollect("none")
#' # Rest of function executes without telemetry
#' reactive({ input$y * 2 })
#' }
#' }
#'
#' @rdname withOtelCollect
#' @export
withOtelCollect <- function(collect, expr) {
collect <- as_otel_collect_with(collect)
withr::with_options(
list(shiny.otel.collect = collect),
expr
)
}
#' @rdname withOtelCollect
#' @export
localOtelCollect <- function(collect, envir = parent.frame()) {
collect <- as_otel_collect_with(collect)
old <- withr::local_options(
list(shiny.otel.collect = collect),
.local_envir = envir
)
invisible(old)
}
# Helper function to validate collect levels for with/local functions
# Only allows "none", "reactivity", and "all" - not "session" or "reactive_update"
as_otel_collect_with <- function(collect) {
if (!is.character(collect)) {
stop("`collect` must be a character vector.")
}
allowed_levels <- c("none", "reactivity", "all")
collect <- match.arg(collect, allowed_levels, several.ok = FALSE)
return(collect)
}

View File

@@ -4,20 +4,24 @@
# elements have the same priority, they are served according to their order in
# the queue." (http://en.wikipedia.org/wiki/Priority_queue)
PriorityQueue <- setRefClass(
PriorityQueue <- R6Class(
'PriorityQueue',
fields = list(
portable = FALSE,
class = FALSE,
public = list(
# Keys are priorities, values are subqueues (implemented as list)
.itemsByPriority = 'Map',
# Sorted vector (largest first)
.priorities = 'numeric'
),
methods = list(
# Enqueue an item, with the given priority level (must be integer). Higher
.priorities = numeric(0),
initialize = function() {
.itemsByPriority <<- Map$new()
},
# Enqueue an item, with the given priority level (must be integer). Higher
# priority numbers are dequeued earlier than lower.
enqueue = function(item, priority) {
priority <- normalizePriority(priority)
if (!(priority %in% .priorities)) {
.priorities <<- c(.priorities, priority)
.priorities <<- sort(.priorities, decreasing=TRUE)
@@ -30,14 +34,14 @@ PriorityQueue <- setRefClass(
}
return(invisible())
},
# Retrieve a single item by 1) priority number (highest first) and then 2)
# insertion order (first in, first out). If there are no items to be
# Retrieve a single item by 1) priority number (highest first) and then 2)
# insertion order (first in, first out). If there are no items to be
# dequeued, then NULL is returned. If it is necessary to distinguish between
# a NULL value and the empty case, call isEmpty() before dequeue().
dequeue = function() {
if (length(.priorities) == 0)
return(NULL)
maxPriority <- .priorities[[1]]
items <- .itemsByPriority$get(.key(maxPriority))
firstItem <- items[[1]]
@@ -67,17 +71,17 @@ PriorityQueue <- setRefClass(
)
normalizePriority <- function(priority) {
if (is.null(priority))
priority <- 0
# Cast integers to numeric to prevent any inconsistencies
if (is.integer(priority))
priority <- as.numeric(priority)
if (!is.numeric(priority))
stop('priority must be an integer or numeric')
# Check length
if (length(priority) == 0) {
warning('Zero-length priority vector was passed; using 0')
@@ -86,7 +90,7 @@ normalizePriority <- function(priority) {
warning('Priority has length > 1 and only the first element will be used')
priority <- priority[1]
}
# NA == 0
if (is.na(priority))
priority <- 0

322
R/progress.R Normal file
View File

@@ -0,0 +1,322 @@
#' Reporting progress (object-oriented API)
#'
#' Reports progress to the user during long-running operations.
#'
#' This package exposes two distinct programming APIs for working with
#' progress. [withProgress()] and [setProgress()]
#' together provide a simple function-based interface, while the
#' `Progress` reference class provides an object-oriented API.
#'
#' Instantiating a `Progress` object causes a progress panel to be
#' created, and it will be displayed the first time the `set`
#' method is called. Calling `close` will cause the progress panel
#' to be removed.
#'
#' As of version 0.14, the progress indicators use Shiny's new notification API.
#' If you want to use the old styling (for example, you may have used customized
#' CSS), you can use `style="old"` each time you call
#' `Progress$new()`. If you don't want to set the style each time
#' `Progress$new` is called, you can instead call
#' [`shinyOptions(progress.style="old")`][shinyOptions] just once, inside the server
#' function.
#'
#' @param message A single-element character vector; the message to be
#' displayed to the user, or `NULL` to hide the current message (if any).
#' @param detail A single-element character vector; the detail message to be
#' displayed to the user, or `NULL` to hide the current detail message (if
#' any). The detail message will be shown with a de-emphasized appearance
#' relative to `message`.
#'
#' @examples
#' ## Only run examples in interactive R sessions
#' if (interactive()) {
#'
#' ui <- fluidPage(
#' plotOutput("plot")
#' )
#'
#' server <- function(input, output, session) {
#' output$plot <- renderPlot({
#' progress <- Progress$new(session, min=1, max=15)
#' on.exit(progress$close())
#'
#' progress$set(message = 'Calculation in progress',
#' detail = 'This may take a while...')
#'
#' for (i in 1:15) {
#' progress$set(value = i)
#' Sys.sleep(0.5)
#' }
#' plot(cars)
#' })
#' }
#'
#' shinyApp(ui, server)
#' }
#' @seealso [withProgress()]
#' @format NULL
#' @usage NULL
#' @export
Progress <- R6Class(
'Progress',
public = list(
#' @description Creates a new progress panel (but does not display it).
#' @param session The Shiny session object, as provided by `shinyServer` to
#' the server function.
#' @param min The value that represents the starting point of the progress
#' bar. Must be less than `max`.
#' @param max The value that represents the end of the progress bar. Must be
#' greater than `min`.
#' @param style Progress display style. If `"notification"` (the default),
#' the progress indicator will show using Shiny's notification API. If
#' `"old"`, use the same HTML and CSS used in Shiny 0.13.2 and below (this
#' is for backward-compatibility).
initialize = function(session = getDefaultReactiveDomain(),
min = 0, max = 1,
style = getShinyOption("progress.style", default = "notification"))
{
if (is.null(session))
rlang::abort("Can only use Progress$new() inside a Shiny app")
if (is.null(session$progressStack))
rlang::abort("`session` is not a ShinySession object.")
private$session <- session
private$id <- createUniqueId(8)
private$min <- min
private$max <- max
private$value <- NULL
private$style <- match.arg(style, choices = c("notification", "old"))
private$closed <- FALSE
session$sendProgress('open', list(id = private$id, style = private$style))
},
#' @description Updates the progress panel. When called the first time, the
#' progress panel is displayed.
#' @param value Single-element numeric vector; the value at which to set the
#' progress bar, relative to `min` and `max`. `NULL` hides the progress
#' bar, if it is currently visible.
set = function(value = NULL, message = NULL, detail = NULL) {
if (private$closed) {
warning("Attempting to set progress, but progress already closed.")
return()
}
if (is.null(value) || is.na(value))
value <- NULL
if (!is.null(value)) {
private$value <- value
# Normalize value to number between 0 and 1
value <- min(1, max(0, (value - private$min) / (private$max - private$min)))
}
data <- dropNulls(list(
id = private$id,
message = message,
detail = detail,
value = value,
style = private$style
))
private$session$sendProgress('update', data)
},
#' @description Like `set`, this updates the progress panel. The difference
#' is that `inc` increases the progress bar by `amount`, instead of
#' setting it to a specific value.
#' @param amount For the `inc()` method, a numeric value to increment the
#' progress bar.
inc = function(amount = 0.1, message = NULL, detail = NULL) {
if (is.null(private$value))
private$value <- private$min
value <- min(private$value + amount, private$max)
self$set(value, message, detail)
},
#' @description Returns the minimum value.
getMin = function() private$min,
#' @description Returns the maximum value.
getMax = function() private$max,
#' @description Returns the current value.
getValue = function() private$value,
#' @description Removes the progress panel. Future calls to `set` and
#' `close` will be ignored.
close = function() {
if (private$closed) {
warning("Attempting to close progress, but progress already closed.")
return()
}
private$session$sendProgress('close',
list(id = private$id, style = private$style)
)
private$closed <- TRUE
}
),
private = list(
session = 'ShinySession',
id = character(0),
min = numeric(0),
max = numeric(0),
style = character(0),
value = numeric(0),
closed = logical(0)
)
)
#' Reporting progress (functional API)
#'
#' Reports progress to the user during long-running operations.
#'
#' This package exposes two distinct programming APIs for working with progress.
#' Using `withProgress` with `incProgress` or `setProgress`
#' provide a simple function-based interface, while the [Progress()]
#' reference class provides an object-oriented API.
#'
#' Use `withProgress` to wrap the scope of your work; doing so will cause a
#' new progress panel to be created, and it will be displayed the first time
#' `incProgress` or `setProgress` are called. When `withProgress`
#' exits, the corresponding progress panel will be removed.
#'
#' The `incProgress` function increments the status bar by a specified
#' amount, whereas the `setProgress` function sets it to a specific value,
#' and can also set the text displayed.
#'
#' Generally, `withProgress`/`incProgress`/`setProgress` should
#' be sufficient; the exception is if the work to be done is asynchronous (this
#' is not common) or otherwise cannot be encapsulated by a single scope. In that
#' case, you can use the `Progress` reference class.
#'
#' As of version 0.14, the progress indicators use Shiny's new notification API.
#' If you want to use the old styling (for example, you may have used customized
#' CSS), you can use `style="old"` each time you call
#' `withProgress()`. If you don't want to set the style each time
#' `withProgress` is called, you can instead call
#' [`shinyOptions(progress.style="old")`][shinyOptions] just once, inside the server
#' function.
#'
#' @param session The Shiny session object, as provided by `shinyServer` to
#' the server function. The default is to automatically find the session by
#' using the current reactive domain.
#' @param expr The work to be done. This expression should contain calls to
#' [setProgress()] or [incProgress()].
#' @param min The value that represents the starting point of the progress bar.
#' Must be less tham `max`. Default is 0.
#' @param max The value that represents the end of the progress bar. Must be
#' greater than `min`. Default is 1.
#' @param amount For `incProgress`, the amount to increment the status bar.
#' Default is 0.1.
#' @param env The environment in which `expr` should be evaluated.
#' @param quoted Whether `expr` is a quoted expression (this is not
#' common).
#' @param message A single-element character vector; the message to be displayed
#' to the user, or `NULL` to hide the current message (if any).
#' @param detail A single-element character vector; the detail message to be
#' displayed to the user, or `NULL` to hide the current detail message
#' (if any). The detail message will be shown with a de-emphasized appearance
#' relative to `message`.
#' @param style Progress display style. If `"notification"` (the default),
#' the progress indicator will show using Shiny's notification API. If
#' `"old"`, use the same HTML and CSS used in Shiny 0.13.2 and below
#' (this is for backward-compatibility).
#' @param value Single-element numeric vector; the value at which to set the
#' progress bar, relative to `min` and `max`.
#'
#' @return The result of `expr`.
#' @examples
#' ## Only run examples in interactive R sessions
#' if (interactive()) {
#' options(device.ask.default = FALSE)
#'
#' ui <- fluidPage(
#' plotOutput("plot")
#' )
#'
#' server <- function(input, output) {
#' output$plot <- renderPlot({
#' withProgress(message = 'Calculation in progress',
#' detail = 'This may take a while...', value = 0, {
#' for (i in 1:15) {
#' incProgress(1/15)
#' Sys.sleep(0.25)
#' }
#' })
#' plot(cars)
#' })
#' }
#'
#' shinyApp(ui, server)
#' }
#' @seealso [Progress()]
#' @rdname withProgress
#' @export
withProgress <- function(expr, min = 0, max = 1,
value = min + (max - min) * 0.1,
message = NULL, detail = NULL,
style = getShinyOption("progress.style", default = "notification"),
session = getDefaultReactiveDomain(),
env = parent.frame(), quoted = FALSE)
{
if (!quoted)
expr <- substitute(expr)
if (is.null(session$progressStack))
stop("'session' is not a ShinySession object.")
style <- match.arg(style, c("notification", "old"))
p <- Progress$new(session, min = min, max = max, style = style)
session$progressStack$push(p)
on.exit({
session$progressStack$pop()
p$close()
})
p$set(value, message, detail)
eval(expr, env)
}
#' @rdname withProgress
#' @export
setProgress <- function(value = NULL, message = NULL, detail = NULL,
session = getDefaultReactiveDomain()) {
if (is.null(session$progressStack))
stop("'session' is not a ShinySession object.")
if (session$progressStack$size() == 0) {
warning('setProgress was called outside of withProgress; ignoring')
return()
}
session$progressStack$peek()$set(value, message, detail)
invisible()
}
#' @rdname withProgress
#' @export
incProgress <- function(amount = 0.1, message = NULL, detail = NULL,
session = getDefaultReactiveDomain()) {
if (is.null(session$progressStack))
stop("'session' is not a ShinySession object.")
if (session$progressStack$size() == 0) {
warning('incProgress was called outside of withProgress; ignoring')
return()
}
p <- session$progressStack$peek()
p$inc(amount, message, detail)
invisible()
}

286
R/react.R
View File

@@ -1,41 +1,163 @@
Context <- setRefClass(
processId <- local({
# pid is not sufficient to uniquely identify a process, because
# distributed futures span machines which could introduce pid
# collisions.
cached <- NULL
function() {
if (is.null(cached)) {
cached <<- rlang::hash(list(
Sys.info(),
Sys.time()
))
}
# Sys.getpid() cannot be cached because forked children will
# then have the same processId as their parents.
paste(cached, Sys.getpid())
}
})
ctx_otel_info_obj <- function(
isRecordingOtel = FALSE,
otelLabel = "<unknown>",
otelAttrs = list()
) {
structure(
list(
isRecordingOtel = isRecordingOtel,
otelLabel = otelLabel,
otelAttrs = otelAttrs
),
class = "ctx_otel_info"
)
}
with_otel_span_context <- function(otel_info, expr, domain) {
if (!otel_is_tracing_enabled()) {
return(force(expr))
}
isRecordingOtel <- .subset2(otel_info, "isRecordingOtel")
otelLabel <- .subset2(otel_info, "otelLabel")
otelAttrs <- .subset2(otel_info, "otelAttrs")
# Always set the reactive update span as active
# This ensures that any spans created within the reactive context
# are at least children of the reactive update span
maybe_with_otel_span_reactive_update(domain = domain, {
if (isRecordingOtel) {
with_otel_span(
otelLabel,
{
# Works with both sync and async expressions
# Needed for both observer and reactive contexts
hybrid_then(
expr,
on_failure = set_otel_exception_status_and_throw,
# Must upgrade the error object
tee = FALSE
)
},
# expr,
attributes = otelAttrs
)
} else {
force(expr)
}
})
}
#' @include graph.R
Context <- R6Class(
'Context',
fields = list(
id = 'character',
.label = 'character', # For debug purposes
.invalidated = 'logical',
.invalidateCallbacks = 'list',
.flushCallbacks = 'list'
),
methods = list(
initialize = function(label='') {
id <<- .getReactiveEnvironment()$nextId()
.invalidated <<- FALSE
.invalidateCallbacks <<- list()
.flushCallbacks <<- list()
portable = FALSE,
class = FALSE,
public = list(
id = character(0),
.reactId = character(0),
.reactType = "other",
.label = character(0), # For debug purposes
.invalidated = FALSE,
.invalidateCallbacks = list(),
.flushCallbacks = list(),
.domain = NULL,
.pid = NULL,
.weak = NULL,
.otel_info = NULL,
initialize = function(
domain, label='', type='other', prevId='',
reactId = rLog$noReactId,
id = .getReactiveEnvironment()$nextId(), # For dummy context
weak = FALSE,
otel_info = ctx_otel_info_obj()
) {
id <<- id
.label <<- label
.domain <<- domain
.pid <<- processId()
.reactId <<- reactId
.reactType <<- type
.weak <<- weak
rLog$createContext(id, label, type, prevId, domain)
if (!is.null(otel_info)) {
if (IS_SHINY_LOCAL_PKG) {
stopifnot(inherits(otel_info, "ctx_otel_info"))
}
.otel_info <<- otel_info
}
},
run = function(func) {
"Run the provided function under this context."
env <- .getReactiveEnvironment()
env$runWith(.self, func)
# Use `promises::` as it shows up in the stack trace
promises::with_promise_domain(reactivePromiseDomain(), {
withReactiveDomain(.domain, {
with_otel_span_context(.otel_info, domain = .domain, {
captureStackTraces({
env <- .getReactiveEnvironment()
rLog$enter(.reactId, id, .reactType, .domain)
on.exit(rLog$exit(.reactId, id, .reactType, .domain), add = TRUE)
env$runWith(self, func)
})
})
})
})
},
invalidate = function() {
"Invalidate this context. It will immediately call the callbacks
that have been registered with onInvalidate()."
if (!identical(.pid, processId())) {
rlang::abort("Reactive context was created in one process and invalidated from another.")
}
if (.invalidated)
return()
.invalidated <<- TRUE
rLog$invalidateStart(.reactId, id, .reactType, .domain)
on.exit(rLog$invalidateEnd(.reactId, id, .reactType, .domain), add = TRUE)
lapply(.invalidateCallbacks, function(func) {
func()
})
.invalidateCallbacks <<- list()
NULL
},
onInvalidate = function(func) {
"Register a function to be called when this context is invalidated.
If this context is already invalidated, the function is called
immediately."
if (!identical(.pid, processId())) {
rlang::abort("Reactive context was created in one process and accessed from another.")
}
if (.invalidated)
func()
else
@@ -45,7 +167,7 @@ Context <- setRefClass(
addPendingFlush = function(priority) {
"Tell the reactive environment that this context should be flushed the
next time flushReact() called."
.getReactiveEnvironment()$addPendingFlush(.self, priority)
.getReactiveEnvironment()$addPendingFlush(self, priority)
},
onFlush = function(func) {
"Register a function to be called when this context is flushed."
@@ -53,76 +175,97 @@ Context <- setRefClass(
},
executeFlushCallbacks = function() {
"For internal use only."
lapply(.flushCallbacks, function(func) {
withCallingHandlers({
func()
}, warning = function(e) {
# TODO: Callbacks in app
}, error = function(e) {
# TODO: Callbacks in app
})
lapply(.flushCallbacks, function(flushCallback) {
flushCallback()
})
},
isWeak = function() {
.weak
}
)
)
ReactiveEnvironment <- setRefClass(
ReactiveEnvironment <- R6Class(
'ReactiveEnvironment',
fields = list(
.currentContext = 'ANY',
.nextId = 'integer',
portable = FALSE,
class = FALSE,
public = list(
.currentContext = NULL,
.nextId = 0L,
.pendingFlush = 'PriorityQueue',
.inFlush = 'logical'
),
methods = list(
.inFlush = FALSE,
initialize = function() {
.currentContext <<- NULL
.nextId <<- 0L
.pendingFlush <<- PriorityQueue$new()
.inFlush <<- FALSE
},
nextId = function() {
.nextId <<- .nextId + 1L
return(as.character(.nextId))
},
currentContext = function() {
if (is.null(.currentContext))
stop('Operation not allowed without an active reactive context. ',
'(You tried to do something that can only be done from inside a ',
'reactive function.)')
if (is.null(.currentContext)) {
if (isTRUE(getOption('shiny.suppressMissingContextError'))) {
return(getDummyContext())
} else {
rlang::abort(c(
'Operation not allowed without an active reactive context.',
paste0(
'You tried to do something that can only be done from inside a ',
'reactive consumer.'
)
))
}
}
return(.currentContext)
},
runWith = function(ctx, func) {
runWith = function(ctx, contextFunc) {
old.ctx <- .currentContext
.currentContext <<- ctx
on.exit(.currentContext <<- old.ctx)
func()
contextFunc()
},
addPendingFlush = function(ctx, priority) {
.pendingFlush$enqueue(ctx, priority)
},
hasPendingFlush = function() {
return(!.pendingFlush$isEmpty())
},
# Returns TRUE if anything was actually called
flush = function() {
# If nothing to flush, exit early
if (!hasPendingFlush()) return(invisible(FALSE))
# If already in a flush, don't start another one
if (.inFlush) return()
if (.inFlush) return(invisible(FALSE))
.inFlush <<- TRUE
on.exit(.inFlush <<- FALSE)
on.exit({
.inFlush <<- FALSE
rLog$idle(domain = NULL)
})
while (!.pendingFlush$isEmpty()) {
while (hasPendingFlush()) {
ctx <- .pendingFlush$dequeue()
ctx$executeFlushCallbacks()
}
invisible(TRUE)
}
)
)
.reactiveEnvironment <- ReactiveEnvironment$new()
.getReactiveEnvironment <- function() {
.reactiveEnvironment
}
.getReactiveEnvironment <- local({
reactiveEnvironment <- NULL
function() {
if (is.null(reactiveEnvironment))
reactiveEnvironment <<- ReactiveEnvironment$new()
return(reactiveEnvironment)
}
})
# Causes any pending invalidations to run.
# Causes any pending invalidations to run. Returns TRUE if any invalidations
# were pending (i.e. if work was actually done).
flushReact <- function() {
.getReactiveEnvironment()$flush()
return(.getReactiveEnvironment()$flush())
}
# Retrieves the current reactive context, or errors if there is no reactive
@@ -130,3 +273,46 @@ flushReact <- function() {
getCurrentContext <- function() {
.getReactiveEnvironment()$currentContext()
}
hasCurrentContext <- function() {
!is.null(.getReactiveEnvironment()$.currentContext) ||
isTRUE(getOption("shiny.suppressMissingContextError"))
}
getDummyContext <- function() {
Context$new(
getDefaultReactiveDomain(), '[none]', type = 'isolate',
id = "Dummy", reactId = rLog$dummyReactId
)
}
wrapForContext <- function(func, ctx) {
force(func)
force(ctx) # may be NULL (in the case of maskReactiveContext())
function(...) {
.getReactiveEnvironment()$runWith(ctx, function() {
func(...)
})
}
}
reactivePromiseDomain <- function() {
new_promise_domain(
wrapOnFulfilled = function(onFulfilled) {
force(onFulfilled)
# ctx will be NULL if we're in a maskReactiveContext()
ctx <- if (hasCurrentContext()) getCurrentContext() else NULL
wrapForContext(onFulfilled, ctx)
},
wrapOnRejected = function(onRejected) {
force(onRejected)
# ctx will be NULL if we're in a maskReactiveContext()
ctx <- if (hasCurrentContext()) getCurrentContext() else NULL
wrapForContext(onRejected, ctx)
}
)
}

257
R/reactive-domains.R Normal file
View File

@@ -0,0 +1,257 @@
#' @include globals.R
NULL
#
# Over the last few months we've seen a number of cases where it'd be helpful
# for objects that are instantiated within a Shiny app to know what Shiny
# session they are "owned" by. I put "owned" in quotes because there isn't a
# built-in notion of object ownership in Shiny today, any more than there is a
# notion of one object owning another in R.
#
# But it's intuitive to everyone, I think, that the outputs for a session are
# owned by that session, and any logic that is executed as part of the output
# is done on behalf of that session. And it seems like in the vast majority of
# cases, observers that are created inside a shinyServer function (i.e. one per
# session) are also intuitively owned by the session that's starting up.
#
# This notion of ownership is important/helpful for a few scenarios that have
# come up in recent months:
#
# 1. The showcase mode that Jonathan implemented recently highlights
# observers/reactives as they execute. In order for sessions to only receive
# highlights for their own code execution, we need to know which sessions own
# which observers. 2. We've seen a number of apps crash out when observers
# outlive their sessions and then try to do things with their sessions (the
# most common error message was something like "Can't write to a closed
# websocket", but we now silently ignore writes to closed websockets). It'd be
# convenient for the default behavior of observers to be that they don't
# outlive their parent sessions. 3. The reactive log visualizer currently
# visualizes all reactivity in the process; it would be great if by default it
# only visualized the current session. 4. When an observer has an error, it
# would be great to be able to send the error to the session so it can do its
# own handling (such as sending the error info to the client so the user can be
# notified). 5. Shiny Server Pro wants to show the admin how much time is being
# spent servicing each session.
#
# So what are the rules for establishing ownership?
#
# 1. Define the "current domain" as a global variable whose value will own any
# newly created observer (by default). A domain is a reference class or
# environment that contains the functions `onEnded(callback)`, `isEnded()`, and
# `reactlog(logEntry)`.
#
## ------------------------------------------------------------------------
createMockDomain <- function() {
callbacks <- Callbacks$new()
ended <- FALSE
domain <- new.env(parent = emptyenv())
domain$ns <- function(id) id
domain$token <- "mock-domain"
domain$onEnded <- function(callback) {
return(callbacks$register(callback))
}
domain$isEnded <- function() {
ended
}
domain$reactlog <- function(logEntry) NULL
domain$end <- function() {
if (!ended) {
ended <<- TRUE
callbacks$invoke()
}
invisible()
}
domain$incrementBusyCount <- function() NULL
domain$decrementBusyCount <- function() NULL
return(domain)
}
#
# 2. The initial value of "current domain" is null.
#
## ------------------------------------------------------------------------
.globals$domain <- NULL
#
# 3. Objects that can be owned include observers, reactive expressions,
# invalidateLater instances, reactiveTimer instances. Whenever one of these is
# created, by default its owner will be the current domain.
#
## ------------------------------------------------------------------------
#' @name domains
#' @rdname domains
#' @export
getDefaultReactiveDomain <- function() {
.globals$domain
}
#
# 4. While a session is being created and the shinyServer function is executed,
# the current domain is set to the new session. When the shinyServer function
# is done executing, the previous value of the current domain is restored. This
# is made foolproof using a `withReactiveDomain` function.
#
## ------------------------------------------------------------------------
#' @rdname domains
#' @export
withReactiveDomain <- function(domain, expr) {
# Use `promises::` as it shows up in the stack trace
promises::with_promise_domain(
createVarPromiseDomain(.globals, "domain", domain),
expr
)
}
#
# 5. While an observer or reactive expression is executing, the current domain
# is set to the owner of the observer. When the observer completes, the
# previous value of the current domain is restored.
#
# 6. Note that once created, an observer/reactive expression belongs to the
# same domain forever, regardless of how many times it is invalidated and
# re-executed, and regardless of what caused the invalidation to happen.
#
# 7. When a session ends, any observers that it owns are suspended, any
# invalidateLater/reactiveTimers are stopped.
#
## ------------------------------------------------------------------------
#' @rdname domains
#' @export
onReactiveDomainEnded <- function(domain, callback, failIfNull = FALSE) {
if (is.null(domain)) {
if (isTRUE(failIfNull))
stop("onReactiveDomainEnded called with null domain and failIfNull=TRUE")
else
return()
}
domain$onEnded(callback)
}
#
# 8. If an uncaught error occurs while executing an observer, the session gets
# a chance to handle it. I suppose the default behavior would be to send the
# message to the client if possible, and then perhaps end the session (or not,
# I could argue either way).
#
# The basic idea here is inspired by Node.js domains, which you can think of as
# a way to track execution contexts across callback- or listener-oriented
# asynchronous code. They use it to unify error handling code across a graph of
# related objects. Our domains will be to unify both lifetime and error
# handling across a graph of related reactive primitives.
#
# (You could imagine that as a client update is being processed, the session
# associated with that client would become the current domain. IIRC this is how
# showcase mode is implemented today. I don't think this would cover any cases
# not covered by rule 5 above, and the absence of rule 5 would leave cases that
# this rule would not cover.)
#
# Pitfalls/open issues:
#
# 1. Our current approach has the issue of observers staying alive longer than
# they ought to. This proposal introduces the opposite risk: that
# observers/invalidateLater/reactiveTimer instances, having implicitly been
# assigned a parent, are suspended/disposed earlier than they ought to have
# been. I find this especially worrisome for invalidateLater/reactiveTimer,
# which will often be called in a reactive expression, and thus execute under
# unpredictable circumstances. Perhaps those should continue to accept an
# explicit "session=" parameter that the user is warned about if they don't
# provide a value.
#
# 2. Are there situations where it is ambiguous what the right thing to do is,
# and we should warn/error to ask the user to provide a domain explicitly?
#
## ------------------------------------------------------------------------
#' Reactive domains
#'
#' Reactive domains are a mechanism for establishing ownership over reactive
#' primitives (like reactive expressions and observers), even if the set of
#' reactive primitives is dynamically created. This is useful for lifetime
#' management (i.e. destroying observers when the Shiny session that created
#' them ends) and error handling.
#'
#' At any given time, there can be either a single "default" reactive domain
#' object, or none (i.e. the reactive domain object is `NULL`). You can
#' access the current default reactive domain by calling
#' `getDefaultReactiveDomain`.
#'
#' Unless you specify otherwise, newly created observers and reactive
#' expressions will be assigned to the current default domain (if any). You can
#' override this assignment by providing an explicit `domain` argument to
#' [reactive()] or [observe()].
#'
#' For advanced usage, it's possible to override the default domain using
#' `withReactiveDomain`. The `domain` argument will be made the
#' default domain while `expr` is evaluated.
#'
#' Implementers of new reactive primitives can use `onReactiveDomainEnded`
#' as a convenience function for registering callbacks. If the reactive domain
#' is `NULL` and `failIfNull` is `FALSE`, then the callback will
#' never be invoked.
#'
#' @name domains
#' @param domain A valid domain object (for example, a Shiny session), or
#' `NULL`
#' @param expr An expression to evaluate under `domain`
#' @param callback A callback function to be invoked
#' @param failIfNull If `TRUE` then an error is given if the `domain`
#' is `NULL`
NULL
#
# Example 1
# ---
# ```
# obs1 <- observe({
# })
# shinyServer(function(input, output) {
# obs2 <- observe({
# obs3 <- observe({
# })
# })
# })
# # obs1 would have no domain, obs2 and obs3 would be owned by the session
# ```
#
# Example 2
# ---
# ```
# globalValues <- reactiveValues(broadcast="")
# shinyServer(function(input, output) {
# sessionValues <- reactiveValues()
# output$messageOutput <- renderText({
# globalValues$broadcast
# obs1 <- observe({...})
# })
# observe({
# if (input$goButton == 0) return()
# isolate( globalValues$broadcast <- input$messageInput )
# })
# })
# # The observer behind messageOutput would be owned by the session,
# # as would all the many instances of obs1 that were created.
# ```
# ---
#
# Example 3
# ---
# ```
# rexpr1 <- reactive({
# invalidateLater(1000)
# obs1 <- observe({...})
# })
# observeSomething <- function() {
# obs2 <- observe({...})
# })
# shinyServer(function(input, output) {
# obs3 <- observe({
# observeSomething()
# rexpr1()
# })
# })
# # rexpr1, the invalidateLater call, and obs1 would all have no owner;
# # obs2 and obs3 would be owned by the session.
# ```

File diff suppressed because it is too large Load Diff

201
R/reexports.R Normal file
View File

@@ -0,0 +1,201 @@
####
# Generated by `./tools/documentation/updateReexports.R`: do not edit by hand
# Please call `source('tools/documentation/updateReexports.R')` from the root folder to update`
####
# fastmap key_missing.Rd -------------------------------------------------------
#' @importFrom fastmap key_missing
#' @export
fastmap::key_missing
#' @importFrom fastmap is.key_missing
#' @export
fastmap::is.key_missing
# htmltools builder.Rd ---------------------------------------------------------
#' @importFrom htmltools tags
#' @export
htmltools::tags
#' @importFrom htmltools p
#' @export
htmltools::p
#' @importFrom htmltools h1
#' @export
htmltools::h1
#' @importFrom htmltools h2
#' @export
htmltools::h2
#' @importFrom htmltools h3
#' @export
htmltools::h3
#' @importFrom htmltools h4
#' @export
htmltools::h4
#' @importFrom htmltools h5
#' @export
htmltools::h5
#' @importFrom htmltools h6
#' @export
htmltools::h6
#' @importFrom htmltools a
#' @export
htmltools::a
#' @importFrom htmltools br
#' @export
htmltools::br
#' @importFrom htmltools div
#' @export
htmltools::div
#' @importFrom htmltools span
#' @export
htmltools::span
#' @importFrom htmltools pre
#' @export
htmltools::pre
#' @importFrom htmltools code
#' @export
htmltools::code
#' @importFrom htmltools img
#' @export
htmltools::img
#' @importFrom htmltools strong
#' @export
htmltools::strong
#' @importFrom htmltools em
#' @export
htmltools::em
#' @importFrom htmltools hr
#' @export
htmltools::hr
#' @importFrom htmltools tag
#' @export
htmltools::tag
# htmltools tagList.Rd ---------------------------------------------------------
#' @importFrom htmltools tagList
#' @export
htmltools::tagList
# htmltools tagAppendAttributes.Rd ---------------------------------------------
#' @importFrom htmltools tagAppendAttributes
#' @export
htmltools::tagAppendAttributes
#' @importFrom htmltools tagHasAttribute
#' @export
htmltools::tagHasAttribute
#' @importFrom htmltools tagGetAttribute
#' @export
htmltools::tagGetAttribute
# htmltools tagAppendChild.Rd --------------------------------------------------
#' @importFrom htmltools tagAppendChild
#' @export
htmltools::tagAppendChild
#' @importFrom htmltools tagAppendChildren
#' @export
htmltools::tagAppendChildren
#' @importFrom htmltools tagSetChildren
#' @export
htmltools::tagSetChildren
# htmltools HTML.Rd ------------------------------------------------------------
#' @importFrom htmltools HTML
#' @export
htmltools::HTML
# htmltools include.Rd ---------------------------------------------------------
#' @importFrom htmltools includeHTML
#' @export
htmltools::includeHTML
#' @importFrom htmltools includeText
#' @export
htmltools::includeText
#' @importFrom htmltools includeMarkdown
#' @export
htmltools::includeMarkdown
#' @importFrom htmltools includeCSS
#' @export
htmltools::includeCSS
#' @importFrom htmltools includeScript
#' @export
htmltools::includeScript
# htmltools singleton.Rd -------------------------------------------------------
#' @importFrom htmltools singleton
#' @export
htmltools::singleton
#' @importFrom htmltools is.singleton
#' @export
htmltools::is.singleton
# htmltools validateCssUnit.Rd -------------------------------------------------
#' @importFrom htmltools validateCssUnit
#' @export
htmltools::validateCssUnit
# htmltools htmlTemplate.Rd ----------------------------------------------------
#' @importFrom htmltools htmlTemplate
#' @export
htmltools::htmlTemplate
# htmltools suppressDependencies.Rd --------------------------------------------
#' @importFrom htmltools suppressDependencies
#' @export
htmltools::suppressDependencies
# htmltools withTags.Rd --------------------------------------------------------
#' @importFrom htmltools withTags
#' @export
htmltools::withTags

280
R/render-cached-plot.R Normal file
View File

@@ -0,0 +1,280 @@
#' Plot output with cached images
#'
#' Renders a reactive plot, with plot images cached to disk. As of Shiny 1.6.0,
#' this is a shortcut for using [bindCache()] with [renderPlot()].
#'
#' `expr` is an expression that generates a plot, similar to that in
#' `renderPlot`. Unlike with `renderPlot`, this expression does not
#' take reactive dependencies. It is re-executed only when the cache key
#' changes.
#'
#' `cacheKeyExpr` is an expression which, when evaluated, returns an object
#' which will be serialized and hashed using the [rlang::hash()]
#' function to generate a string that will be used as a cache key. This key is
#' used to identify the contents of the plot: if the cache key is the same as a
#' previous time, it assumes that the plot is the same and can be retrieved from
#' the cache.
#'
#' This `cacheKeyExpr` is reactive, and so it will be re-evaluated when any
#' upstream reactives are invalidated. This will also trigger re-execution of
#' the plotting expression, `expr`.
#'
#' The key should consist of "normal" R objects, like vectors and lists. Lists
#' should in turn contain other normal R objects. If the key contains
#' environments, external pointers, or reference objects --- or even if it has
#' such objects attached as attributes --- then it is possible that it will
#' change unpredictably even when you do not expect it to. Additionally, because
#' the entire key is serialized and hashed, if it contains a very large object
#' --- a large data set, for example --- there may be a noticeable performance
#' penalty.
#'
#' If you face these issues with the cache key, you can work around them by
#' extracting out the important parts of the objects, and/or by converting them
#' to normal R objects before returning them. Your expression could even
#' serialize and hash that information in an efficient way and return a string,
#' which will in turn be hashed (very quickly) by the
#' [rlang::hash()] function.
#'
#' Internally, the result from `cacheKeyExpr` is combined with the name of
#' the output (if you assign it to `output$plot1`, it will be combined
#' with `"plot1"`) to form the actual key that is used. As a result, even
#' if there are multiple plots that have the same `cacheKeyExpr`, they
#' will not have cache key collisions.
#'
#' @section Interactive plots:
#'
#' `renderCachedPlot` can be used to create interactive plots. See
#' [plotOutput()] for more information and examples.
#'
#'
#' @inheritParams renderPlot
#' @inheritParams bindCache
#' @param cacheKeyExpr An expression that returns a cache key. This key should
#' be a unique identifier for a plot: the assumption is that if the cache key
#' is the same, then the plot will be the same.
#' @param sizePolicy A function that takes two arguments, `width` and
#' `height`, and returns a list with `width` and `height`. The
#' purpose is to round the actual pixel dimensions from the browser to some
#' other dimensions, so that this will not generate and cache images of every
#' possible pixel dimension. See [sizeGrowthRatio()] for more
#' information on the default sizing policy.
#' @param res The resolution of the PNG, in pixels per inch.
#' @param width,height not used. They are specified via the argument
#' `sizePolicy`.
#'
#' @seealso See [renderPlot()] for the regular, non-cached version of this
#' function. It can be used with [bindCache()] to get the same effect as
#' `renderCachedPlot()`. For more about configuring caches, see
#' [cachem::cache_mem()] and [cachem::cache_disk()].
#'
#'
#' @examples
#' ## Only run examples in interactive R sessions
#' if (interactive()) {
#'
#' # A basic example that uses the default app-scoped memory cache.
#' # The cache will be shared among all simultaneous users of the application.
#' shinyApp(
#' fluidPage(
#' sidebarLayout(
#' sidebarPanel(
#' sliderInput("n", "Number of points", 4, 32, value = 8, step = 4)
#' ),
#' mainPanel(plotOutput("plot"))
#' )
#' ),
#' function(input, output, session) {
#' output$plot <- renderCachedPlot({
#' Sys.sleep(2) # Add an artificial delay
#' seqn <- seq_len(input$n)
#' plot(mtcars$wt[seqn], mtcars$mpg[seqn],
#' xlim = range(mtcars$wt), ylim = range(mtcars$mpg))
#' },
#' cacheKeyExpr = { list(input$n) }
#' )
#' }
#' )
#'
#'
#'
#' # An example uses a data object shared across sessions. mydata() is part of
#' # the cache key, so when its value changes, plots that were previously
#' # stored in the cache will no longer be used (unless mydata() changes back
#' # to its previous value).
#' mydata <- reactiveVal(data.frame(x = rnorm(400), y = rnorm(400)))
#'
#' ui <- fluidPage(
#' sidebarLayout(
#' sidebarPanel(
#' sliderInput("n", "Number of points", 50, 400, 100, step = 50),
#' actionButton("newdata", "New data")
#' ),
#' mainPanel(
#' plotOutput("plot")
#' )
#' )
#' )
#'
#' server <- function(input, output, session) {
#' observeEvent(input$newdata, {
#' mydata(data.frame(x = rnorm(400), y = rnorm(400)))
#' })
#'
#' output$plot <- renderCachedPlot(
#' {
#' Sys.sleep(2)
#' d <- mydata()
#' seqn <- seq_len(input$n)
#' plot(d$x[seqn], d$y[seqn], xlim = range(d$x), ylim = range(d$y))
#' },
#' cacheKeyExpr = { list(input$n, mydata()) },
#' )
#' }
#'
#' shinyApp(ui, server)
#'
#'
#' # A basic application with two plots, where each plot in each session has
#' # a separate cache.
#' shinyApp(
#' fluidPage(
#' sidebarLayout(
#' sidebarPanel(
#' sliderInput("n", "Number of points", 4, 32, value = 8, step = 4)
#' ),
#' mainPanel(
#' plotOutput("plot1"),
#' plotOutput("plot2")
#' )
#' )
#' ),
#' function(input, output, session) {
#' output$plot1 <- renderCachedPlot({
#' Sys.sleep(2) # Add an artificial delay
#' seqn <- seq_len(input$n)
#' plot(mtcars$wt[seqn], mtcars$mpg[seqn],
#' xlim = range(mtcars$wt), ylim = range(mtcars$mpg))
#' },
#' cacheKeyExpr = { list(input$n) },
#' cache = cachem::cache_mem()
#' )
#' output$plot2 <- renderCachedPlot({
#' Sys.sleep(2) # Add an artificial delay
#' seqn <- seq_len(input$n)
#' plot(mtcars$wt[seqn], mtcars$mpg[seqn],
#' xlim = range(mtcars$wt), ylim = range(mtcars$mpg))
#' },
#' cacheKeyExpr = { list(input$n) },
#' cache = cachem::cache_mem()
#' )
#' }
#' )
#'
#' }
#'
#' \dontrun{
#' # At the top of app.R, this set the application-scoped cache to be a memory
#' # cache that is 20 MB in size, and where cached objects expire after one
#' # hour.
#' shinyOptions(cache = cachem::cache_mem(max_size = 20e6, max_age = 3600))
#'
#' # At the top of app.R, this set the application-scoped cache to be a disk
#' # cache that can be shared among multiple concurrent R processes, and is
#' # deleted when the system reboots.
#' shinyOptions(cache = cachem::cache_disk(file.path(dirname(tempdir()), "myapp-cache")))
#'
#' # At the top of app.R, this set the application-scoped cache to be a disk
#' # cache that can be shared among multiple concurrent R processes, and
#' # persists on disk across reboots.
#' shinyOptions(cache = cachem::cache_disk("./myapp-cache"))
#'
#' # At the top of the server function, this set the session-scoped cache to be
#' # a memory cache that is 5 MB in size.
#' server <- function(input, output, session) {
#' shinyOptions(cache = cachem::cache_mem(max_size = 5e6))
#'
#' output$plot <- renderCachedPlot(
#' ...,
#' cache = "session"
#' )
#' }
#'
#' }
#' @export
renderCachedPlot <- function(expr,
cacheKeyExpr,
sizePolicy = sizeGrowthRatio(width = 400, height = 400, growthRate = 1.2),
res = 72,
cache = "app",
...,
alt = "Plot object",
outputArgs = list(),
width = NULL,
height = NULL
) {
expr <- substitute(expr)
if (!is_quosure(expr)) {
expr <- new_quosure(expr, env = parent.frame())
}
cacheKeyExpr <- substitute(cacheKeyExpr)
if (!is_quosure(cacheKeyExpr)) {
cacheKeyExpr <- new_quosure(cacheKeyExpr, env = parent.frame())
}
if (!is.null(width) || !is.null(height)) {
warning("Unused argument(s) 'width' and/or 'height'. ",
"'sizePolicy' is used instead.")
}
inject(
bindCache(
renderPlot(!!expr, res = res, alt = alt, outputArgs = outputArgs, ...),
!!cacheKeyExpr,
sizePolicy = sizePolicy,
cache = cache
)
)
}
#' Create a sizing function that grows at a given ratio
#'
#' Returns a function which takes a two-element vector representing an input
#' width and height, and returns a two-element vector of width and height. The
#' possible widths are the base width times the growthRate to any integer power.
#' For example, with a base width of 500 and growth rate of 1.25, the possible
#' widths include 320, 400, 500, 625, 782, and so on, both smaller and larger.
#' Sizes are rounded up to the next pixel. Heights are computed the same way as
#' widths.
#'
#' @param width,height Base width and height.
#' @param growthRate Growth rate multiplier.
#'
#' @seealso This is to be used with [renderCachedPlot()].
#'
#' @examples
#' f <- sizeGrowthRatio(500, 500, 1.25)
#' f(c(400, 400))
#' f(c(500, 500))
#' f(c(530, 550))
#' f(c(625, 700))
#'
#' @export
sizeGrowthRatio <- function(width = 400, height = 400, growthRate = 1.2) {
round_dim_up <- function(x, base, rate) {
power <- ceiling(log(x / base, rate))
ceiling(base * rate^power)
}
function(dims) {
if (length(dims) != 2) {
stop("dims must be a vector with two numbers, for width and height.")
}
c(
round_dim_up(dims[1], width, growthRate),
round_dim_up(dims[2], height, growthRate)
)
}
}

1148
R/render-plot.R Normal file

File diff suppressed because it is too large Load Diff

246
R/render-table.R Normal file
View File

@@ -0,0 +1,246 @@
#' Table Output
#'
#' @description
#' The `tableOuptut()`/`renderTable()` pair creates a reactive table that is
#' suitable for display small matrices and data frames. The columns are
#' formatted with [xtable::xtable()].
#'
#' See [renderDataTable()] for data frames that are too big to fit on a single
#' page.
#'
#' @param expr An expression that returns an R object that can be used with
#' [xtable::xtable()].
#' @param striped,hover,bordered Logicals: if `TRUE`, apply the
#' corresponding Bootstrap table format to the output table.
#' @param spacing The spacing between the rows of the table (`xs`
#' stands for "extra small", `s` for "small", `m` for "medium"
#' and `l` for "large").
#' @param width Table width. Must be a valid CSS unit (like "100%", "400px",
#' "auto") or a number, which will be coerced to a string and
#' have "px" appended.
#' @param align A string that specifies the column alignment. If equal to
#' `'l'`, `'c'` or `'r'`, then all columns will be,
#' respectively, left-, center- or right-aligned. Otherwise, `align`
#' must have the same number of characters as the resulting table (if
#' `rownames = TRUE`, this will be equal to `ncol()+1`), with
#' the *i*-th character specifying the alignment for the
#' *i*-th column (besides `'l'`, `'c'` and
#' `'r'`, `'?'` is also permitted - `'?'` is a placeholder
#' for that particular column, indicating that it should keep its default
#' alignment). If `NULL`, then all numeric/integer columns (including
#' the row names, if they are numbers) will be right-aligned and
#' everything else will be left-aligned (`align = '?'` produces the
#' same result).
#' @param rownames,colnames Logicals: include rownames? include colnames
#' (column headers)?
#' @param digits An integer specifying the number of decimal places for
#' the numeric columns (this will not apply to columns with an integer
#' class). If `digits` is set to a negative value, then the numeric
#' columns will be displayed in scientific format with a precision of
#' `abs(digits)` digits.
#' @param na The string to use in the table cells whose values are missing
#' (i.e. they either evaluate to `NA` or `NaN`).
#' @param ... Arguments to be passed through to [xtable::xtable()]
#' and [xtable::print.xtable()].
#' @inheritParams renderUI
#' @param outputArgs A list of arguments to be passed through to the
#' implicit call to [tableOutput()] when `renderTable` is
#' used in an interactive R Markdown document.
#' @export
#' @examples
#' ## Only run this example in interactive R sessions
#' if (interactive()) {
#' # table example
#' shinyApp(
#' ui = fluidPage(
#' fluidRow(
#' column(12,
#' tableOutput('table')
#' )
#' )
#' ),
#' server = function(input, output) {
#' output$table <- renderTable(iris)
#' }
#' )
#' }
renderTable <- function(expr, striped = FALSE, hover = FALSE,
bordered = FALSE, spacing = c("s", "xs", "m", "l"),
width = "auto", align = NULL,
rownames = FALSE, colnames = TRUE,
digits = NULL, na = "NA", ...,
env = parent.frame(), quoted = FALSE,
outputArgs=list())
{
func <- installExprFunction(expr, "func", env, quoted, label = "renderTable")
if (!is.function(spacing)) spacing <- match.arg(spacing)
# A small helper function to create a wrapper for an argument that was
# passed to renderTable()
createWrapper <- function(arg) {
if (is.function(arg)) wrapper <- arg
else wrapper <- function() arg
return(wrapper)
}
# Create wrappers for most arguments so that functions can also be passed
# in, rather than only literals (useful for shiny apps)
stripedWrapper <- createWrapper(striped)
hoverWrapper <- createWrapper(hover)
borderedWrapper <- createWrapper(bordered)
spacingWrapper <- createWrapper(spacing)
widthWrapper <- createWrapper(width)
alignWrapper <- createWrapper(align)
rownamesWrapper <- createWrapper(rownames)
colnamesWrapper <- createWrapper(colnames)
digitsWrapper <- createWrapper(digits)
naWrapper <- createWrapper(na)
dots <- list(...) ## used later (but defined here because of scoping)
createRenderFunction(
func,
function(data, session, name, ...) {
striped <- stripedWrapper()
hover <- hoverWrapper()
bordered <- borderedWrapper()
format <- c(striped = striped, hover = hover, bordered = bordered)
spacing <- spacingWrapper()
width <- widthWrapper()
align <- alignWrapper()
rownames <- rownamesWrapper()
colnames <- colnamesWrapper()
digits <- digitsWrapper()
na <- naWrapper()
spacing_choices <- c("s", "xs", "m", "l")
if (!(spacing %in% spacing_choices)) {
stop(paste("`spacing` must be one of",
paste0("'", spacing_choices, "'", collapse=", ")))
}
# For css styling
classNames <- paste0("table shiny-table",
paste0(" table-", names(format)[format], collapse = "" ),
paste0(" spacing-", spacing))
data <- as.data.frame(data)
# Return NULL if no data is provided
if (is.null(data) ||
(is.data.frame(data) && nrow(data) == 0 && ncol(data) == 0))
return(NULL)
# Separate the ... args to pass to xtable() vs print.xtable()
xtable_argnames <- setdiff(names(formals(xtable)), c("x", "..."))
xtable_args <- dots[intersect(names(dots), xtable_argnames)]
non_xtable_args <- dots[setdiff(names(dots), xtable_argnames)]
# By default, numbers are right-aligned and everything else is left-aligned.
defaultAlignment <- function(col) {
if (is.numeric(col)) "r" else "l"
}
# Figure out column alignment
## Case 1: default alignment
if (is.null(align) || align == "?") {
names <- defaultAlignment(attr(data, "row.names"))
cols <- paste(vapply(data, defaultAlignment, character(1)), collapse = "")
cols <- paste0(names, cols)
} else {
## Case 2: user-specified alignment
num_cols <- if (rownames) nchar(align) else nchar(align)+1
valid <- !grepl("[^lcr\\?]", align)
if (num_cols == ncol(data)+1 && valid) {
cols <- if (rownames) align else paste0("r", align)
defaults <- grep("\\?", strsplit(cols,"")[[1]])
if (length(defaults) != 0) {
vals <- vapply(data[,defaults-1], defaultAlignment, character(1))
for (i in seq_len(length(defaults))) {
substr(cols, defaults[i], defaults[i]) <- vals[i]
}
}
} else if (nchar(align) == 1 && valid) {
cols <- paste0(rep(align, ncol(data)+1), collapse="")
} else {
stop("`align` must contain only the characters `l`, `c`, `r` and/or `?` and",
"have length either equal to 1 or to the total number of columns")
}
}
# Call xtable with its (updated) args
xtable_args <- c(xtable_args, align = cols, digits = digits)
xtable_res <- do.call(xtable, c(list(data), xtable_args))
# Set up print args
print_args <- list(
x = xtable_res,
type = 'html',
include.rownames = {
if ("include.rownames" %in% names(dots)) dots$include.rownames
else rownames
},
include.colnames = {
if ("include.colnames" %in% names(dots)) dots$include.colnames
else colnames
},
NA.string = {
if ("NA.string" %in% names(dots)) dots$NA.string
else na
},
html.table.attributes =
paste0({
if ("html.table.attributes" %in% names(dots)) dots$html.table.attributes
else ""
}, " ",
"class = '", htmlEscape(classNames, TRUE), "' ",
"style = 'width:", validateCssUnit(width), ";'"),
comment = {
if ("comment" %in% names(dots)) dots$comment
else FALSE
}
)
print_args <- c(print_args, non_xtable_args)
print_args <- print_args[unique(names(print_args))]
# Capture the raw html table returned by print.xtable(), and store it in
# a variable for further processing
tab <- paste(utils::capture.output(do.call(print, print_args)),collapse = "\n")
# Add extra class to cells with NA value, to be able to style them separately
tab <- gsub(paste(">", na, "<"), paste(" class='NA'>", na, "<"), tab)
# All further processing concerns the table headers, so we don't need to run
# any of this if colnames=FALSE
if (colnames) {
# Make sure that the final html table has a proper header (not included
# in the print.xtable() default)
tab <- sub("<tr>", "<thead> <tr>", tab)
tab <- sub("</tr>", "</tr> </thead> <tbody>", tab)
tab <- sub("</table>$", "</tbody> </table>", tab)
# Update the `cols` string (which stores the alignment of each column) so
# that it only includes the alignment for the table variables (and not
# for the row.names)
cols <- if (rownames) cols else substr(cols, 2, nchar(cols))
# Create a vector whose i-th entry corresponds to the i-th table variable
# alignment (substituting "l" by "left", "c" by "center" and "r" by "right")
cols <- strsplit(cols, "")[[1]]
cols[cols == "l"] <- "left"
cols[cols == "r"] <- "right"
cols[cols == "c"] <- "center"
# Align each header accordingly (this guarantees that each header and its
# corresponding column have the same alignment)
for (i in seq_len(length(cols))) {
tab <- sub("<th>", paste0("<th style='text-align: ", cols[i], ";'>"), tab)
}
}
return(tab)
},
tableOutput, outputArgs
)
}

View File

@@ -1,124 +1,35 @@
#' Run a Shiny application from https://gist.github.com
#'
#' Download and launch a Shiny application that is hosted on GitHub as a gist.
#'
#' @param gist The identifier of the gist. For example, if the gist is
#' https://gist.github.com/jcheng5/3239667, then \code{3239667},
#' \code{'3239667'}, and \code{'https://gist.github.com/jcheng5/3239667'}
#' are all valid values.
#' @param port The TCP port that the application should listen on. Defaults to
#' port 8100.
#' @param launch.browser If true, the system's default web browser will be
#' launched automatically after the app is started. Defaults to true in
#' interactive sessions only.
#'
#' @examples
#' \dontrun{
#' runGist(3239667)
#' runGist("https://gist.github.com/jcheng5/3239667")
#'
#' # Old URL format without username
#' runGist("https://gist.github.com/3239667")
#' }
#'
#' @export
runGist <- function(gist,
port=8100L,
launch.browser=getOption('shiny.launch.browser',
interactive())) {
gistUrl <- if (is.numeric(gist) || grepl('^[0-9a-f]+$', gist)) {
sprintf('https://gist.github.com/%s/download', gist)
} else if(grepl('^https://gist.github.com/([^/]+/)?([0-9a-f]+)$', gist)) {
paste(gist, '/download', sep='')
} else {
stop('Unrecognized gist identifier format')
}
runUrl(gistUrl, filetype=".tar.gz", subdir=NULL, port=port,
launch.browser=launch.browser)
}
#' Run a Shiny application from a GitHub repository
#'
#' Download and launch a Shiny application that is hosted in a GitHub repository.
#'
#' @param repo Name of the repository
#' @param username GitHub username
#' @param ref Desired git reference. Could be a commit, tag, or branch
#' name. Defaults to \code{"master"}.
#' @param subdir A subdirectory in the repository that contains the app. By
#' default, this function will run an app from the top level of the repo, but
#' you can use a path such as `\code{"inst/shinyapp"}.
#' @param port The TCP port that the application should listen on. Defaults to
#' port 8100.
#' @param launch.browser If true, the system's default web browser will be
#' launched automatically after the app is started. Defaults to true in
#' interactive sessions only.
#'
#' @examples
#' \dontrun{
#' runGitHub("shiny_example", "rstudio")
#'
#' # Can run an app from a subdirectory in the repo
#' runGitHub("shiny_example", "rstudio", subdir = "inst/shinyapp/")
#' }
#'
#' @export
runGitHub <- function(repo, username = getOption("github.user"),
ref = "master", subdir = NULL, port = 8100,
launch.browser = getOption('shiny.launch.browser', interactive())) {
if (is.null(ref)) {
stop("Must specify either a ref. ")
}
message("Downloading github repo(s) ",
paste(repo, ref, sep = "/", collapse = ", "),
" from ",
paste(username, collapse = ", "))
name <- paste(username, "-", repo, sep = "")
url <- paste("https://github.com/", username, "/", repo, "/archive/",
ref, ".tar.gz", sep = "")
runUrl(url, subdir=subdir, port=port, launch.browser=launch.browser)
}
#' Run a Shiny application from a URL
#'
#' Download and launch a Shiny application that is hosted at a downloadable
#' URL. The Shiny application must be saved in a .zip, .tar, or .tar.gz file.
#' The Shiny application files must be contained in a subdirectory in the
#' archive. For example, the files might be \code{myapp/server.r} and
#' \code{myapp/ui.r}.
#'
#' `runUrl()` downloads and launches a Shiny application that is hosted at
#' a downloadable URL. The Shiny application must be saved in a .zip, .tar, or
#' .tar.gz file. The Shiny application files must be contained in the root
#' directory or a subdirectory in the archive. For example, the files might be
#' `myapp/server.r` and `myapp/ui.r`. The functions `runGitHub()`
#' and `runGist()` are based on `runUrl()`, using URL's from GitHub
#' (<https://github.com>) and GitHub gists (<https://gist.github.com>),
#' respectively.
#' @param url URL of the application.
#' @param filetype The file type (\code{".zip"}, \code{".tar"}, or
#' \code{".tar.gz"}. Defaults to the file extension taken from the url.
#' @param filetype The file type (`".zip"`, `".tar"`, or
#' `".tar.gz"`. Defaults to the file extension taken from the url.
#' @param subdir A subdirectory in the repository that contains the app. By
#' default, this function will run an app from the top level of the repo, but
#' you can use a path such as `\code{"inst/shinyapp"}.
#' @param port The TCP port that the application should listen on. Defaults to
#' port 8100.
#' @param launch.browser If true, the system's default web browser will be
#' launched automatically after the app is started. Defaults to true in
#' interactive sessions only.
#'
#' @examples
#' \dontrun{
#' runUrl('https://github.com/rstudio/shiny_example/archive/master.tar.gz')
#'
#' # Can run an app from a subdirectory in the archive
#' runUrl("https://github.com/rstudio/shiny_example/archive/master.zip",
#' subdir = "inst/shinyapp/")
#' }
#'
#' you can use a path such as `"inst/shinyapp"`.
#' @param destdir Directory to store the downloaded application files. If `NULL`
#' (the default), the application files will be stored in a temporary directory
#' and removed when the app exits
#' @param ... Other arguments to be passed to [runApp()], such as
#' `port` and `launch.browser`.
#' @export
runUrl <- function(url, filetype = NULL, subdir = NULL, port = 8100,
launch.browser = getOption('shiny.launch.browser', interactive())) {
#' @examples
#' ## Only run this example in interactive R sessions
#' if (interactive()) {
#' runUrl('https://github.com/rstudio/shiny_example/archive/main.tar.gz')
#'
#' # Can run an app from a subdirectory in the archive
#' runUrl("https://github.com/rstudio/shiny_example/archive/main.zip",
#' subdir = "inst/shinyapp/")
#' }
runUrl <- function(url, filetype = NULL, subdir = NULL, destdir = NULL, ...) {
if (!is.null(subdir) && ".." %in% strsplit(subdir, '/')[[1]])
stop("'..' not allowed in subdir")
@@ -136,7 +47,15 @@ runUrl <- function(url, filetype = NULL, subdir = NULL, port = 8100,
stop("Unknown file extension.")
message("Downloading ", url)
filePath <- tempfile('shinyapp', fileext=fileext)
if (is.null(destdir)) {
filePath <- tempfile('shinyapp', fileext = fileext)
fileDir <- tempfile('shinyapp')
} else {
fileDir <- destdir
filePath <- paste(destdir, fileext)
}
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 +67,84 @@ runUrl <- function(url, filetype = NULL, subdir = NULL, port = 8100,
# 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(utils::unzip(filePath, list=TRUE)$Name)[1]
utils::unzip(filePath, exdir = fileDir)
}
appdir <- file.path(dirname(filePath), dirname)
on.exit(unlink(appdir, recursive = TRUE), add = TRUE)
if(is.null(destdir)){
on.exit(unlink(fileDir, recursive = TRUE), add = TRUE)
}
appsubdir <- ifelse(is.null(subdir), appdir, file.path(appdir, subdir))
runApp(appsubdir, port=port, launch.browser=launch.browser)
appdir <- file.path(fileDir, first)
if (!utils::file_test('-d', appdir)) appdir <- dirname(appdir)
if (!is.null(subdir)) appdir <- file.path(appdir, subdir)
runApp(appdir, ...)
}
#' @rdname runUrl
#' @param gist The identifier of the gist. For example, if the gist is
#' https://gist.github.com/jcheng5/3239667, then `3239667`,
#' `'3239667'`, and `'https://gist.github.com/jcheng5/3239667'` are
#' all valid values.
#' @export
#' @examples
#' ## Only run this example in interactive R sessions
#' if (interactive()) {
#' runGist(3239667)
#' runGist("https://gist.github.com/jcheng5/3239667")
#'
#' # Old URL format without username
#' runGist("https://gist.github.com/3239667")
#' }
#'
runGist <- function(gist, destdir = NULL, ...) {
gistUrl <- if (is.numeric(gist) || grepl('^[0-9a-f]+$', gist)) {
sprintf('https://gist.github.com/%s/download', gist)
} else if(grepl('^https://gist.github.com/([^/]+/)?([0-9a-f]+)$', gist)) {
paste(gist, '/download', sep='')
} else {
stop('Unrecognized gist identifier format')
}
runUrl(gistUrl, filetype = ".zip", destdir = destdir, ...)
}
#' @rdname runUrl
#' @param repo Name of the repository.
#' @param username GitHub username. If `repo` is of the form
#' `"username/repo"`, `username` will be taken from `repo`.
#' @param ref Desired git reference. Could be a commit, tag, or branch name.
#' Defaults to `"HEAD"`, which means the default branch on GitHub, typically
#' `"main"` or `"master"`.
#' @export
#' @examples
#' ## Only run this example in interactive R sessions
#' if (interactive()) {
#' runGitHub("shiny_example", "rstudio")
#' # or runGitHub("rstudio/shiny_example")
#'
#' # Can run an app from a subdirectory in the repo
#' runGitHub("shiny_example", "rstudio", subdir = "inst/shinyapp/")
#' }
runGitHub <- function(repo, username = getOption("github.user"),
ref = "HEAD", subdir = NULL, destdir = NULL, ...) {
if (grepl('/', repo)) {
res <- strsplit(repo, '/')[[1]]
if (length(res) != 2) stop("'repo' must be of the form 'username/repo'")
username <- res[1]
repo <- res[2]
}
url <- paste("https://github.com/", username, "/", repo, "/archive/",
ref, ".tar.gz", sep = "")
runUrl(url, subdir = subdir, destdir = destdir, ...)
}

601
R/runapp.R Normal file
View File

@@ -0,0 +1,601 @@
#' Run Shiny Application
#'
#' Runs a Shiny application. This function normally does not return; interrupt R
#' to stop the application (usually by pressing Ctrl+C or Esc).
#'
#' The host parameter was introduced in Shiny 0.9.0. Its default value of
#' `"127.0.0.1"` means that, contrary to previous versions of Shiny, only
#' the current machine can access locally hosted Shiny apps. To allow other
#' clients to connect, use the value `"0.0.0.0"` instead (which was the
#' value that was hard-coded into Shiny in 0.8.0 and earlier).
#'
#' @param appDir The application to run. Should be one of the following:
#' \itemize{
#' \item A directory containing `server.R`, plus, either `ui.R` or
#' a `www` directory that contains the file `index.html`.
#' \item A directory containing `app.R`.
#' \item An `.R` file containing a Shiny application, ending with an
#' expression that produces a Shiny app object.
#' \item A list with `ui` and `server` components.
#' \item A Shiny app object created by [shinyApp()].
#' }
#' @param port The TCP port that the application should listen on. If the
#' `port` is not specified, and the `shiny.port` option is set (with
#' `options(shiny.port = XX)`), then that port will be used. Otherwise,
#' use a random port between 3000:8000, excluding ports that are blocked
#' by Google Chrome for being considered unsafe: 3659, 4045, 5060,
#' 5061, 6000, 6566, 6665:6669 and 6697. Up to twenty random
#' ports will be tried.
#' @param launch.browser If true, the system's default web browser will be
#' launched automatically after the app is started. Defaults to true in
#' interactive sessions only. The value of this parameter can also be a
#' function to call with the application's URL.
#' @param host The IPv4 address that the application should listen on. Defaults
#' to the `shiny.host` option, if set, or `"127.0.0.1"` if not. See
#' Details.
#' @param workerId Can generally be ignored. Exists to help some editions of
#' Shiny Server Pro route requests to the correct process.
#' @param quiet Should Shiny status messages be shown? Defaults to FALSE.
#' @param display.mode The mode in which to display the application. If set to
#' the value `"showcase"`, shows application code and metadata from a
#' `DESCRIPTION` file in the application directory alongside the
#' application. If set to `"normal"`, displays the application normally.
#' Defaults to `"auto"`, which displays the application in the mode given
#' in its `DESCRIPTION` file, if any.
#' @param test.mode Should the application be launched in test mode? This is
#' only used for recording or running automated tests. Defaults to the
#' `shiny.testmode` option, or FALSE if the option is not set.
#'
#' @examples
#' \dontrun{
#' # Start app in the current working directory
#' runApp()
#'
#' # Start app in a subdirectory called myapp
#' runApp("myapp")
#' }
#'
#' ## Only run this example in interactive R sessions
#' if (interactive()) {
#' options(device.ask.default = FALSE)
#'
#' # Apps can be run without a server.r and ui.r file
#' runApp(list(
#' ui = bootstrapPage(
#' numericInput('n', 'Number of obs', 100),
#' plotOutput('plot')
#' ),
#' server = function(input, output) {
#' output$plot <- renderPlot({ hist(runif(input$n)) })
#' }
#' ))
#'
#'
#' # Running a Shiny app object
#' app <- shinyApp(
#' ui = bootstrapPage(
#' numericInput('n', 'Number of obs', 100),
#' plotOutput('plot')
#' ),
#' server = function(input, output) {
#' output$plot <- renderPlot({ hist(runif(input$n)) })
#' }
#' )
#' runApp(app)
#' }
#' @export
runApp <- function(
appDir=getwd(),
port=getOption('shiny.port'),
launch.browser = getOption('shiny.launch.browser', interactive()),
host=getOption('shiny.host', '127.0.0.1'),
workerId="", quiet=FALSE,
display.mode=c("auto", "normal", "showcase"),
test.mode=getOption('shiny.testmode', FALSE)
) {
# * Wrap **all** execution of the app inside the otel promise domain
# * While this could be done at a lower level, it allows for _anything_ within
# shiny's control to allow for the opportunity to have otel active spans be
# reactivated upon promise domain restoration
promises::local_otel_promise_domain()
on.exit({
handlerManager$clear()
}, add = TRUE)
if (isRunning()) {
stop("Can't call `runApp()` from within `runApp()`. If your ",
"application code contains `runApp()`, please remove it.")
}
# Make warnings print immediately
# Set pool.scheduler to support pool package
ops <- options(
# Raise warn level to 1, but don't lower it
warn = max(1, getOption("warn", default = 1)),
pool.scheduler = scheduleTask
)
on.exit(options(ops), add = TRUE)
# ============================================================================
# Global onStart/onStop callbacks
# ============================================================================
# Invoke user-defined onStop callbacks, before the application's internal
# onStop callbacks.
on.exit({
.globals$onStopCallbacks$invoke()
.globals$onStopCallbacks <- Callbacks$new()
}, add = TRUE)
require(shiny)
# ============================================================================
# Convert to Shiny app object
# ============================================================================
appParts <- as.shiny.appobj(appDir)
# ============================================================================
# Initialize app state object
# ============================================================================
# This is so calls to getCurrentAppState() can be used to find (A) whether an
# app is running and (B), get options and data associated with the app.
initCurrentAppState(appParts)
on.exit(clearCurrentAppState(), add = TRUE)
# Any shinyOptions set after this point will apply to the current app only
# (and will not persist after the app stops).
# ============================================================================
# shinyOptions
# ============================================================================
# A unique identifier associated with this run of this application. It is
# shared across sessions.
shinyOptions(appToken = createUniqueId(8))
# Set up default cache for app.
if (is.null(getShinyOption("cache", default = NULL))) {
shinyOptions(cache = cachem::cache_mem(max_size = 200 * 1024^2))
}
# Extract appOptions (which is a list) and store them as shinyOptions, for
# this app. (This is the only place we have to store settings that are
# accessible both the UI and server portion of the app.)
applyCapturedAppOptions(appParts$appOptions)
# ============================================================================
# runApp options set via shinyApp(options = list(...))
# ============================================================================
# The lines below set some of the app's running options, which
# can be:
# - left unspecified (in which case the arguments' default
# values from `runApp` kick in);
# - passed through `shinyApp`
# - passed through `runApp` (this function)
# - passed through both `shinyApp` and `runApp` (the latter
# takes precedence)
#
# Matrix of possibilities:
# | IN shinyApp | IN runApp | result | check |
# |-------------|-----------|--------------|----------------------------------------------------------------------------------------------------------------------------------------|
# | no | no | use defaults | exhaust all possibilities: if it's missing (runApp does not specify); THEN if it's not in shinyApp appParts$options; THEN use defaults |
# | yes | no | use shinyApp | if it's missing (runApp does not specify); THEN if it's in shinyApp appParts$options; THEN use shinyApp |
# | no | yes | use runApp | if it's not missing (runApp specifies), use those |
# | yes | yes | use runApp | if it's not missing (runApp specifies), use those |
#
# I tried to make this as compact and intuitive as possible,
# given that there are four distinct possibilities to check
appOps <- appParts$options
findVal <- function(arg, default) {
if (arg %in% names(appOps)) appOps[[arg]] else default
}
if (missing(port))
port <- findVal("port", port)
if (missing(launch.browser))
launch.browser <- findVal("launch.browser", launch.browser)
if (missing(host))
host <- findVal("host", host)
if (missing(quiet))
quiet <- findVal("quiet", quiet)
if (missing(display.mode))
display.mode <- findVal("display.mode", display.mode)
if (missing(test.mode))
test.mode <- findVal("test.mode", test.mode)
if (is.null(host) || is.na(host)) host <- '0.0.0.0'
# ============================================================================
# Hosted environment
# ============================================================================
workerId(workerId)
if (inShinyServer()) {
# If SHINY_PORT is set, we're running under Shiny Server. Check the version
# to make sure it is compatible. Older versions of Shiny Server don't set
# SHINY_SERVER_VERSION, those will return "" which is considered less than
# any valid version.
ver <- Sys.getenv('SHINY_SERVER_VERSION')
if (utils::compareVersion(ver, .shinyServerMinVersion) < 0) {
warning('Shiny Server v', .shinyServerMinVersion,
' or later is required; please upgrade!')
}
}
# ============================================================================
# Shinytest
# ============================================================================
# Set the testmode shinyoption so that this can be read by both the
# ShinySession and the UI code (which executes separately from the
# ShinySession code).
shinyOptions(testmode = test.mode)
if (test.mode) {
message("Running application in test mode.")
}
# ============================================================================
# Showcase mode
# ============================================================================
# Showcase mode is disabled by default; it must be explicitly enabled in
# either the DESCRIPTION file for directory-based apps, or via
# the display.mode parameter. The latter takes precedence.
setShowcaseDefault(0)
# If appDir specifies a path, and display mode is specified in the
# DESCRIPTION file at that path, apply it here.
if (is.character(appDir)) {
# if appDir specifies a .R file (single-file Shiny app), look for the
# DESCRIPTION in the parent directory
desc <- file.path.ci(
if (tolower(tools::file_ext(appDir)) == "r")
dirname(appDir)
else
appDir, "DESCRIPTION")
if (file.exists(desc)) {
con <- file(desc, encoding = checkEncoding(desc))
on.exit(close(con), add = TRUE)
settings <- read.dcf(con)
if ("DisplayMode" %in% colnames(settings)) {
mode <- settings[1, "DisplayMode"]
if (mode == "Showcase") {
setShowcaseDefault(1)
if ("IncludeWWW" %in% colnames(settings)) {
.globals$IncludeWWW <- as.logical(settings[1, "IncludeWWW"])
if (is.na(.globals$IncludeWWW)) {
stop("In your Description file, `IncludeWWW` ",
"must be set to `True` (default) or `False`")
}
} else {
.globals$IncludeWWW <- TRUE
}
}
}
}
}
## default is to show the .js, .css and .html files in the www directory
## (if not in showcase mode, this variable will simply be ignored)
if (is.null(.globals$IncludeWWW) || is.na(.globals$IncludeWWW)) {
.globals$IncludeWWW <- TRUE
}
# If display mode is specified as an argument, apply it (overriding the
# value specified in DESCRIPTION, if any).
display.mode <- match.arg(display.mode)
if (display.mode == "normal") {
setShowcaseDefault(0)
}
else if (display.mode == "showcase") {
setShowcaseDefault(1)
}
# ============================================================================
# Server port
# ============================================================================
# determine port if we need to
if (is.null(port)) {
# Try up to 20 random ports. If we don't succeed just plow ahead
# with the final value we tried, and let the "real" startServer
# somewhere down the line fail and throw the error to the user.
#
# If we (think we) succeed, save the value as .globals$lastPort,
# and try that first next time the user wants a random port.
for (i in 1:20) {
if (!is.null(.globals$lastPort)) {
port <- .globals$lastPort
.globals$lastPort <- NULL
}
else {
# Try up to 20 random ports
while (TRUE) {
port <- p_randomInt(3000, 8000)
# Reject ports in this range that are considered unsafe by Chrome
# http://superuser.com/questions/188058/which-ports-are-considered-unsafe-on-chrome
# https://github.com/rstudio/shiny/issues/1784
# https://chromium.googlesource.com/chromium/src.git/+/refs/heads/main/net/base/port_util.cc
if (!port %in% c(3659, 4045, 5060, 5061, 6000, 6566, 6665:6669, 6697)) {
break
}
}
}
# Test port to see if we can use it
tmp <- try(startServer(host, port, list()), silent=TRUE)
if (!inherits(tmp, 'try-error')) {
stopServer(tmp)
.globals$lastPort <- port
break
}
}
}
# ============================================================================
# onStart/onStop callbacks
# ============================================================================
# Set up the onStop before we call onStart, so that it gets called even if an
# error happens in onStart.
if (!is.null(appParts$onStop))
on.exit(appParts$onStop(), add = TRUE)
if (!is.null(appParts$onStart))
appParts$onStart()
# ============================================================================
# Start/stop httpuv app
# ============================================================================
server <- startApp(appParts, port, host, quiet)
# Make the httpuv server object accessible. Needed for calling
# addResourcePath while app is running.
shinyOptions(server = server)
on.exit({
stopServer(server)
}, add = TRUE)
# ============================================================================
# Launch web browser
# ============================================================================
if (!is.character(port)) {
browseHost <- host
if (identical(host, "0.0.0.0")) {
# http://0.0.0.0/ doesn't work on QtWebKit (i.e. RStudio viewer)
browseHost <- "127.0.0.1"
} else if (identical(host, "::")) {
browseHost <- "::1"
}
if (httpuv::ipFamily(browseHost) == 6L) {
browseHost <- paste0("[", browseHost, "]")
}
appUrl <- paste("http://", browseHost, ":", port, sep="")
if (is.function(launch.browser))
launch.browser(appUrl)
else if (launch.browser)
utils::browseURL(appUrl)
} else {
appUrl <- NULL
}
# ============================================================================
# Application hooks
# ============================================================================
callAppHook("onAppStart", appUrl)
on.exit({
callAppHook("onAppStop", appUrl)
}, add = TRUE)
# ============================================================================
# Run event loop via httpuv
# ============================================================================
.globals$reterror <- NULL
.globals$retval <- NULL
.globals$stopped <- FALSE
# Top-level ..stacktraceoff..; matches with ..stacktraceon in observe(),
# reactive(), Callbacks$invoke(), and others
..stacktraceoff..(
captureStackTraces({
while (!.globals$stopped) {
..stacktracefloor..(serviceApp())
}
})
)
if (isTRUE(.globals$reterror)) {
stop(.globals$retval)
}
else if (.globals$retval$visible)
.globals$retval$value
else
invisible(.globals$retval$value)
}
#' Stop the currently running Shiny app
#'
#' Stops the currently running Shiny app, returning control to the caller of
#' [runApp()].
#'
#' @param returnValue The value that should be returned from
#' [runApp()].
#' @export
stopApp <- function(returnValue = invisible()) {
# reterror will indicate whether retval is an error (i.e. it should be passed
# to stop() when the serviceApp loop stops) or a regular value (in which case
# it should simply be returned with the appropriate visibility).
.globals$reterror <- FALSE
..stacktraceoff..(
tryCatch(
{
captureStackTraces(
.globals$retval <- withVisible(..stacktraceon..(force(returnValue)))
)
},
error = function(e) {
.globals$retval <- e
.globals$reterror <- TRUE
}
)
)
.globals$stopped <- TRUE
httpuv::interrupt()
}
#' Run Shiny Example Applications
#'
#' Launch Shiny example applications, and optionally, your system's web browser.
#'
#' @param example The name of the example to run, or `NA` (the default) to
#' list the available examples.
#' @param launch.browser If true, the system's default web browser will be
#' launched automatically after the app is started. Defaults to true in
#' interactive sessions only.
#' @param host The IPv4 address that the application should listen on. Defaults
#' to the `shiny.host` option, if set, or `"127.0.0.1"` if not.
#' @param display.mode The mode in which to display the example. Defaults to
#' `"auto"`, which uses the value of `DisplayMode` in the example's
#' `DESCRIPTION` file. Set to `"showcase"` to show the app code and
#' description with the running app, or `"normal"` to see the example without
#' code or commentary.
#' @param package The package in which to find the example (defaults to
#' `"shiny"`).
#'
#' To provide examples in your package, store examples in the
#' `inst/examples-shiny` directory of your package. Each example should be
#' in its own subdirectory and should be runnable when [runApp()] is called
#' on the subdirectory. Example apps can include a `DESCRIPTION` file and a
#' `README.md` file to provide metadata and commentary about the example. See
#' the article on [Display Modes](https://shiny.posit.co/r/articles/build/display-modes/)
#' on the Shiny website for more information.
#' @inheritParams runApp
#'
#' @examples
#' ## Only run this example in interactive R sessions
#' if (interactive()) {
#' # List all available examples
#' runExample()
#'
#' # Run one of the examples
#' runExample("01_hello")
#'
#' # Print the directory containing the code for all examples
#' system.file("examples", package="shiny")
#' }
#' @export
runExample <- function(
example = NA,
port = getOption("shiny.port"),
launch.browser = getOption("shiny.launch.browser", interactive()),
host = getOption("shiny.host", "127.0.0.1"),
display.mode = c("auto", "normal", "showcase"),
package = "shiny"
) {
if (!identical(package, "shiny") && !is_installed(package)) {
rlang::check_installed(package)
}
use_legacy_shiny_examples <-
identical(package, "shiny") &&
isTRUE(getOption('shiny.legacy.examples', FALSE))
examplesDir <- system_file(
if (use_legacy_shiny_examples) "examples" else "examples-shiny",
package = package
)
dir <- resolve(examplesDir, example)
if (is.null(dir)) {
valid_examples <- sprintf(
'Valid examples in {%s}: "%s"',
package,
paste(list.files(examplesDir), collapse = '", "')
)
if (is.na(example)) {
message(valid_examples)
return(invisible())
}
stop("Example '", example, "' does not exist. ", valid_examples)
}
runApp(dir, port = port, host = host, launch.browser = launch.browser,
display.mode = display.mode)
}
#' Run a gadget
#'
#' Similar to `runApp`, but handles `input$cancel` automatically, and
#' if running in RStudio, defaults to viewing the app in the Viewer pane.
#'
#' @param app Either a Shiny app object as created by
#' [`shinyApp()`][shiny] et al, or, a UI object.
#' @param server Ignored if `app` is a Shiny app object; otherwise, passed
#' along to `shinyApp` (i.e. `shinyApp(ui = app, server = server)`).
#' @param port See [`runApp()`][shiny].
#' @param viewer Specify where the gadget should be displayed--viewer pane,
#' dialog window, or external browser--by passing in a call to one of the
#' [viewer()] functions.
#' @param stopOnCancel If `TRUE` (the default), then an `observeEvent`
#' is automatically created that handles `input$cancel` by calling
#' `stopApp()` with an error. Pass `FALSE` if you want to handle
#' `input$cancel` yourself.
#' @return The value returned by the gadget.
#'
#' @examples
#' \dontrun{
#' library(shiny)
#'
#' ui <- fillPage(...)
#'
#' server <- function(input, output, session) {
#' ...
#' }
#'
#' # Either pass ui/server as separate arguments...
#' runGadget(ui, server)
#'
#' # ...or as a single app object
#' runGadget(shinyApp(ui, server))
#' }
#' @export
runGadget <- function(app, server = NULL, port = getOption("shiny.port"),
viewer = paneViewer(), stopOnCancel = TRUE) {
if (!is.shiny.appobj(app)) {
app <- shinyApp(app, server)
}
if (isTRUE(stopOnCancel)) {
app <- decorateServerFunc(app, function(input, output, session) {
observeEvent(input$cancel, {
stopApp(stop("User cancel", call. = FALSE))
})
})
}
if (is.null(viewer)) {
viewer <- utils::browseURL
}
shiny::runApp(app, port = port, launch.browser = viewer)
}
# Add custom functionality to a Shiny app object's server func
decorateServerFunc <- function(appobj, serverFunc) {
origServerFuncSource <- appobj$serverFuncSource
appobj$serverFuncSource <- function() {
origServerFunc <- origServerFuncSource()
function(input, output, session) {
serverFunc(input, output, session)
# The clientData and session arguments are optional; check if
# each exists
args <- argsForServerFunc(origServerFunc, session)
do.call(origServerFunc, args)
}
}
appobj
}

90
R/serializers.R Normal file
View File

@@ -0,0 +1,90 @@
#' Add a function for serializing an input before bookmarking application state
#'
#' @param inputId Name of the input value.
#' @param fun A function that takes the input value and returns a modified
#' value. The returned value will be used for the test snapshot.
#' @param session A Shiny session object.
#'
#' @export
setSerializer <- function(inputId, fun, session = getDefaultReactiveDomain()) {
if (is.null(session)) {
stop("setSerializer() needs a session object.")
}
input_impl <- .subset2(session$input, "impl")
input_impl$setMeta(inputId, "shiny.serializer", fun)
}
# For most types of values, simply return the value unchanged.
serializerDefault <- function(value, stateDir) {
value
}
serializerFileInput <- function(value, stateDir = NULL) {
# File inputs can be serialized only if there's a stateDir
if (is.null(stateDir)) {
return(serializerUnserializable())
}
# value is a data frame. When persisting files, we need to copy the file to
# the persistent dir and then strip the original path before saving.
newpaths <- file.path(stateDir, basename(value$datapath))
file.copy(value$datapath, newpaths, overwrite = TRUE)
value$datapath <- basename(newpaths)
value
}
# Return a sentinel value that represents "unserializable". This is applied to
# for example, passwords and actionButtons.
serializerUnserializable <- function(value, stateDir) {
structure(
list(),
serializable = FALSE
)
}
# Is this an "unserializable" sentinel value?
isUnserializable <- function(x) {
identical(
attr(x, "serializable", exact = TRUE),
FALSE
)
}
# Given a reactiveValues object and optional directory for saving state, apply
# serializer function to each of the values, and return a list of the returned
# values. This function passes stateDir to the serializer functions, so if
# stateDir is non-NULL, it can have a side effect of writing values to disk (in
# stateDir).
serializeReactiveValues <- function(values, exclude, stateDir = NULL) {
impl <- .subset2(values, "impl")
# Get named list where keys and values are the names of inputs; we'll retrieve
# actual values later.
vals <- isolate(impl$names())
vals <- setdiff(vals, exclude)
names(vals) <- vals
# Get values and apply serializer functions
vals <- lapply(vals, function(name) {
val <- impl$get(name)
# Get the serializer function for this input value. If none specified, use
# the default.
serializer_fun <- impl$getMeta(name, "shiny.serializer")
if (is.null(serializer_fun))
serializer_fun <- serializerDefault
# Apply serializer function.
serializer_fun(val, stateDir)
})
# Filter out any values that were marked as unserializable.
vals <- Filter(Negate(isUnserializable), vals)
vals
}

245
R/server-input-handlers.R Normal file
View File

@@ -0,0 +1,245 @@
# Create a Map object for input handlers and register the defaults.
# This is assigned in .onLoad time.
inputHandlers <- NULL
on_load({
inputHandlers <- Map$new()
})
#' Register an Input Handler
#'
#' Adds an input handler for data of this type. When called, Shiny will use the
#' function provided to refine the data passed back from the client (after being
#' deserialized by jsonlite) before making it available in the `input` variable
#' of the `server.R` file.
#'
#' This function will register the handler for the duration of the R process
#' (unless Shiny is explicitly reloaded). For that reason, the `type` used
#' should be very specific to this package to minimize the risk of colliding
#' with another Shiny package which might use this data type name. We recommend
#' the format of "packageName.widgetName". It should be called from the
#' package's `.onLoad()` function.
#'
#' Currently Shiny registers the following handlers: `shiny.matrix`,
#' `shiny.number`, and `shiny.date`.
#'
#' The `type` of a custom Shiny Input widget will be deduced using the
#' `getType()` JavaScript function on the registered Shiny inputBinding.
#' @param type The type for which the handler should be added --- should be a
#' single-element character vector.
#' @param fun The handler function. This is the function that will be used to
#' parse the data delivered from the client before it is available in the
#' `input` variable. The function will be called with the following three
#' parameters: \enumerate{ \item{The value of this input as provided by the
#' client, deserialized using jsonlite.} \item{The `shinysession` in which the
#' input exists.} \item{The name of the input.} }
#' @param force If `TRUE`, will overwrite any existing handler without warning.
#' If `FALSE`, will throw an error if this class already has a handler
#' defined.
#' @examples
#' \dontrun{
#' # Register an input handler which rounds a input number to the nearest integer
#' # In a package, this should be called from the .onLoad function.
#' registerInputHandler("mypackage.validint", function(x, shinysession, name) {
#' if (is.null(x)) return(NA)
#' round(x)
#' })
#'
#' ## On the Javascript side, the associated input binding must have a corresponding getType method:
#' # getType: function(el) {
#' # return "mypackage.validint";
#' # }
#'
#' }
#' @seealso [removeInputHandler()] [applyInputHandlers()]
#' @export
registerInputHandler <- function(type, fun, force=FALSE){
if (inputHandlers$containsKey(type) && !force){
stop("There is already an input handler for type: ", type)
}
inputHandlers$set(type, fun)
}
#' Deregister an Input Handler
#'
#' Removes an Input Handler. Rather than using the previously specified handler
#' for data of this type, the default jsonlite serialization will be used.
#'
#' @param type The type for which handlers should be removed.
#' @return The handler previously associated with this `type`, if one
#' existed. Otherwise, `NULL`.
#' @seealso [registerInputHandler()]
#' @export
removeInputHandler <- function(type){
inputHandlers$remove(type)
}
# Apply input handler to a single input value
applyInputHandler <- function(name, val, shinysession) {
splitName <- strsplit(name, ':')[[1]]
if (length(splitName) > 1) {
if (!inputHandlers$containsKey(splitName[[2]])) {
# No input handler registered for this type
stop("No handler registered for type ", name)
}
inputName <- splitName[[1]]
# Get the function for processing this type of input
inputHandler <- inputHandlers$get(splitName[[2]])
return(inputHandler(val, shinysession, inputName))
} else if (is.list(val) && is.null(names(val))) {
return(unlist(val, recursive = TRUE))
} else {
return(val)
}
}
#' Apply input handlers to raw input values
#'
#' The purpose of this function is to make it possible for external packages to
#' test Shiny inputs. It takes a named list of raw input values, applies input
#' handlers to those values, and then returns a named list of the processed
#' values.
#'
#' The raw input values should be in a named list. Some values may have names
#' like `"x:shiny.date"`. This function would apply the `"shiny.date"`
#' input handler to the value, and then rename the result to `"x"`, in the
#' output.
#'
#' @param inputs A named list of input values.
#' @param shinysession A Shiny session object.
#'
#' @seealso registerInputHandler
#' @keywords internal
applyInputHandlers <- function(inputs, shinysession = getDefaultReactiveDomain()) {
inputs <- mapply(applyInputHandler, names(inputs), inputs,
MoreArgs = list(shinysession = shinysession),
SIMPLIFY = FALSE)
# Convert names like "button1:shiny.action" to "button1"
names(inputs) <- vapply(
names(inputs),
function(name) { strsplit(name, ":")[[1]][1] },
FUN.VALUE = character(1)
)
inputs
}
on_load({
# Takes a list-of-lists and returns a matrix. The lists
# must all be the same length. NULL is replaced by NA.
registerInputHandler("shiny.matrix", function(data, ...) {
if (length(data) == 0)
return(matrix(nrow=0, ncol=0))
m <- matrix(unlist(lapply(data, function(x) {
sapply(x, function(y) {
ifelse(is.null(y), NA, y)
})
})), nrow = length(data[[1]]), ncol = length(data))
return(m)
})
registerInputHandler("shiny.number", function(val, ...){
ifelse(is.null(val), NA, val)
})
registerInputHandler("shiny.password", function(val, shinysession, name) {
# Mark passwords as not serializable
setSerializer(name, serializerUnserializable)
val
})
registerInputHandler("shiny.date", function(val, ...){
# First replace NULLs with NA, then convert to Date vector
datelist <- ifelse(lapply(val, is.null), NA, val)
res <- NULL
tryCatch({
res <- as.Date(unlist(datelist))
},
error = function(e) {
# It's possible for client to send a string like "99999-01-01", which
# as.Date can't handle.
warning(e$message)
res <<- as.Date(rep(NA, length(datelist)))
}
)
res
})
registerInputHandler("shiny.datetime", function(val, ...){
# First replace NULLs with NA, then convert to POSIXct vector
times <- lapply(val, function(x) {
if (is.null(x)) NA
else x
})
as.POSIXct(unlist(times), origin = "1970-01-01", tz = "UTC")
})
registerInputHandler("shiny.action", function(val, shinysession, name) {
# mark up the action button value with a special class so we can recognize it later
class(val) <- c("shinyActionButtonValue", class(val))
val
})
registerInputHandler("shiny.file", function(val, shinysession, name) {
# This function is only used when restoring a Shiny fileInput. When a file is
# uploaded the usual way, it takes a different code path and won't hit this
# function.
if (is.null(val))
return(NULL)
# The data will be a named list of lists; convert to a data frame.
val <- as.data.frame(lapply(val, unlist), stringsAsFactors = FALSE)
# `val$datapath` should be a filename without a path, for security reasons.
if (basename(val$datapath) != val$datapath) {
stop("Invalid '/' found in file input path.")
}
# Prepend the persistent dir
oldfile <- file.path(getCurrentRestoreContext()$dir, val$datapath)
# Copy the original file to a new temp dir, so that a restored session can't
# modify the original.
newdir <- file.path(tempdir(), createUniqueId(12))
dir.create(newdir)
val$datapath <- file.path(newdir, val$datapath)
file.copy(oldfile, val$datapath)
# Need to mark this input value with the correct serializer. When a file is
# uploaded the usual way (instead of being restored), this occurs in
# session$`@uploadEnd`.
setSerializer(name, serializerFileInput)
snapshotPreprocessInput(name, snapshotPreprocessorFileInput)
val
})
# to be used with !!!answer
registerInputHandler("shiny.symbolList", function(val, ...) {
if (is.null(val)) {
list()
} else {
lapply(val, as.symbol)
}
})
# to be used with !!answer
registerInputHandler("shiny.symbol", function(val, ...) {
if (is.null(val) || identical(val, "")) {
NULL
} else {
as.symbol(val)
}
})
})

169
R/server-resource-paths.R Normal file
View File

@@ -0,0 +1,169 @@
.globals$resourcePaths <- list()
.globals$resources <- list()
#' Resource Publishing
#'
#' Add, remove, or list directory of static resources to Shiny's web server,
#' with the given path prefix. Primarily intended for package authors to make
#' supporting JavaScript/CSS files available to their components.
#'
#' Shiny provides two ways of serving static files (i.e., resources):
#'
#' 1. Static files under the `www/` directory are automatically made available
#' under a request path that begins with `/`.
#' 2. `addResourcePath()` makes static files in a `directoryPath` available
#' under a request path that begins with `prefix`.
#'
#' The second approach is primarily intended for package authors to make
#' supporting JavaScript/CSS files available to their components.
#'
#' Tools for managing static resources published by Shiny's web server:
#' * `addResourcePath()` adds a directory of static resources.
#' * `resourcePaths()` lists the currently active resource mappings.
#' * `removeResourcePath()` removes a directory of static resources.
#'
#' @param prefix The URL prefix (without slashes). Valid characters are a-z,
#' A-Z, 0-9, hyphen, period, and underscore. For example, a value of 'foo'
#' means that any request paths that begin with '/foo' will be mapped to the
#' given directory.
#' @param directoryPath The directory that contains the static resources to be
#' served.
#'
#' @rdname resourcePaths
#' @seealso [singleton()]
#'
#' @examples
#' addResourcePath('datasets', system.file('data', package='datasets'))
#' resourcePaths()
#' removeResourcePath('datasets')
#' resourcePaths()
#'
#' # make sure all resources are removed
#' lapply(names(resourcePaths()), removeResourcePath)
#' @export
addResourcePath <- function(prefix, directoryPath) {
if (length(prefix) != 1) stop("prefix must be of length 1")
if (grepl("^\\.+$", prefix)) stop("prefix can't be composed of dots only")
if (!grepl('[a-z0-9\\-_.]+$', prefix, ignore.case = TRUE, perl = TRUE)) {
stop("addResourcePath called with invalid prefix; please see documentation")
}
if (prefix %in% c('shared')) {
stop("addResourcePath called with the reserved prefix '", prefix, "'; ",
"please use a different prefix")
}
normalizedPath <- tryCatch(normalizePath(directoryPath, mustWork = TRUE),
error = function(e) {
stop("Couldn't normalize path in `addResourcePath`, with arguments: ",
"`prefix` = '", prefix, "'; `directoryPath` = '" , directoryPath, "'")
}
)
# # Often times overwriting a resource path is "what you want",
# # but sometimes it can lead to difficult to diagnose issues
# # (e.g. an implict dependency might set a resource path that
# # conflicts with what you, the app author, are trying to register)
# # Note that previous versions of shiny used to warn about this case,
# # but it was eventually removed since it caused confusion (#567).
# # It seems a good compromise is to throw a more information message.
# if (getOption("shiny.resourcePathChanges", FALSE) &&
# prefix %in% names(.globals$resourcePaths)) {
# existingPath <- .globals$resourcePaths[[prefix]]$path
# if (normalizedPath != existingPath) {
# message(
# "The resource path '", prefix, "' used to point to ",
# existingPath, ", but it now points to ", normalizedPath, ". ",
# "If your app doesn't work as expected, you may want to ",
# "choose a different prefix name."
# )
# }
# }
# If a shiny app is currently running, dynamically register this path with
# the corresponding httpuv server object.
if (!is.null(getShinyOption("server", default = NULL)))
{
getShinyOption("server")$setStaticPath(.list = stats::setNames(normalizedPath, prefix))
}
# .globals$resourcePaths and .globals$resources persist across runs of applications.
.globals$resourcePaths[[prefix]] <- staticPath(normalizedPath)
# This is necessary because resourcePaths is only for serving assets out of C++;
# to support subapps, we also need assets to be served out of R, because those
# URLs are rewritten by R code (i.e. routeHandler) before they can be matched to
# a resource path.
.globals$resources[[prefix]] <- list(
directoryPath = normalizedPath,
func = staticHandler(normalizedPath)
)
}
#' @rdname resourcePaths
#' @export
resourcePaths <- function() {
urls <- names(.globals$resourcePaths)
paths <- vapply(.globals$resourcePaths, function(x) x$path, character(1))
stats::setNames(paths, urls)
}
hasResourcePath <- function(prefix) {
prefix %in% names(resourcePaths())
}
#' @rdname resourcePaths
#' @export
removeResourcePath <- function(prefix) {
if (length(prefix) > 1) stop("`prefix` must be of length 1.")
if (!hasResourcePath(prefix)) {
warning("Resource ", prefix, " not found.")
return(invisible(FALSE))
}
.globals$resourcePaths[[prefix]] <- NULL
.globals$resources[[prefix]] <- NULL
invisible(TRUE)
}
# This function handles any GET request with two or more path elements where the
# first path element matches a prefix that was previously added using
# addResourcePath().
#
# For example, if `addResourcePath("foo", "~/bar")` was called, then a GET
# request for /foo/one/two.html would rewrite the PATH_INFO as /one/two.html and
# send it to the resource path function for "foo". As of this writing, that
# function will always be a staticHandler, which serves up a file if it exists
# and NULL if it does not.
#
# Since Shiny 1.3.x, assets registered via addResourcePath should mostly be
# served out of httpuv's native static file serving features. However, in the
# specific case of subapps, the R code path must be used, because subapps insert
# a giant random ID into the beginning of the URL that must be stripped off by
# an R route handler (see addSubApp()).
resourcePathHandler <- function(req) {
if (!identical(req$REQUEST_METHOD, 'GET'))
return(NULL)
# e.g. "/foo/one/two.html"
path <- req$PATH_INFO
match <- regexpr('^/([^/]+)/', path, perl=TRUE)
if (match == -1)
return(NULL)
len <- attr(match, 'capture.length')
# e.g. "foo"
prefix <- substr(path, 2, 2 + len - 1)
resInfo <- .globals$resources[[prefix]]
if (is.null(resInfo))
return(NULL)
# e.g. "/one/two.html"
suffix <- substr(path, 2 + len, nchar(path))
# Create a new request that's a clone of the current request, but adjust
# PATH_INFO and SCRIPT_NAME to reflect that we have already matched the first
# path element (e.g. "/foo"). See routeHandler() for more info.
subreq <- as.environment(as.list(req, all.names=TRUE))
subreq$PATH_INFO <- suffix
subreq$SCRIPT_NAME <- paste(subreq$SCRIPT_NAME, substr(path, 1, 2 + len), sep='')
return(resInfo$func(subreq))
}

525
R/server.R Normal file
View File

@@ -0,0 +1,525 @@
#' @include server-input-handlers.R
appsByToken <- NULL
appsNeedingFlush <- NULL
on_load({
appsByToken <- Map$new()
appsNeedingFlush <- Map$new()
})
# Provide a character representation of the WS that can be used
# as a key in a Map.
wsToKey <- function(WS) {
as.character(WS$socket)
}
.globals$clients <- function(req) NULL
clearClients <- function() {
.globals$clients <- function(req) NULL
}
registerClient <- function(client) {
.globals$clients <- append(.globals$clients, client)
}
.globals$showcaseDefault <- 0
.globals$showcaseOverride <- FALSE
#' Define Server Functionality
#'
#' @description `r lifecycle::badge("superseded")`
#'
#' @description Defines the server-side logic of the Shiny application. This generally
#' involves creating functions that map user inputs to various kinds of output.
#' In older versions of Shiny, it was necessary to call `shinyServer()` in
#' the `server.R` file, but this is no longer required as of Shiny 0.10.
#' Now the `server.R` file may simply return the appropriate server
#' function (as the last expression in the code), without calling
#' `shinyServer()`.
#'
#' Call `shinyServer` from your application's `server.R`
#' file, passing in a "server function" that provides the server-side logic of
#' your application.
#'
#' The server function will be called when each client (web browser) first loads
#' the Shiny application's page. It must take an `input` and an
#' `output` parameter. Any return value will be ignored. It also takes an
#' optional `session` parameter, which is used when greater control is
#' needed.
#'
#' See the [tutorial](https://shiny.rstudio.com/tutorial/) for more
#' on how to write a server function.
#'
#' @param func The server function for this application. See the details section
#' for more information.
#'
#' @examples
#' \dontrun{
#' # A very simple Shiny app that takes a message from the user
#' # and outputs an uppercase version of it.
#' shinyServer(function(input, output, session) {
#' output$uppercase <- renderText({
#' toupper(input$message)
#' })
#' })
#'
#'
#' # It is also possible for a server.R file to simply return the function,
#' # without calling shinyServer().
#' # For example, the server.R file could contain just the following:
#' function(input, output, session) {
#' output$uppercase <- renderText({
#' toupper(input$message)
#' })
#' }
#' }
#' @export
#' @keywords internal
shinyServer <- function(func) {
if (in_devmode()) {
shinyDeprecated(
"0.10.0", "shinyServer()",
details = paste0(
"When removing `shinyServer()`, ",
"ensure that the last expression returned from server.R ",
"is the function normally supplied to `shinyServer(func)`."
)
)
}
.globals$server <- list(func)
invisible(func)
}
decodeMessage <- function(data) {
readInt <- function(pos) {
packBits(rawToBits(data[pos:(pos+3)]), type='integer')
}
if (readInt(1) != 0x01020202L) {
# Treat message as UTF-8
charData <- rawToChar(data)
Encoding(charData) <- 'UTF-8'
return(safeFromJSON(charData, simplifyVector=FALSE))
}
i <- 5
parts <- list()
while (i <= length(data)) {
length <- readInt(i)
i <- i + 4
if (length != 0)
parts <- append(parts, list(data[i:(i+length-1)]))
else
parts <- append(parts, list(raw(0)))
i <- i + length
}
mainMessage <- decodeMessage(parts[[1]])
mainMessage$blobs <- parts[2:length(parts)]
return(mainMessage)
}
autoReloadCallbacks <- NULL
on_load({
autoReloadCallbacks <- Callbacks$new()
})
createAppHandlers <- function(httpHandlers, serverFuncSource) {
appvars <- new.env()
appvars$server <- NULL
sys.www.root <- system_file('www', package='shiny')
# This value, if non-NULL, must be present on all HTTP and WebSocket
# requests as the Shiny-Shared-Secret header or else access will be
# denied (403 response for HTTP, and instant close for websocket).
checkSharedSecret <- loadSharedSecret()
appHandlers <- list(
http = joinHandlers(c(
sessionHandler,
httpHandlers,
sys.www.root,
resourcePathHandler,
reactLogHandler
)),
ws = function(ws) {
if (!checkSharedSecret(ws$request$HTTP_SHINY_SHARED_SECRET)) {
ws$close()
return(TRUE)
}
if (identical(ws$request$PATH_INFO, "/autoreload/")) {
if (!get_devmode_option("shiny.autoreload", FALSE)) {
ws$close()
return(TRUE)
}
callbackHandle <- autoReloadCallbacks$register(function() {
ws$send("autoreload")
ws$close()
})
ws$onClose(function() {
callbackHandle()
})
return(TRUE)
}
if (!is.null(getOption("shiny.observer.error", NULL))) {
warning(
call. = FALSE,
"options(shiny.observer.error) is no longer supported; please unset it!"
)
stopApp()
}
shinysession <- ShinySession$new(ws)
appsByToken$set(shinysession$token, shinysession)
shinysession$setShowcase(.globals$showcaseDefault)
messageHandler <- function(binary, msg) {
withReactiveDomain(shinysession, {
# To ease transition from websockets-based code. Should remove once we're stable.
if (is.character(msg))
msg <- charToRaw(msg)
traceOption <- getOption('shiny.trace', FALSE)
if (isTRUE(traceOption) || traceOption == "recv") {
if (binary)
message("RECV ", '$$binary data$$')
else
message("RECV ", rawToChar(msg))
}
if (isEmptyMessage(msg))
return()
msg <- decodeMessage(msg)
# Set up a restore context from .clientdata_url_search before
# handling all the input values, because the restore context may be
# used by an input handler (like the one for "shiny.file"). This
# should only happen once, when the app starts.
if (is.null(shinysession$restoreContext)) {
bookmarkStore <- getShinyOption("bookmarkStore", default = "disable")
if (bookmarkStore == "disable") {
# If bookmarking is disabled, use empty context
shinysession$restoreContext <- RestoreContext$new()
} else {
# If there's bookmarked state, save it on the session object
shinysession$restoreContext <- RestoreContext$new(msg$data$.clientdata_url_search)
shinysession$createBookmarkObservers()
}
}
msg$data <- applyInputHandlers(msg$data)
switch(
msg$method,
init = {
serverFunc <- withReactiveDomain(NULL, serverFuncSource())
if (!identicalFunctionBodies(serverFunc, appvars$server)) {
appvars$server <- serverFunc
if (!is.null(appvars$server))
{
# Tag this function as the Shiny server function. A debugger may use this
# tag to give this function special treatment.
# It's very important that it's appvars$server itself and NOT a copy that
# is invoked, otherwise new breakpoints won't be picked up.
attr(appvars$server, "shinyServerFunction") <- TRUE
registerDebugHook("server", appvars, "Server Function")
}
}
# Check for switching into/out of showcase mode
if (.globals$showcaseOverride &&
exists(".clientdata_url_search", where = msg$data)) {
mode <- showcaseModeOfQuerystring(msg$data$.clientdata_url_search)
if (!is.null(mode))
shinysession$setShowcase(mode)
}
# In shinysession$createBookmarkObservers() above, observers may be
# created, which puts the shiny session in busyCount > 0 state. That
# prevents the manageInputs here from taking immediate effect, by
# default. The manageInputs here needs to take effect though, because
# otherwise the bookmark observers won't find the clientData they are
# looking for. So use `now = TRUE` to force the changes to be
# immediate.
#
# FIXME: break createBookmarkObservers into two separate steps, one
# before and one after manageInputs, and put the observer creation
# in the latter. Then add an assertion that busyCount == 0L when
# this manageInputs is called.
shinysession$manageInputs(msg$data, now = TRUE)
# The client tells us what singletons were rendered into
# the initial page
if (!is.null(msg$data$.clientdata_singletons)) {
shinysession$singletons <- strsplit(
msg$data$.clientdata_singletons, ',')[[1]]
}
local({
args <- argsForServerFunc(serverFunc, shinysession)
withReactiveDomain(shinysession, {
otel_span_session_start(domain = shinysession, {
do.call(
# No corresponding ..stacktraceoff; the server func is pure
# user code
wrapFunctionLabel(appvars$server, "server",
..stacktraceon = TRUE
),
args
)
})
})
})
},
update = {
shinysession$manageInputs(msg$data)
},
shinysession$dispatch(msg)
)
# The HTTP_GUID, if it exists, is for Shiny Server reporting purposes
shinysession$startTiming(ws$request$HTTP_GUID)
shinysession$requestFlush()
# Make httpuv return control to Shiny quickly, instead of waiting
# for the usual timeout
httpuv::interrupt()
})
}
ws$onMessage(function(binary, msg) {
# If unhandled errors occur, make sure they get properly logged
withLogErrors(messageHandler(binary, msg))
})
ws$onClose(function() {
shinysession$wsClosed()
appsByToken$remove(shinysession$token)
appsNeedingFlush$remove(shinysession$token)
})
return(TRUE)
}
)
return(appHandlers)
}
# Determine what arguments should be passed to this serverFunc. All server funcs
# must take input and output, but clientData (obsolete) and session are
# optional.
argsForServerFunc <- function(serverFunc, session) {
args <- list(input = session$input, output = .createOutputWriter(session))
paramNames <- names(formals(serverFunc))
# The clientData and session arguments are optional; check if
# each exists
if ("clientData" %in% paramNames)
args$clientData <- session$clientData
if ("session" %in% paramNames)
args$session <- session
args
}
getEffectiveBody <- function(func) {
if (is.null(func))
NULL
else if (isS4(func) && inherits(func, "functionWithTrace"))
body(func@original)
else
body(func)
}
identicalFunctionBodies <- function(a, b) {
identical(getEffectiveBody(a), getEffectiveBody(b))
}
handlerManager <- HandlerManager$new()
addSubApp <- function(appObj, autoRemove = TRUE) {
path <- createUniqueId(16, "/app")
appHandlers <- createAppHandlers(appObj$httpHandler, appObj$serverFuncSource)
# remove the leading / from the path so a relative path is returned
# (needed for the case where the root URL for the Shiny app isn't /, such
# as portmapped URLs)
finalPath <- paste(
substr(path, 2, nchar(path)),
"/?w=", workerId(),
"&__subapp__=1",
sep="")
handlerManager$addHandler(routeHandler(path, appHandlers$http), finalPath)
handlerManager$addWSHandler(routeWSHandler(path, appHandlers$ws), finalPath)
if (autoRemove) {
# If a session is currently active, remove this subapp automatically when
# the current session ends
onReactiveDomainEnded(getDefaultReactiveDomain(), function() {
removeSubApp(finalPath)
})
}
return(finalPath)
}
removeSubApp <- function(path) {
handlerManager$removeHandler(path)
handlerManager$removeWSHandler(path)
}
startApp <- function(appObj, port, host, quiet) {
appHandlers <- createAppHandlers(appObj$httpHandler, appObj$serverFuncSource)
handlerManager$addHandler(appHandlers$http, "/", tail = TRUE)
handlerManager$addWSHandler(appHandlers$ws, "/", tail = TRUE)
httpuvApp <- handlerManager$createHttpuvApp()
httpuvApp$staticPaths <- c(
appObj$staticPaths,
list(
# Always handle /session URLs dynamically, even if / is a static path.
"session" = excludeStaticPath(),
"shared" = system_file(package = "shiny", "www", "shared")
),
.globals$resourcePaths
)
# throw an informative warning if a subdirectory of the
# app's www dir conflicts with another resource prefix
wwwDir <- httpuvApp$staticPaths[["/"]]$path
if (length(wwwDir)) {
# although httpuv allows for resource prefixes like 'foo/bar',
# we won't worry about conflicts in sub-sub directories since
# addResourcePath() currently doesn't allow it
wwwSubDirs <- list.dirs(wwwDir, recursive = FALSE, full.names = FALSE)
resourceConflicts <- intersect(wwwSubDirs, names(httpuvApp$staticPaths))
if (length(resourceConflicts)) {
warning(
"Found subdirectories of your app's www/ directory that ",
"conflict with other resource URL prefixes. ",
"Consider renaming these directories: '",
paste0("www/", resourceConflicts, collapse = "', '"), "'",
call. = FALSE
)
}
}
# check for conflicts in each pairwise combinations of resource mappings
checkResourceConflict <- function(paths) {
if (length(paths) < 2) return(NULL)
# ensure paths is a named character vector: c(resource_path = local_path)
paths <- vapply(paths, function(x) if (inherits(x, "staticPath")) x$path else x, character(1))
# get all possible pairwise combinations of paths
pair_indices <- utils::combn(length(paths), 2, simplify = FALSE)
lapply(pair_indices, function(x) {
p1 <- paths[x[1]]
p2 <- paths[x[2]]
if (identical(names(p1), names(p2)) && (p1 != p2)) {
warning(
"Found multiple local file paths pointing the same resource prefix: ", names(p1), ". ",
"If you run into resource-related issues (e.g. 404 requests), consider ",
"using `addResourcePath()` and/or `removeResourcePath()` to manage resource mappings.",
call. = FALSE
)
}
})
}
checkResourceConflict(httpuvApp$staticPaths)
httpuvApp$staticPathOptions <- httpuv::staticPathOptions(
html_charset = "utf-8",
headers = list("X-UA-Compatible" = "IE=edge,chrome=1"),
validation =
if (!is.null(getOption("shiny.sharedSecret"))) {
sprintf('"Shiny-Shared-Secret" == "%s"', getOption("shiny.sharedSecret"))
} else {
character(0)
}
)
if (is.numeric(port) || is.integer(port)) {
if (!quiet) {
hostString <- host
if (httpuv::ipFamily(host) == 6L)
hostString <- paste0("[", hostString, "]")
message('\n', 'Listening on http://', hostString, ':', port)
}
return(startServer(host, port, httpuvApp))
} else if (is.character(port)) {
if (!quiet) {
message('\n', 'Listening on domain socket ', port)
}
mask <- attr(port, 'mask')
if (is.null(mask)) {
stop("`port` is not a valid domain socket (missing `mask` attribute). ",
"Note that if you're using the default `host` + `port` ",
"configuration (and not domain sockets), then `port` must ",
"be numeric, not a string.")
}
return(startPipeServer(port, mask, httpuvApp))
}
}
# Run an application that was created by \code{\link{startApp}}. This
# function should normally be called in a \code{while(TRUE)} loop.
serviceApp <- function() {
timerCallbacks$executeElapsed()
flushReact()
flushPendingSessions()
# If this R session is interactive, then call service() with a short timeout
# to keep the session responsive to user input
maxTimeout <- ifelse(interactive(), 100, 1000)
timeout <- max(1, min(maxTimeout, timerCallbacks$timeToNextEvent(), later::next_op_secs()))
service(timeout)
flushReact()
flushPendingSessions()
}
.shinyServerMinVersion <- '0.3.4'
#' Check whether a Shiny application is running
#'
#' This function tests whether a Shiny application is currently running.
#'
#' @return `TRUE` if a Shiny application is currently running. Otherwise,
#' `FALSE`.
#' @export
isRunning <- function() {
!is.null(getCurrentAppState())
}
# Returns TRUE if we're running in Shiny Server or other hosting environment,
# otherwise returns FALSE.
inShinyServer <- function() {
nzchar(Sys.getenv('SHINY_PORT'))
}
# This check was moved out of the main function body because of an issue with
# the RStudio debugger. (#1474)
isEmptyMessage <- function(msg) {
identical(as.raw(c(0x03, 0xe9)), msg)
}

313
R/shiny-options.R Normal file
View File

@@ -0,0 +1,313 @@
.globals$options <- list()
#' @param name Name of an option to get.
#' @param default Value to be returned if the option is not currently set.
#' @rdname shinyOptions
#' @export
getShinyOption <- function(name, default = NULL) {
# Make sure to use named (not numeric) indexing
name <- as.character(name)
# Check if there's a current session
session <- getDefaultReactiveDomain()
if (!is.null(session)) {
if (name %in% names(session$options)) {
return(session$options[[name]])
} else {
return(default)
}
}
# Check if there's a current app
app_state <- getCurrentAppState()
if (!is.null(app_state)) {
if (name %in% names(app_state$options)) {
return(app_state$options[[name]])
} else {
return(default)
}
}
# If we got here, look in global options
if (name %in% names(.globals$options)) {
return(.globals$options[[name]])
} else {
return(default)
}
}
#' Get or set Shiny options
#'
#' @description
#'
#' There are two mechanisms for working with options for Shiny. One is the
#' [options()] function, which is part of base R, and the other is the
#' `shinyOptions()` function, which is in the Shiny package. The reason for
#' these two mechanisms is has to do with legacy code and scoping.
#'
#' The [options()] function sets options globally, for the duration of the R
#' process. The [getOption()] function retrieves the value of an option. All
#' shiny related options of this type are prefixed with `"shiny."`.
#'
#' The `shinyOptions()` function sets the value of a shiny option, but unlike
#' `options()`, it is not always global in scope; the options may be scoped
#' globally, to an application, or to a user session in an application,
#' depending on the context. The `getShinyOption()` function retrieves a value
#' of a shiny option. Currently, the options set via `shinyOptions` are for
#' internal use only.
#'
#' @section Options with `options()`:
#'
#' \describe{
#' \item{shiny.autoreload (defaults to `FALSE`)}{If `TRUE` when a Shiny app is launched, the
#' app directory will be continually monitored for changes to files that
#' have the extensions: r, htm, html, js, css, png, jpg, jpeg, gif. If any
#' changes are detected, all connected Shiny sessions are reloaded. This
#' allows for fast feedback loops when tweaking Shiny UI.
#'
#' Monitoring for changes is no longer expensive, thanks to the \pkg{watcher}
#' package, but this feature is still intended only for development.
#'
#' You can customize the file patterns Shiny will monitor by setting the
#' shiny.autoreload.pattern option. For example, to monitor only `ui.R`:
#' `options(shiny.autoreload.pattern = glob2rx("ui.R"))`.
#'
#' As mentioned above, Shiny no longer polls watched files for changes.
#' Instead, using \pkg{watcher}, Shiny is notified of file changes as they
#' occur. These changes are batched together within a customizable latency
#' period. You can adjust this period by setting
#' `options(shiny.autoreload.interval = 2000)` (in milliseconds). This value
#' converted to seconds and passed to the `latency` argument of
#' [watcher::watcher()]. The default latency is 250ms.}
#' \item{shiny.deprecation.messages (defaults to `TRUE`)}{This controls whether messages for
#' deprecated functions in Shiny will be printed. See
#' [shinyDeprecated()] for more information.}
#' \item{shiny.error (defaults to `NULL`)}{This can be a function which is called when an error
#' occurs. For example, `options(shiny.error=recover)` will result a
#' the debugger prompt when an error occurs.}
#' \item{shiny.fullstacktrace (defaults to `FALSE`)}{Controls whether "pretty" (`FALSE`) or full
#' stack traces (`TRUE`) are dumped to the console when errors occur during Shiny app execution.
#' Pretty stack traces attempt to only show user-supplied code, but this pruning can't always
#' be done 100% correctly.}
#' \item{shiny.host (defaults to `"127.0.0.1"`)}{The IP address that Shiny should listen on. See
#' [runApp()] for more information.}
#' \item{shiny.jquery.version (defaults to `3`)}{The major version of jQuery to use.
#' Currently only values of `3` or `1` are supported. If `1`, then jQuery 1.12.4 is used. If `3`,
#' then jQuery `r version_jquery` is used.}
#' \item{shiny.json.digits (defaults to `I(16)`)}{Max number of digits to use when converting
#' numbers to JSON format to send to the client web browser. Use [I()] to specify significant digits.
#' Use `NA` for max precision.}
#' \item{shiny.launch.browser (defaults to `interactive()`)}{A boolean which controls the default behavior
#' when an app is run. See [runApp()] for more information.}
#' \item{shiny.mathjax.url (defaults to `"https://mathjax.rstudio.com/latest/MathJax.js"`)}{
#' The URL that should be used to load MathJax, via [withMathJax()].}
#' \item{shiny.mathjax.config (defaults to `"config=TeX-AMS-MML_HTMLorMML"`)}{The querystring
#' used to load MathJax, via [withMathJax()].}
#' \item{shiny.maxRequestSize (defaults to 5MB)}{This is a number which specifies the maximum
#' web request size, which serves as a size limit for file uploads.}
#' \item{shiny.minified (defaults to `TRUE`)}{By default
#' Whether or not to include Shiny's JavaScript as a minified (`shiny.min.js`)
#' or un-minified (`shiny.js`) file. The un-minified version is larger,
#' but can be helpful for development and debugging.}
#' \item{shiny.port (defaults to a random open port)}{A port number that Shiny will listen on. See
#' [runApp()] for more information.}
#' \item{shiny.reactlog (defaults to `FALSE`)}{If `TRUE`, enable logging of reactive events,
#' which can be viewed later with the [reactlogShow()] function.
#' This incurs a substantial performance penalty and should not be used in
#' production.}
#' \item{shiny.sanitize.errors (defaults to `FALSE`)}{If `TRUE`, then normal errors (i.e.
#' errors not wrapped in `safeError`) won't show up in the app; a simple
#' generic error message is printed instead (the error and stack trace printed
#' to the console remain unchanged). If you want to sanitize errors in general, but you DO want a
#' particular error `e` to get displayed to the user, then set this option
#' to `TRUE` and use `stop(safeError(e))` for errors you want the
#' user to see.}
#' \item{shiny.stacktraceoffset (defaults to `TRUE`)}{If `TRUE`, then Shiny's printed stack
#' traces will display srcrefs one line above their usual location. This is
#' an arguably more intuitive arrangement for casual R users, as the name
#' of a function appears next to the srcref where it is defined, rather than
#' where it is currently being called from.}
#' \item{shiny.suppressMissingContextError (defaults to `FALSE`)}{Normally, invoking a reactive
#' outside of a reactive context (or [isolate()]) results in
#' an error. If this is `TRUE`, don't error in these cases. This
#' should only be used for debugging or demonstrations of reactivity at the
#' console.}
#' \item{shiny.testmode (defaults to `FALSE`)}{If `TRUE`, then various features for testing Shiny
#' applications are enabled.}
#' \item{shiny.snapshotsortc (defaults to `FALSE`)}{If `TRUE`, test snapshot keys
#' for \pkg{shinytest} will be sorted consistently using the C locale. Snapshots
#' retrieved by \pkg{shinytest2} will always sort using the C locale.}
#' \item{shiny.trace (defaults to `FALSE`)}{Print messages sent between the R server and the web
#' browser client to the R console. This is useful for debugging. Possible
#' values are `"send"` (only print messages sent to the client),
#' `"recv"` (only print messages received by the server), `TRUE`
#' (print all messages), or `FALSE` (default; don't print any of these
#' messages).}
#' \item{shiny.autoload.r (defaults to `TRUE`)}{If `TRUE`, then the R/
#' of a shiny app will automatically be sourced.}
#' \item{shiny.useragg (defaults to `TRUE`)}{Set to `FALSE` to prevent PNG rendering via the
#' ragg package. See [plotPNG()] for more information.}
#' \item{shiny.usecairo (defaults to `TRUE`)}{Set to `FALSE` to prevent PNG rendering via the
#' Cairo package. See [plotPNG()] for more information.}
#' \item{shiny.devmode (defaults to `NULL`)}{Option to enable Shiny Developer Mode. When set,
#' different default `getOption(key)` values will be returned. See [devmode()] for more details.}
### Not documenting as 'shiny.devmode.verbose' is for niche use only
# ' \item{shiny.devmode.verbose (defaults to `TRUE`)}{If `TRUE`, will display messages printed
# ' about which options are being set. See [devmode()] for more details. }
### (end not documenting 'shiny.devmode.verbose')
### start shiny.client_devmode is primarily for niche, internal shinylive usage
# ' \item{shiny.client_devmode (defaults to `FALSE`)}{If `TRUE`, enables client-
# ' side devmode features. Currently the primary feature is the client-side
# ' error console.}
### end shiny.client_devmode
#' \item{shiny.otel.collect (defaults to `Sys.getenv("SHINY_OTEL_COLLECT",
#' "all")`)}{Determines how Shiny will interact with OpenTelemetry.
#'
#' Supported values:
#' * `"none"` - No Shiny OpenTelemetry tracing.
#' * `"session"` - Adds session start/end spans.
#' * `"reactive_update"` - Spans for any synchronous/asynchronous reactive
#' update. (Includes `"session"` features).
#' * `"reactivity"` - Spans for all reactive expressions and logs for setting
#' reactive vals and values. (Includes `"reactive_update"` features). This
#' option must be set when creating any reactive objects that should record
#' OpenTelemetry spans / logs. See [`withOtelCollect()`] and
#' [`localOtelCollect()`] for ways to set this option locally when creating
#' your reactive expressions.
#' * `"all"` - All Shiny OpenTelemetry tracing. Currently equivalent to
#' `"reactivity"`.
#'
#' This option is useful for debugging and profiling while in production. This
#' option will only be useful if the `otelsdk` package is installed and
#' `otel::is_tracing_enabled()` returns `TRUE`. Please have any OpenTelemetry
#' environment variables set before loading any relevant R packages.
#'
#' To set this option locally within a specific part of your Shiny
#' application, see [`withOtelCollect()`] and [`localOtelCollect()`].}
#' \item{shiny.otel.sanitize.errors (defaults to `TRUE`)}{If `TRUE`, fatal and unhandled errors will be sanitized before being sent to the OpenTelemetry backend. The default value of `TRUE` is set to avoid potentially sending sensitive information to the OpenTelemetry backend. If you want the full error message and stack trace to be sent to the OpenTelemetry backend, set this option to `FALSE` or use `safeError(e)`.}
#' }
#'
#'
#' @section Scoping for `shinyOptions()`:
#'
#' There are three levels of scoping for `shinyOptions()`: global,
#' application, and session.
#'
#' The global option set is available by default. Any calls to
#' `shinyOptions()` and `getShinyOption()` outside of an app will access the
#' global option set.
#'
#' When a Shiny application is run with [runApp()], the global option set is
#' duplicated and the new option set is available at the application level. If
#' options are set from `global.R`, `app.R`, `ui.R`, or `server.R` (but
#' outside of the server function), then the application-level options will be
#' modified.
#'
#' Each time a user session is started, the application-level option set is
#' duplicated, for that session. If the options are set from inside the server
#' function, then they will be scoped to the session.
#'
#' @section Options with `shinyOptions()`:
#'
#' There are a number of global options that affect Shiny's behavior. These
#' can be set globally with `options()` or locally (for a single app) with
#' `shinyOptions()`.
#'
#' \describe{ \item{cache}{A caching object that will be used by
#' [renderCachedPlot()]. If not specified, a [cachem::cache_mem()] will be
#' used.} }
#'
#' @param ... Options to set, with the form `name = value`.
#' @aliases shiny-options
#' @export
shinyOptions <- function(...) {
newOpts <- list2(...)
if (length(newOpts) > 0) {
# If we're within a session, modify at the session level.
session <- getDefaultReactiveDomain()
if (!is.null(session)) {
# Modify session-level-options
session$options <- dropNulls(mergeVectors(session$options, newOpts))
return(invisible(session$options))
}
# If not in a session, but we have a currently running app, modify options
# at the app level.
app_state <- getCurrentAppState()
if (!is.null(app_state)) {
# Modify app-level options
app_state$options <- dropNulls(mergeVectors(app_state$options, newOpts))
return(invisible(app_state$options))
}
# If no currently running app, modify global options and return them.
.globals$options <- dropNulls(mergeVectors(.globals$options, newOpts))
return(invisible(.globals$options))
}
# If not setting any options, just return current option set, visibly.
session <- getDefaultReactiveDomain()
if (!is.null(session)) {
return(session$options)
}
app_state <- getCurrentAppState()
if (!is.null(app_state)) {
return(app_state$options)
}
return(.globals$options)
}
# Get specific shiny options and put them in a list, reset those shiny options,
# and then return the options list. This should be during the creation of a
# shiny app object. This function "consumes" the options when the shinyApp
# object is created, so the options won't affect another app that is created
# later.
#
# ==== Example ====
# shinyOptions(bookmarkStore = 1234)
# # This now returns 1234.
# getShinyOption("bookmarkStore")
#
# # Creating the app captures the bookmarkStore option and clears it.
# s <- shinyApp(
# fluidPage(verbatimTextOutput("txt")),
# function(input, output) {
# output$txt <- renderText(getShinyOption("bookmarkStore"))
# }
# )
#
# # This now returns NULL.
# getShinyOption("bookmarkStore")
#
# When running the app, the app will display "1234"
# runApp(s)
#
# # After quitting the app, this still returns NULL.
# getShinyOption("bookmarkStore")
# ==================
#
# If another app had been created after s was created, but before s was run,
# then it would capture the value of "bookmarkStore" at the time of creation.
captureAppOptions <- function() {
options <- list(
appDir = getwd(),
bookmarkStore = getShinyOption("bookmarkStore")
)
shinyOptions(appDir = NULL, bookmarkStore = NULL)
options
}
# Do the inverse of captureAppOptions. This should be called once the app is
# started.
applyCapturedAppOptions <- function(options) {
if (!is.null(options)) {
do.call(shinyOptions, options)
}
}

44
R/shiny-package.R Normal file
View File

@@ -0,0 +1,44 @@
# See also R/reexports.R
## usethis namespace: start
#' @importFrom lifecycle deprecated is_present
#' @importFrom grDevices dev.set dev.cur
#' @importFrom fastmap fastmap
#' @importFrom promises
#' %...!% %...>%
#' as.promise is.promising is.promise
#' promise_resolve promise_reject
#' hybrid_then
#' with_promise_domain new_promise_domain
#' @importFrom rlang
#' quo enquo enquo0 as_function get_expr get_env new_function enquos
#' eval_tidy expr pairlist2 new_quosure enexpr as_quosure is_quosure inject
#' quo_set_env quo_set_expr quo_get_expr
#' enquos0 zap_srcref %||% is_na
#' is_false list2
#' missing_arg is_missing maybe_missing
#' quo_is_missing fn_fmls<- fn_body fn_body<-
#' check_dots_empty check_dots_unnamed
#' @import htmltools
#' @import httpuv
#' @import xtable
#' @import R6
#' @import mime
## usethis namespace: end
NULL
# It's necessary to Depend on methods so Rscript doesn't fail. It's necessary
# to import(methods) in NAMESPACE so R CMD check doesn't complain. This
# approach isn't foolproof because Rscript -e pkgname::func() doesn't actually
# cause methods to be attached, but it's not a problem for shiny::runApp()
# since we call require(shiny) as part of loading the app.
#' @import methods
NULL
# For usethis::use_release_issue()
release_bullets <- function() {
c(
"Update static imports: `staticimports::import()`"
)
}

3614
R/shiny.R

File diff suppressed because it is too large Load Diff

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