[med-svn] [r-cran-shiny] 01/06: New upstream version 1.0.0+dfsg

Andreas Tille tille at debian.org
Fri Jan 13 09:03:39 UTC 2017


This is an automated email from the git hooks/post-receive script.

tille pushed a commit to branch master
in repository r-cran-shiny.

commit 0da669610a77830948c8f30fc5d4db1a80231335
Author: Andreas Tille <tille at debian.org>
Date:   Fri Jan 13 09:34:12 2017 +0100

    New upstream version 1.0.0+dfsg
---
 DESCRIPTION                        |   8 +-
 MD5                                | 144 ++++++-------
 NAMESPACE                          |   2 +
 NEWS.md                            |  66 ++++++
 R/app.R                            |  13 +-
 R/bootstrap-layout.R               |   2 +
 R/bootstrap.R                      |  70 ++++---
 R/imageutils.R                     |   2 +-
 R/input-date.R                     |   2 +-
 R/input-daterange.R                |   2 +-
 R/input-select.R                   |  52 +++--
 R/input-slider.R                   |   3 +-
 R/input-submit.R                   |  43 +++-
 R/progress.R                       |   1 +
 R/reactives.R                      | 414 +++++++++++++++++++++++++++++++++----
 R/render-plot.R                    |   2 +-
 R/server.R                         |  83 +++++++-
 R/shiny.R                          | 121 ++++++-----
 R/shinyui.R                        |  14 +-
 R/shinywrappers.R                  |   9 +-
 R/test-export.R                    |  13 +-
 R/utils.R                          |  27 ++-
 README.md                          |   4 +
 inst/examples/07_widgets/Readme.md |   2 +-
 inst/examples/07_widgets/server.R  |  24 ++-
 inst/examples/07_widgets/ui.R      |  20 +-
 inst/staticdocs/index.r            |  19 +-
 inst/www/shared/shiny-testmode.js  |   8 +
 inst/www/shared/shiny.css          |  14 ++
 inst/www/shared/shiny.js           |  99 ++++++---
 inst/www/shared/shiny.js.map       |   2 +-
 inst/www/shared/shiny.min.js       |   8 +-
 inst/www/shared/shiny.min.js.map   |   2 +-
 man/addResourcePath.Rd             |   2 +-
 man/builder.Rd                     |   2 +-
 man/dateInput.Rd                   |   2 +-
 man/dateRangeInput.Rd              |   2 +-
 man/debounce.Rd                    | 122 +++++++++++
 man/downloadButton.Rd              |   6 +-
 man/exportTestValues.Rd            |  13 +-
 man/isolate.Rd                     |   2 +-
 man/observeEvent.Rd                | 133 +++++++++---
 man/plotOutput.Rd                  |   2 +-
 man/plotPNG.Rd                     |   2 +-
 man/reactiveTimer.Rd               |   2 +-
 man/reactiveValuesToList.Rd        |   2 +-
 man/renderDataTable.Rd             |   2 +-
 man/renderImage.Rd                 |   1 +
 man/renderPlot.Rd                  |   2 +-
 man/renderPrint.Rd                 |   6 +-
 man/req.Rd                         |   2 +-
 man/runApp.Rd                      |   9 +-
 man/selectInput.Rd                 |  52 +++--
 man/session.Rd                     |  18 +-
 man/shinyApp.Rd                    |  10 +-
 man/sidebarLayout.Rd               |   1 +
 man/sliderInput.Rd                 |   3 +-
 man/splitLayout.Rd                 |   1 +
 man/submitButton.Rd                |  44 +++-
 man/tag.Rd                         |   2 +-
 man/updateSelectInput.Rd           |   9 +-
 man/validate.Rd                    |   1 +
 man/verbatimTextOutput.Rd          |  31 ++-
 man/withProgress.Rd                |   1 +
 tests/testthat/test-reactivity.r   |  80 +++++++
 tests/testthat/test-utils.R        |  25 +++
 66 files changed, 1500 insertions(+), 387 deletions(-)

diff --git a/DESCRIPTION b/DESCRIPTION
index 4a205f7..ade7155 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -1,7 +1,7 @@
 Package: shiny
 Type: Package
 Title: Web Application Framework for R
-Version: 0.14.2
+Version: 1.0.0
 Authors at R: c(
     person("Winston", "Chang", role = c("aut", "cre"), email = "winston at rstudio.com"),
     person("Joe", "Cheng", role = "aut", email = "joe at rstudio.com"),
@@ -63,7 +63,7 @@ Depends: R (>= 3.0.0), methods
 Imports: utils, httpuv (>= 1.3.3), mime (>= 0.3), jsonlite (>= 0.9.16),
         xtable, digest, htmltools (>= 0.3.5), R6 (>= 2.0), sourcetools
 Suggests: datasets, Cairo (>= 1.5-5), testthat, knitr (>= 1.6),
-        markdown, rmarkdown, ggplot2
+        markdown, rmarkdown, ggplot2, magrittr
 URL: http://shiny.rstudio.com
 BugReports: https://github.com/rstudio/shiny/issues
 Collate: 'app.R' 'bookmark-state-local.R' 'stack.R' 'bookmark-state.R'
@@ -85,7 +85,7 @@ Collate: 'app.R' 'bookmark-state-local.R' 'stack.R' 'bookmark-state.R'
         'test-export.R' 'timer.R' 'update-input.R'
 RoxygenNote: 5.0.1
 NeedsCompilation: no
-Packaged: 2016-10-31 18:49:17 UTC; winston
+Packaged: 2017-01-09 19:02:04 UTC; winston
 Author: Winston Chang [aut, cre],
   Joe Cheng [aut],
   JJ Allaire [aut],
@@ -118,4 +118,4 @@ Author: Winston Chang [aut, cre],
   R Core Team [ctb, cph] (tar implementation from R)
 Maintainer: Winston Chang <winston at rstudio.com>
 Repository: CRAN
-Date/Publication: 2016-11-01 19:53:48
+Date/Publication: 2017-01-12 00:49:04
diff --git a/MD5 b/MD5
index 804b3d8..9c468d3 100644
--- a/MD5
+++ b/MD5
@@ -1,12 +1,12 @@
-823fbe7a187e2e0824d280f6da81c479 *DESCRIPTION
+87829d8932c5b2dace9fe3ad4707cbc4 *DESCRIPTION
 3ea3bb190b681ed860efbb72545a0de7 *LICENSE
-b1f4cff3b8aef8d7095a6333427b08a4 *NAMESPACE
-9098adc2c34df34bb7097920e95d49c4 *NEWS.md
-e1025bd539fbcf0c49f528cfacf8a039 *R/app.R
+c2786b9d967c31e423683d011eddb8f8 *NAMESPACE
+a8c3d3c81b17040ac2f297dfb2fc1f45 *NEWS.md
+1162fa76c4fa048c037ac94fe66d17db *R/app.R
 bc5f3a814689aee175d6472b08d45cff *R/bookmark-state-local.R
 126fca9813a088ddac9fa080e26b787c *R/bookmark-state.R
-5e8f345254f57d457071cd822e55018f *R/bootstrap-layout.R
-7bc99d26ae38f43a4323369659505fdc *R/bootstrap.R
+ba54e23962a1b2a5b41ecbccba8170e1 *R/bootstrap-layout.R
+9c66b36bbbea9a49eca6f69202fcb536 *R/bootstrap.R
 d18246ad3e9786fc0a4e7485cbb63eca *R/cache.R
 c930e3553b07208d57cfa4240f2c4183 *R/conditions.R
 776e0c0c4e11677b365eeb18dd7754cc *R/diagnose.R
@@ -18,19 +18,19 @@ d51c0bdc4f4fdce2044436601117c50c *R/html-deps.R
 cb5f6557eed03c0e328c4930ccb2dd5b *R/htmltools.R
 a948ed0c0e57270308f3240987fc91c8 *R/image-interact-opts.R
 937c2a6ff9c2a0becd87929301ee58a9 *R/image-interact.R
-ed97714c80138da2c92742037de3d1e2 *R/imageutils.R
+7389e7f4bc581a5f6bdff941b97929a8 *R/imageutils.R
 7f8f6802204589ab37d06172f5940e53 *R/input-action.R
 65d9ee630649a84e145e6a520ebb9c0d *R/input-checkbox.R
 411b22116c2e1b00417eb67ef6acb720 *R/input-checkboxgroup.R
-6ec947e8d528ccb7bb88585dc02a696a *R/input-date.R
-fd55f04d9aee23afbc23ef0afc2cc4a6 *R/input-daterange.R
+123716afe5ba949701ab8e12e6253eeb *R/input-date.R
+945aa3795285c8128d42c9e057baf5af *R/input-daterange.R
 3ca3eb926ae21ac315f2c964933795c2 *R/input-file.R
 fa92350905d2ebd34c9a5248d8330430 *R/input-numeric.R
 38fe4bab9adcf4e937539409cc9f9bd9 *R/input-password.R
 ac1b06b5184e16f88f346bf76f576de0 *R/input-radiobuttons.R
-4386bfe38973cc881599e8060a6269df *R/input-select.R
-ef4e0199be359a0c65a4dade30f714b5 *R/input-slider.R
-30d1369d77b3e9a87b903a0d9c6bf9eb *R/input-submit.R
+caf808bd1c5eb50b9ae36b0ba6de6a35 *R/input-select.R
+2d48946eba984f4aaabc9b99e17148c5 *R/input-slider.R
+e28536765e141943afb23fc9914257e3 *R/input-submit.R
 b7ae016e7e83bc0b2392b8f0aaa3a1d2 *R/input-text.R
 18117fb36bd141f40a2d428b4ebde85f *R/input-textarea.R
 7eac31e4b672ae2dbfd56eb120bbe253 *R/input-utils.R
@@ -43,28 +43,28 @@ eda55c83ceea5d4c0c370a9d0e917c7b *R/jqueryui.R
 6d0f7f380ee6dc6c3b7db6bb1fa2a6ab *R/modules.R
 9eee0da791854d797abe756b3e557eda *R/notifications.R
 60974a727692bdfa4608c60e8a8e649e *R/priorityqueue.R
-90ecf0bfcbfc88f489f4f993ecbeebaf *R/progress.R
+0bd0e39113f584047eb540053e914377 *R/progress.R
 0933ed20ab79b75e1afbd8123f907120 *R/react.R
 46c87fe2a02ddbc777432437239c121b *R/reactive-domains.R
-5de0d075d8067dd1b26128eb4751ad38 *R/reactives.R
-571d229785679a03f54b088d6a8125d7 *R/render-plot.R
+ce4b0accf871a97427637fd202bde48b *R/reactives.R
+170e0ca3ae345dc244e9d56496ecef80 *R/render-plot.R
 613aabcd6945abb8c642ff84bb1897e0 *R/render-table.R
 f147ee14f642fdcc6912f86d447fe4ef *R/run-url.R
 1b787135fbb2bc3548b7b2e4186cc42a *R/serializers.R
 1efda313aeaaf2e5887511d97bdc1d17 *R/server-input-handlers.R
-b9682d127a556288178f70cc00f22401 *R/server.R
+d7a4b5155639557cae290029ef1b370c *R/server.R
 7413722439f9f9a4b384e3882e29ebb1 *R/shiny-options.R
-1a785b62fdeffd616d51ff8cec29f804 *R/shiny.R
-d604e8a5f2534729bc965473588dfe34 *R/shinyui.R
-503d9ce00c372c98bca516d38ec5e63b *R/shinywrappers.R
+104ca784a8ec4abc21aec77b8d3f1f65 *R/shiny.R
+aaf2d667acb01884f99de0e4c1c62ddf *R/shinyui.R
+f48385e37beb1623fff0362d2d9336a7 *R/shinywrappers.R
 31498a9cc37604d758ec61194c5041a3 *R/showcase.R
 175d3263ed5066754fb83d0894232c9f *R/stack.R
 3f61918de4e7b5aad9fedc41c12dcbfa *R/tar.R
-411796fa2119e7968003ee0f698d03f1 *R/test-export.R
+631abc9b6a1b7bc032bd48344ba5e0d9 *R/test-export.R
 650376bbc07bcff1258d7f2a7a64243f *R/timer.R
 08367ad1506e3c67cb4694651146d43c *R/update-input.R
-71c388235d86af136b05d8b760e20d7d *R/utils.R
-afd2ecf45c8c49ed0c05d214791337ac *README.md
+0ce1eb3f0d02b7d4ee3d63eaf45dadf0 *R/utils.R
+c98c21cb2969035684026a665046b71c *README.md
 13f970fb92cec9836ea297717872f46e *inst/examples/01_hello/DESCRIPTION
 85d0eaa1f8d68da015f0447469489143 *inst/examples/01_hello/Readme.md
 2bff53f9df19d6de6bd04fe0a06c2471 *inst/examples/01_hello/server.R
@@ -90,9 +90,9 @@ f3c2f11e2df951548bdb75cbaf19946a *inst/examples/06_tabsets/Readme.md
 fdab09eb2c2be970e9a92f5762707252 *inst/examples/06_tabsets/server.R
 06feed1ca040463292775e0369c86b42 *inst/examples/06_tabsets/ui.R
 448d49f3c1fd4f84bf6affd027605023 *inst/examples/07_widgets/DESCRIPTION
-09131b23106933be28474b5ce6161224 *inst/examples/07_widgets/Readme.md
-671c7bf33d459552cba1eb0b93faa076 *inst/examples/07_widgets/server.R
-e8d08f013b24e6c471d619fd34184750 *inst/examples/07_widgets/ui.R
+75a55e4fdd6696b324a3b62107abaa75 *inst/examples/07_widgets/Readme.md
+3cc1347c380c0a7c1a2fb6f676f851e8 *inst/examples/07_widgets/server.R
+8e24b0e96dbd95d4be5bc4fb1860ae18 *inst/examples/07_widgets/ui.R
 fc57e0cc1f1689531e8b6d2b308530a6 *inst/examples/08_html/DESCRIPTION
 5554a23aa8a10b633f5fddfe3d159d57 *inst/examples/08_html/Readme.md
 41124d8f6c1a9895786583462d83bee4 *inst/examples/08_html/server.R
@@ -109,7 +109,7 @@ c481010dc652e7a3ab80140f461c0ef2 *inst/examples/11_timer/DESCRIPTION
 f1b063aae380d9463f3739dd60c3e666 *inst/examples/11_timer/Readme.md
 35d7c446405450684e2acef391dae83f *inst/examples/11_timer/server.R
 41f3b74ab8de992e28301ee763af45e5 *inst/examples/11_timer/ui.R
-1343514b5c91235dbc24b47144f4d73e *inst/staticdocs/index.r
+ff5ae7942e0369cefa318637bcbe2e63 *inst/staticdocs/index.r
 cd58550659401cbeb23bc3dad25399b4 *inst/template/default.html
 c6e3068736b084cd7d78d38452ced423 *inst/www-dir/index.html
 fc07eb5cb6354d9070657e2cf0df3658 *inst/www/reactive-graph.html
@@ -212,14 +212,14 @@ ff0781daf30ebf3a9bff3e2c29e3bc36 *inst/www/shared/datepicker/js/locales/bootstra
 8be76c0d0e10acd89d19249e5830d072 *inst/www/shared/datepicker/js/locales/bootstrap-datepicker.vi.min.js
 4a616de93d45ec1d42f9bfab4ea2689e *inst/www/shared/datepicker/js/locales/bootstrap-datepicker.zh-CN.min.js
 7c30c64ca6cebaa76e783c22988f39bc *inst/www/shared/datepicker/js/locales/bootstrap-datepicker.zh-TW.min.js
-b652e3b759188ceaf79182f2fe72ea64 *inst/www/shared/font-awesome/css/font-awesome.css
-4083f5d376eb849a458cc790b53ba080 *inst/www/shared/font-awesome/css/font-awesome.min.css
-5dc41d8fe329a22fa1ee9225571c843e *inst/www/shared/font-awesome/fonts/FontAwesome.otf
-25a32416abee198dd821b0b17a198a8f *inst/www/shared/font-awesome/fonts/fontawesome-webfont.eot
-d7c639084f684d66a1bc66855d193ed8 *inst/www/shared/font-awesome/fonts/fontawesome-webfont.svg
-1dc35d25e61d819a9c357074014867ab *inst/www/shared/font-awesome/fonts/fontawesome-webfont.ttf
-c8ddf1e5e5bf3682bc7bebf30f394148 *inst/www/shared/font-awesome/fonts/fontawesome-webfont.woff
-e6cf7c6ec7c2d6f670ae9d762604cb0b *inst/www/shared/font-awesome/fonts/fontawesome-webfont.woff2
+c495654869785bc3df60216616814ad1 *inst/www/shared/font-awesome/css/font-awesome.css
+269550530cc127b6aa5a35925a7de6ce *inst/www/shared/font-awesome/css/font-awesome.min.css
+0d2717cd5d853e5c765ca032dfd41a4d *inst/www/shared/font-awesome/fonts/FontAwesome.otf
+674f50d287a8c48dc19ba404d20fe713 *inst/www/shared/font-awesome/fonts/fontawesome-webfont.eot
+912ec66d7572ff821749319396470bde *inst/www/shared/font-awesome/fonts/fontawesome-webfont.svg
+b06871f281fee6b241d60582ae9369b9 *inst/www/shared/font-awesome/fonts/fontawesome-webfont.ttf
+fee66e712a8a08eef5805a46892932ad *inst/www/shared/font-awesome/fonts/fontawesome-webfont.woff
+af7ae505a9eed503f8b8e6982036873e *inst/www/shared/font-awesome/fonts/fontawesome-webfont.woff2
 ec39d75cbc4de8171c2f6656a26816a3 *inst/www/shared/highlight/LICENSE
 e095ae120d1b8a9c12d0ebf7e7fa967b *inst/www/shared/highlight/classref.txt
 0b5415083b347c7d5f98b47bcf7e758a *inst/www/shared/highlight/highlight.pack.js
@@ -266,11 +266,12 @@ bd681a8efd2f45628dddf749426dc633 *inst/www/shared/selectize/js/es5-shim.min.js
 146435eeda32f0e12bca8519f0da5ad9 *inst/www/shared/selectize/js/selectize.min.js
 c539894c4785ce273996b9d5376c048e *inst/www/shared/shiny-showcase.css
 226233db9edba2c3503b0df84ef8a1cc *inst/www/shared/shiny-showcase.js
-0a9b375649f25d6201c0867df340f1a1 *inst/www/shared/shiny.css
-dabba789395e9f4d568e47a922c5fde3 *inst/www/shared/shiny.js
-934c7e1052307cea2239a0d1f5f0682b *inst/www/shared/shiny.js.map
-d07ead81941c0093ec4435ffcfc45ca5 *inst/www/shared/shiny.min.js
-1400f8989bd7e5e183c8f42d1d2198f7 *inst/www/shared/shiny.min.js.map
+b4db4844f8e15ea3da7bea9749b9b925 *inst/www/shared/shiny-testmode.js
+12879788a4d199155c6187779b1e5605 *inst/www/shared/shiny.css
+884d6152374c3a67f7de78c044133014 *inst/www/shared/shiny.js
+e1aae0c73e45c0744bd033a41fcd5e68 *inst/www/shared/shiny.js.map
+98b57c0172430410b1398f25893d36e8 *inst/www/shared/shiny.min.js
+00e742d4774bcf3f9ed3f55726a0d36c *inst/www/shared/shiny.min.js.map
 d42bccda0accb4e937f79e5bd9540643 *inst/www/shared/showdown/compressed/showdown.js
 ae18a8f49f1a446ca1772447b95a99d0 *inst/www/shared/showdown/license.txt
 e192e62c348b4dc09fd3d9f32cd558c3 *inst/www/shared/showdown/src/showdown.js
@@ -280,14 +281,14 @@ c272996ea1fd62ed42113b3c4a9c06e6 *man/NS.Rd
 6b695cf8aa4e2e2f9000350dfa35ee63 *man/Progress.Rd
 9b645260993b8a9dba0e1de99dfeb47d *man/absolutePanel.Rd
 0983de4f0d434fb88e8a2179dee83ab2 *man/actionButton.Rd
-37baaab9d4b9159fd70d1a507391e447 *man/addResourcePath.Rd
+b5801edc866cc52676a891edda00df68 *man/addResourcePath.Rd
 f23a4205ab93ffde15bd44ba1404ea5d *man/applyInputHandlers.Rd
 d38b6b09e59d71964cd040c0b0d063a1 *man/bookmarkButton.Rd
 5c7e3991f2c6c68b4376d9d03c86f682 *man/bootstrapLib.Rd
 0ce227618e7e1c463a235374c8bdfa9d *man/bootstrapPage.Rd
 d1641fa3516d97c0890cca51a88e2586 *man/brushOpts.Rd
 a64dfa56528185a338efd8438e97ac3f *man/brushedPoints.Rd
-22a8bcc9aa7da08a6ca8bef449257da1 *man/builder.Rd
+8953ddcb594cf24180e4ea1a563e5f0b *man/builder.Rd
 9e712890a20931b166ec8a82545deae7 *man/callModule.Rd
 df6def08194f9c22e0b70afd57ed5689 *man/checkboxGroupInput.Rd
 57c8638b00ed42a76290d99bb2ab86e3 *man/checkboxInput.Rd
@@ -295,14 +296,15 @@ df6def08194f9c22e0b70afd57ed5689 *man/checkboxGroupInput.Rd
 9bacf8c019a10445b779a3fc0c64269e *man/column.Rd
 6c9870829d5833a37428af1cfd010461 *man/conditionalPanel.Rd
 f3c0810329c410cc843f5c6e9d440e16 *man/createWebDependency.Rd
-071d37b1e519fd797449506703c769cb *man/dateInput.Rd
-46978f653eecb1c32a39e18adfdb5d32 *man/dateRangeInput.Rd
+d8b80674884b9676da8c6523955628fd *man/dateInput.Rd
+82007d8ad0c65de77c28fa624d921af9 *man/dateRangeInput.Rd
 a941504ef1e6235ce5161b26cd207543 *man/dblclickOpts.Rd
+304376a72a996303e354d717884677b2 *man/debounce.Rd
 2d9b353d16b677b55a58ff0cff020541 *man/domains.Rd
-481fa1943f6d4353eeed023a75521446 *man/downloadButton.Rd
+088e4bb6aa4558a58dd8fecf40847e72 *man/downloadButton.Rd
 b1b0171792a1332a9fc950fc05feea3c *man/downloadHandler.Rd
 1ad2440a33bd4cfb1abed64535c81bb6 *man/enableBookmarking.Rd
-32cd02cd61aa1aca2911eb8a87bf9009 *man/exportTestValues.Rd
+4a14be9b31878c6e3ea36a5d9ef1c1bb *man/exportTestValues.Rd
 a285c035ff015a2575f8219c4ad6aa6d *man/exprToFunction.Rd
 6baa248b78954215db322d3853be3cbd *man/fileInput.Rd
 7e7ce1a49c339b757eda2facaecf3292 *man/fillPage.Rd
@@ -323,7 +325,7 @@ b6db1c34fc97f2fa8fb24f7d2713aec5 *man/htmlTemplate.Rd
 388595ea019cb50b911585a0e83385ab *man/installExprFunction.Rd
 e076609c816c0988da5c2be9198fc820 *man/invalidateLater.Rd
 c4df81c50b02bbab02a021451f779900 *man/is.reactivevalues.Rd
-1f36b2c405bd2c6eff6780b345030f34 *man/isolate.Rd
+d90537fdcf9d3a8e70606e24194b80ec *man/isolate.Rd
 e6422e37aa4e65a851ea929c44537daa *man/knitr_methods.Rd
 0cef753d073f90ea736a0b259cb53c3f *man/knitr_methods_htmltools.Rd
 cbc1ae1138599f3156f30fea5d91a148 *man/mainPanel.Rd
@@ -337,15 +339,15 @@ cbc1ae1138599f3156f30fea5d91a148 *man/mainPanel.Rd
 c5093ba7b905be444ec88e92c96601fd *man/nearPoints.Rd
 6425976695c5876714e9aafb25dd4e56 *man/numericInput.Rd
 502664a517e3252a2ecd47ffd12657b7 *man/observe.Rd
-6b39b917fef923fa748fad5ed1819a14 *man/observeEvent.Rd
+c33f35b9295bfd7a3c38fb1823ee53cf *man/observeEvent.Rd
 775a1e9289ca94c74b5bde1cb7570bec *man/onBookmark.Rd
 a6066c56c39f8ef669f6afa7b0d14665 *man/onFlush.Rd
 5f97903060489ca6bf90931b1efd434c *man/outputOptions.Rd
 64956bda426d937ece36462ce7d64664 *man/pageWithSidebar.Rd
 32188a9e53789dca0e17a0956f2c5e0f *man/parseQueryString.Rd
 81fe1abb4ed16abcfb3cb33051438adc *man/passwordInput.Rd
-08dc2bd952ad061b03ef87da4be22ed6 *man/plotOutput.Rd
-2aeaf22fa666cd0c5415d806365e138b *man/plotPNG.Rd
+fe835df646692ac7eadc7dc0d36da99a *man/plotOutput.Rd
+ea0107429a4eef996a2006adccd3846f *man/plotPNG.Rd
 629ecf8d44e9d10b323a317b2e424a17 *man/radioButtons.Rd
 c837729b4fc389cd68abc41bc254053c *man/reactive.Rd
 4734037e317cbe3fe6aab349f1802a22 *man/reactiveFileReader.Rd
@@ -354,35 +356,35 @@ c837729b4fc389cd68abc41bc254053c *man/reactive.Rd
 ba03335e953884bb60bce143cff17a84 *man/reactivePrint.Rd
 69ba7fcda401f11bb6a1297d9cbb31a5 *man/reactiveTable.Rd
 b09c00b93df747fe2e0e63ba438d68e9 *man/reactiveText.Rd
-c40a6528c40e5b36cb775e783f1fe6d7 *man/reactiveTimer.Rd
+39abeb3429c3509befab9538f8effed1 *man/reactiveTimer.Rd
 3c02e74514e9a44e0b6a06fb21ef7c02 *man/reactiveUI.Rd
 c84a1d66e76e48ccb58d2ba45abcdb74 *man/reactiveValues.Rd
-cdd30631426dd57b2ec76e574b3fac15 *man/reactiveValuesToList.Rd
+5a3d5ff42b6ffdadd689873b61f30e08 *man/reactiveValuesToList.Rd
 d1197c9ae61dea32d0c572b007a6d977 *man/registerInputHandler.Rd
 5acd414830d166e09a322fb79abe8b8d *man/removeInputHandler.Rd
 e165d130c98a3a604eab4bdf2fece4c3 *man/removeUI.Rd
-481e593983a4b12b58999b9edc701e5d *man/renderDataTable.Rd
-68a42ab42b758dd231c13b45e401c7c0 *man/renderImage.Rd
-56df2054d0d46dbdcd21871890b4f942 *man/renderPlot.Rd
-5033ea616a18927a45a3624e4c0d9e87 *man/renderPrint.Rd
+c2f3efe5e160871890a8f35f5ca32a0c *man/renderDataTable.Rd
+3cec290a138279854e41bbabbed01e6c *man/renderImage.Rd
+07f9b12328d89985c84b2e4e875cfc00 *man/renderPlot.Rd
+411b9f59f26c4148ab98a9a809a80ac1 *man/renderPrint.Rd
 a7f657cc7de1d2b53391731fb4c1701a *man/renderTable.Rd
 9713fe1dff93b89d8400a76528373143 *man/renderText.Rd
 cb63e3d50cf01f80de1b720febe4e32b *man/renderUI.Rd
 28c14b86847bad36ea6b4a01b0a9d314 *man/repeatable.Rd
-696d09d4d1eb49a609b25e5cc79675bc *man/req.Rd
+aa771cdab26c33133cf361b289ba503a *man/req.Rd
 f0670deffbe1f77380892ca1f5a8b37e *man/restoreInput.Rd
-d47f1a9e121c4bd2bb41034c8b96d50f *man/runApp.Rd
+f320b68865d50839f115856139666c70 *man/runApp.Rd
 6e500ae957bc388d27e14b5bc1851b68 *man/runExample.Rd
 1524263164e53933bc07e3eb968a113a *man/runGadget.Rd
 a26b63c9973d07c18281d758bfac1d28 *man/runUrl.Rd
 fc0e60e0d97dcc6fca79678b8b3ef925 *man/safeError.Rd
-68b05175fa88a32c763810437d72417b *man/selectInput.Rd
+f32c4c17d259eb6d06c32b5642cb3f81 *man/selectInput.Rd
 312354ec69a77cc6f25c682811203170 *man/serverInfo.Rd
-c540d7b2961aa2a6eb3738244643fc33 *man/session.Rd
+5906c1d9bc243cf3f1283342ed8dbb1b *man/session.Rd
 2da0c9c542da2c542c440713e9171468 *man/setBookmarkExclude.Rd
 1a4118e80bcdf4086c793bcf91ca2a86 *man/shiny-options.Rd
 30cc9e53fee6282852effbdad93a696e *man/shiny-package.Rd
-56f59d6daedc6e547314478d45918c78 *man/shinyApp.Rd
+dce9964b142672d221649101383c418c *man/shinyApp.Rd
 d5ec7a3b8a327bcd55172015ed341e81 *man/shinyDeprecated.Rd
 20198c4520f4383415916da04d79d716 *man/shinyOptions.Rd
 0aaa8b2fd73d0f2505700a4433435e65 *man/shinyServer.Rd
@@ -391,19 +393,19 @@ d5ec7a3b8a327bcd55172015ed341e81 *man/shinyDeprecated.Rd
 5446bebae929fd941f5bd6cd7c0e5a22 *man/showModal.Rd
 c4d7c2453fbdabcf687b871e6af4b300 *man/showNotification.Rd
 0b835143915d5213dad9a0c0a2d03b52 *man/showReactLog.Rd
-095b29965d301213c8a481c898072b82 *man/sidebarLayout.Rd
+e7e92a912dc3b56c30f85f5436bc9036 *man/sidebarLayout.Rd
 ed31f0a3d0e3457d9d3f1b22a6d1d4a7 *man/sidebarPanel.Rd
 025c15a6e3be95777dda20d2559a7497 *man/singleton.Rd
-663fa0ff7955d113c0635dca8dd6e33b *man/sliderInput.Rd
-048dd9ea4438d2079ec417608bedd1d5 *man/splitLayout.Rd
+e59447049feaabd35597c00756fd4874 *man/sliderInput.Rd
+be0642fdffe02e7ec8cd3ee006a576ed *man/splitLayout.Rd
 f1dbb30aeb7032894d8af89caddf1e8f *man/stacktrace.Rd
 029e949411bc4c0aa9658e32f7319aaa *man/stopApp.Rd
-e4d3181367e06d0d7a5d3ea8010facb7 *man/submitButton.Rd
+cd1d9f648c339ff3f03e047dd63832bf *man/submitButton.Rd
 d32cc8ebf7ebce324a0983102a0a6de9 *man/suppressDependencies.Rd
 1b43b425f3cc300e5624e01f80802af7 *man/tabPanel.Rd
 f98f806c6a8d5837242934318e4c7d77 *man/tableOutput.Rd
 6fdfc632cfd96a91746d5cc168359b68 *man/tabsetPanel.Rd
-5c7c7daf31e2492fb5a21cfae8c0be1d *man/tag.Rd
+df812031fdc7a63233007259573230e5 *man/tag.Rd
 790855f0657c91551f3c288d256bed1a *man/textAreaInput.Rd
 f75162e96f0cb3df7bd385cb0b600332 *man/textInput.Rd
 f53a4f566d6a81d6b578f386684cc50d *man/textOutput.Rd
@@ -416,20 +418,20 @@ db1b0f13650b95f71793ae1bd094de40 *man/updateCheckboxInput.Rd
 6fc25fe24ace006d2d472e0dca0d7140 *man/updateNumericInput.Rd
 dd9d5a3e653c5eb24914fc0c87d5279e *man/updateQueryString.Rd
 ffb9ee1fbcd72ae2c05f28d248bf9808 *man/updateRadioButtons.Rd
-8aae9d3d8241ca089b73b3bdc82d3aea *man/updateSelectInput.Rd
+599b08675ceb6a0b94bcf38b4c91136d *man/updateSelectInput.Rd
 9a3a91b1779425416a020aa2face286f *man/updateSliderInput.Rd
 c3aa33fcc31510f39c9f08b003bd37df *man/updateTabsetPanel.Rd
 e6af9d2a830c2556201347e1c76f1b2a *man/updateTextAreaInput.Rd
 546a3d58223af5c48c287440c29013a0 *man/updateTextInput.Rd
 f4e84efeebbd28c7ef8646401ec5af6d *man/urlModal.Rd
-6d91e1b7bb98814c01bd90ed44ef9520 *man/validate.Rd
+f7500412dc367e7b74b2c74b3ddfd1e9 *man/validate.Rd
 21bdae51050d3832ab46550659947bd0 *man/validateCssUnit.Rd
-489c6b8cdebd85e26d36d0f893efae53 *man/verbatimTextOutput.Rd
+aa7ae49457a120d4b986aac02630ce80 *man/verbatimTextOutput.Rd
 2b7dbd754c2b127a4c14019e27d904e5 *man/verticalLayout.Rd
 ca965f9478634d57819776471e7df8c6 *man/viewer.Rd
 29fc1b3faa440f561c6b78d02d6ccbe4 *man/wellPanel.Rd
 a12068140cb7a01bdf11ef6168e328f3 *man/withMathJax.Rd
-8cebd842703578396fe5df3681c91152 *man/withProgress.Rd
+18329794b5438873183e0d75e4448de9 *man/withProgress.Rd
 0138d018b7594f66e96ec66f82763758 *man/withTags.Rd
 d44a15e0a188bccb87dcab4fefdc872e *tests/test-all.R
 89f3a210025c4dee6c10f4b357eefbbf *tests/test-encoding/01-symbols/app.R
@@ -445,7 +447,7 @@ dbe84e866824cfdf042f6d92729188cf *tests/testthat/test-gc.r
 f9ee5309105f8f0c9743572e7409336f *tests/testthat/test-modules.R
 f3f69a0a024170377ac09de1c788ba12 *tests/testthat/test-options.R
 093c126111fb2a656665464f4238b2cd *tests/testthat/test-plot-coordmap.R
-d05aec42cdf4064b0f409927812285cc *tests/testthat/test-reactivity.r
+1f7e7402d887e941ba458148c3827a46 *tests/testthat/test-reactivity.r
 bc84dab9f44f9079568a0c2e4fc83884 *tests/testthat/test-stack.R
 5c2dfe371178ff9274169cde1bc7e5f3 *tests/testthat/test-stacks.R
 fbace4e45a8036a85bdd983da02b330c *tests/testthat/test-staticdocs.R
@@ -455,4 +457,4 @@ fe4b5516a083f1c9ede932e37b27e34c *tests/testthat/test-timer.R
 c59f5d981a17ad5c7e93f367abb45a1b *tests/testthat/test-ui.R
 77572f6e0036925f9c37a120d93beba7 *tests/testthat/test-update-input.R
 10bf6c1026eb046245839061ea91494b *tests/testthat/test-url.R
-b5978ec26571bd4116d061b90994a70d *tests/testthat/test-utils.R
+a548f446b80e3790a5874aefaf802eed *tests/testthat/test-utils.R
diff --git a/NAMESPACE b/NAMESPACE
index f088a36..a9e62b7 100644
--- a/NAMESPACE
+++ b/NAMESPACE
@@ -61,6 +61,7 @@ export(dataTableOutput)
 export(dateInput)
 export(dateRangeInput)
 export(dblclickOpts)
+export(debounce)
 export(dialogViewer)
 export(div)
 export(downloadButton)
@@ -229,6 +230,7 @@ export(tags)
 export(textAreaInput)
 export(textInput)
 export(textOutput)
+export(throttle)
 export(titlePanel)
 export(uiOutput)
 export(updateActionButton)
diff --git a/NEWS.md b/NEWS.md
index c239736..79215b6 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -1,3 +1,69 @@
+shiny 1.0.0
+===========
+
+Shiny has reached a milestone: version 1.0.0! In the last year, we've added two major features that we considered essential for a 1.0.0 release: bookmarking, and support for testing Shiny applications. As usual, this version of Shiny also includes many minor features and bug fixes.
+
+Here are some highlights from this release. For more details, see the full changelog below.
+
+## Support for testing Shiny applications
+
+Shiny now supports automated testing of applications, with the [shinytest](https://github.com/MangoTheCat/shinytest) package. Shinytest has not yet been released on CRAN, but will be soon. ([#18](https://github.com/rstudio/shiny/issues/18), [#1464](https://github.com/rstudio/shiny/pull/1464))
+
+## Debounce/throttle reactives
+
+Now there's an official way to slow down reactive values and expressions that invalidate too quickly. Pass a reactive expression to the new `debounce` or `throttle` function, and get back a modified reactive expression that doesn't invalidate as often. ([#1510](https://github.com/rstudio/shiny/pull/1510))
+
+## Full changelog
+
+### Breaking changes
+
+* Added a new `placeholder` argument to `verbatimTextOutput()`. The default is `FALSE`, which means that, if there is no content for this output, no representation of this slot will be made in the UI. Previsouly, even if there was no content, you'd see an empty rectangle in the UI that served as a placeholder. You can set `placeholder = TRUE` to revert back to that look. ([#1480](https://github.com/rstudio/shiny/pull/1480))
+
+### New features
+
+* Added support for testing Shiny applications with the shinytest package. ([#18](https://github.com/rstudio/shiny/issues/18), [#1464](https://github.com/rstudio/shiny/pull/1464))
+
+* Added `debounce` and `throttle` functions, to control the rate at which reactive values and expressions invalidate. ([#1510](https://github.com/rstudio/shiny/pull/1510))
+
+### Minor new features and improvements
+
+* Addressed [#1486](https://github.com/rstudio/shiny/issues/1486) by adding a new argument to `observeEvent` and `eventReactive`, called `ignoreInit` (defaults to `FALSE` for backwards compatibility). When set to `TRUE`, the action (i.e. the second argument: `handlerExpr` and `valueExpr`, respectively) will not be triggered when the observer/reactive is first created/initialized. In other words, `ignoreInit = TRUE` ensures that the `observeEvent` (or `eventReactive`) is *never* run right [...]
+    
+* Added a new argument to `observeEvent` called `once`. When set to `TRUE`, it results in the observer being destroyed (stop observing) after the first time that `handlerExpr` is run (i.e. `once = TRUE` guarantees that the observer only runs, at most, once). For more info, see the documentation (`?observeEvent`). ([#1494](https://github.com/rstudio/shiny/pull/1494))
+
+* Addressed [#1358](https://github.com/rstudio/shiny/issues/1358): more informative error message when calling `runApp()` inside of an app's app.R (or inside ui.R or server.R). ([#1482](https://github.com/rstudio/shiny/pull/1482))
+
+* Added a more descriptive JS warning for `insertUI()` when the selector argument does not match anything in DOM. ([#1488](https://github.com/rstudio/shiny/pull/1488))
+
+* Added support for injecting JavaScript code when the `shiny.testmode` option is set to `TRUE`. This makes it possible to record test events interactively. ([#1464](https://github.com/rstudio/shiny/pull/1464))
+
+* Added ability through arguments to the `a` tag function called inside `downloadButton()` and `downloadLink()`. Closes [#986](https://github.com/rstudio/shiny/issues/986). ([#1492](https://github.com/rstudio/shiny/pulls/1492))
+
+* Implemented [#1512](https://github.com/rstudio/shiny/issues/1512): added a `userData` environment to `session`, for storing arbitrary session-related variables. Generally, session-scoped variables are created just by declaring normal variables that are local to the Shiny server function, but `session$userData` may be more convenient for some advanced scenarios. ([#1513](https://github.com/rstudio/shiny/pull/1513))
+
+* Relaxed naming requirements for `addResourcePath()` (the first character no longer needs to be a letter). ([#1529](https://github.com/rstudio/shiny/pull/1529))
+
+### Bug fixes
+
+* Fixed [#969](https://github.com/rstudio/shiny/issues/969): allow navbarPage's `fluid` param to control both containers. ([#1481](https://github.com/rstudio/shiny/pull/1481))
+
+* Fixed [#1438](https://github.com/rstudio/shiny/issues/1438): `unbindAll()` should not be called when inserting content with `insertUI()` ([#1449](https://github.com/rstudio/shiny/pull/1449))
+
+* Fixed bug causing `<meta>` tags associated with HTML dependencies of Shiny R Markdown files to be rendered incorrectly. ([#1463](https://github.com/rstudio/shiny/pull/1463))
+
+* Fixed [#1359](https://github.com/rstudio/shiny/issues/1359): `shinyApp()` options argument ignored when passed to `runApp()`. ([#1483](https://github.com/rstudio/shiny/pull/1483))
+
+* Fixed [#117](https://github.com/rstudio/shiny/issues/117): Reactive expressions now release references to cached values as soon as they are invalidated, potentially making those cached values eligible for garbage collection sooner. Previously, this would not occur until the next cached value was calculated and stored. ([#1504](https://github.com/rstudio/shiny/pull/1504/files))
+
+* Fixed [#1013](https://github.com/rstudio/shiny/issues/1013): `flushReact` should be called after app loads. Observers set up outside of server functions were not running until after the first user connects. ([#1503](https://github.com/rstudio/shiny/pull/1503))
+
+* Fixed [#1453](https://github.com/rstudio/shiny/issues/1453): When using a modal dialog with `easyClose=TRUE` in a Shiny gadget, pressing Esc would close both the modal and the gadget. Now pressing Esc only closes the modal. ([#1523](https://github.com/rstudio/shiny/pull/1523))
+
+### Library updates
+
+* Updated to Font Awesome 4.7.0.
+
+
 shiny 0.14.2
 ============
 
diff --git a/R/app.R b/R/app.R
index 35290e5..4857e71 100644
--- a/R/app.R
+++ b/R/app.R
@@ -20,9 +20,11 @@
 #' @param onStart A function that will be called before the app is actually run.
 #'   This is only needed for \code{shinyAppObj}, since in the \code{shinyAppDir}
 #'   case, a \code{global.R} file can be used for this purpose.
-#' @param options Named options that should be passed to the `runApp` call. You
-#'   can also specify \code{width} and \code{height} parameters which provide a
-#'   hint to the embedding environment about the ideal height/width for the app.
+#' @param options Named options that should be passed to the \code{runApp} call
+#'   (these can be any of the following: "port", "launch.browser", "host", "quiet",
+#'   "display.mode" and "test.mode"). You can also specify \code{width} and
+#'   \code{height} parameters which provide a hint to the embedding environment
+#'   about the ideal height/width for the app.
 #' @param uiPattern A regular expression that will be applied to each \code{GET}
 #'   request to determine whether the \code{ui} should be used to handle the
 #'   request. Note that the entire request path must match the regular
@@ -39,6 +41,8 @@
 #' @examples
 #' ## Only run this example in interactive R sessions
 #' if (interactive()) {
+#'   options(device.ask.default = FALSE)
+#'
 #'   shinyApp(
 #'     ui = fluidPage(
 #'       numericInput("n", "n", 1),
@@ -373,7 +377,8 @@ is.shiny.appobj <- function(x) {
 print.shiny.appobj <- function(x, ...) {
   opts <- x$options %OR% list()
   opts <- opts[names(opts) %in%
-      c("port", "launch.browser", "host", "quiet", "display.mode")]
+      c("port", "launch.browser", "host", "quiet",
+        "display.mode", "test.mode")]
 
   args <- c(list(x), opts)
 
diff --git a/R/bootstrap-layout.R b/R/bootstrap-layout.R
index 9588af1..835a2d8 100644
--- a/R/bootstrap-layout.R
+++ b/R/bootstrap-layout.R
@@ -277,6 +277,7 @@ titlePanel <- function(title, windowTitle=title) {
 #' @examples
 #' ## Only run examples in interactive R sessions
 #' if (interactive()) {
+#' options(device.ask.default = FALSE)
 #'
 #' # Define UI
 #' ui <- fluidPage(
@@ -442,6 +443,7 @@ inputPanel <- function(...) {
 #' @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) {
diff --git a/R/bootstrap.R b/R/bootstrap.R
index 07e5e12..1cf1265 100644
--- a/R/bootstrap.R
+++ b/R/bootstrap.R
@@ -342,10 +342,18 @@ navbarPage <- function(title,
   tabs <- list(...)
   tabset <- buildTabset(tabs, "nav navbar-nav", NULL, id, selected)
 
+  # function to return plain or fluid class name
+  className <- function(name) {
+    if (fluid)
+      paste(name, "-fluid", sep="")
+    else
+      name
+  }
+
   # built the container div dynamically to support optional collapsibility
   if (collapsible) {
     navId <- paste("navbar-collapse-", p_randomInt(1000, 10000), sep="")
-    containerDiv <- div(class="container",
+    containerDiv <- div(class=className("container"),
       div(class="navbar-header",
         tags$button(type="button", class="navbar-toggle collapsed",
           `data-toggle`="collapse", `data-target`=paste0("#", navId),
@@ -359,7 +367,7 @@ navbarPage <- function(title,
       div(class="navbar-collapse collapse", id=navId, tabset$navList)
     )
   } else {
-    containerDiv <- div(class="container",
+    containerDiv <- div(class=className("container"),
       div(class="navbar-header",
         span(class="navbar-brand", pageTitle)
       ),
@@ -367,14 +375,6 @@ navbarPage <- function(title,
     )
   }
 
-  # function to return plain or fluid class name
-  className <- function(name) {
-    if (fluid)
-      paste(name, "-fluid", sep="")
-    else
-      name
-  }
-
   # build the main tab content div
   contentDiv <- div(class=className("container"))
   if (!is.null(header))
@@ -935,21 +935,34 @@ textOutput <- function(outputId, container = if (inline) span else div, inline =
 #' Render a reactive output variable as verbatim text within an
 #' application page. The text will be included within an HTML \code{pre} tag.
 #' @param outputId output variable to read the value from
+#' @param placeholder if the output is empty or \code{NULL}, should an empty
+#'   rectangle be displayed to serve as a placeholder? (does not affect
+#'   behavior when the the output in nonempty)
 #' @return A verbatim text output element that can be included in a panel
 #' @details Text is HTML-escaped prior to rendering. This element is often used
-#' with the \link{renderPrint} function to preserve fixed-width formatting
-#' of printed objects.
+#'   with the \link{renderPrint} function to preserve fixed-width formatting
+#'   of printed objects.
 #' @examples
-#' mainPanel(
-#'   h4("Summary"),
-#'   verbatimTextOutput("summary"),
-#'
-#'   h4("Observations"),
-#'   tableOutput("view")
-#' )
+#' ## Only run this example in interactive R sessions
+#' if (interactive()) {
+#'   shinyApp(
+#'     ui = basicPage(
+#'       textInput("txt", "Enter the text to display below:"),
+#'       verbatimTextOutput("default"),
+#'       verbatimTextOutput("placeholder", placeholder = TRUE)
+#'     ),
+#'     server = function(input, output) {
+#'       output$default <- renderText({ input$txt })
+#'       output$placeholder <- renderText({ input$txt })
+#'     }
+#'   )
+#' }
 #' @export
-verbatimTextOutput <- function(outputId) {
-  textOutput(outputId, container = pre)
+verbatimTextOutput <- function(outputId, placeholder = FALSE) {
+  pre(id = outputId,
+      class = paste(c("shiny-text-output", if (!placeholder) "noplaceholder"),
+                    collapse = " ")
+      )
 }
 
 
@@ -1123,7 +1136,7 @@ imageOutput <- function(outputId, width = "100%", height="400px",
 #'   same \code{id} to disappear.
 #' @inheritParams textOutput
 #' @note The arguments \code{clickId} and \code{hoverId} only work for R base
-#'   graphics (see the \pkg{\link{graphics}} package). They do not work for
+#'   graphics (see the \pkg{\link[graphics:graphics-package]{graphics}} package). They do not work for
 #'   \pkg{\link[grid:grid-package]{grid}}-based graphics, such as \pkg{ggplot2},
 #'   \pkg{lattice}, and so on.
 #'
@@ -1421,6 +1434,7 @@ uiOutput <- htmlOutput
 #'   is assigned to.
 #' @param label The label that should appear on the button.
 #' @param class Additional CSS classes to apply to the tag, if any.
+#' @param ... Other arguments to pass to the container tag function.
 #'
 #' @examples
 #' \dontrun{
@@ -1443,23 +1457,25 @@ uiOutput <- htmlOutput
 #' @export
 downloadButton <- function(outputId,
                            label="Download",
-                           class=NULL) {
+                           class=NULL, ...) {
   aTag <- tags$a(id=outputId,
                  class=paste('btn btn-default shiny-download-link', class),
                  href='',
                  target='_blank',
+                 download=NA,
                  icon("download"),
-                 label)
+                 label, ...)
 }
 
 #' @rdname downloadButton
 #' @export
-downloadLink <- function(outputId, label="Download", class=NULL) {
+downloadLink <- function(outputId, label="Download", class=NULL, ...) {
   tags$a(id=outputId,
          class=paste(c('shiny-download-link', class), collapse=" "),
          href='',
          target='_blank',
-         label)
+         download=NA,
+         label, ...)
 }
 
 
@@ -1527,7 +1543,7 @@ icon <- function(name, class = NULL, lib = "font-awesome") {
   # font-awesome needs an additional dependency (glyphicon is in bootstrap)
   if (lib == "font-awesome") {
     htmlDependencies(iconTag) <- htmlDependency(
-      "font-awesome", "4.6.3", c(href="shared/font-awesome"),
+      "font-awesome", "4.7.0", c(href="shared/font-awesome"),
       stylesheet = "css/font-awesome.min.css"
     )
   }
diff --git a/R/imageutils.R b/R/imageutils.R
index 376809d..88a923c 100644
--- a/R/imageutils.R
+++ b/R/imageutils.R
@@ -21,7 +21,7 @@
 #' @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
+#'   \code{\link[grDevices]{png}}. 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.
diff --git a/R/input-date.R b/R/input-date.R
index 9a5c501..2c088a0 100644
--- a/R/input-date.R
+++ b/R/input-date.R
@@ -10,7 +10,7 @@
 #'   \item \code{yy} Year without century (12)
 #'   \item \code{yyyy} Year with century (2012)
 #'   \item \code{mm} Month number, with leading zero (01-12)
-#'   \item \code{m} Month number, without leading zero (01-12)
+#'   \item \code{m} Month number, without leading zero (1-12)
 #'   \item \code{M} Abbreviated month name
 #'   \item \code{MM} Full month name
 #'   \item \code{dd} Day of month with leading zero
diff --git a/R/input-daterange.R b/R/input-daterange.R
index 0b9a7c5..4026aca 100644
--- a/R/input-daterange.R
+++ b/R/input-daterange.R
@@ -10,7 +10,7 @@
 #'   \item \code{yy} Year without century (12)
 #'   \item \code{yyyy} Year with century (2012)
 #'   \item \code{mm} Month number, with leading zero (01-12)
-#'   \item \code{m} Month number, without leading zero (01-12)
+#'   \item \code{m} Month number, without leading zero (1-12)
 #'   \item \code{M} Abbreviated month name
 #'   \item \code{MM} Full month name
 #'   \item \code{dd} Day of month with leading zero
diff --git a/R/input-select.R b/R/input-select.R
index 23e2201..fb04f47 100644
--- a/R/input-select.R
+++ b/R/input-select.R
@@ -15,7 +15,12 @@
 #'
 #' @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.
+#'   named, then that name rather than the value is displayed to the user.
+#'   This can also be a named list whose elements are (either named or
+#'   unnamed) lists or vectors. If this is the case, the outermost names
+#'   will be used as the "optgroup" label for the elements in the respective
+#'   sublist. This allows you to group and label similar choices. See the
+#'   example section for a small demo of this feature.
 #' @param selected The initially selected value (or multiple values if
 #'   \code{multiple = TRUE}). If not specified then defaults to the first value
 #'   for single-select lists and no values for multiple select lists.
@@ -34,21 +39,38 @@
 #' ## Only run examples in interactive R sessions
 #' if (interactive()) {
 #'
-#' ui <- fluidPage(
-#'   selectInput("variable", "Variable:",
-#'               c("Cylinders" = "cyl",
-#'                 "Transmission" = "am",
-#'                 "Gears" = "gear")),
-#'   tableOutput("data")
+#' # 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)
+#'   }
 #' )
 #'
-#' server <- function(input, output) {
-#'   output$data <- renderTable({
-#'     mtcars[, c("mpg", input$variable), drop = FALSE]
-#'   }, rownames = TRUE)
-#' }
-#'
-#' shinyApp(ui, server)
+#' # demoing optgroup support in the `choices` arg
+#' shinyApp(
+#'   ui = fluidPage(
+#'     selectInput("state", "Choose a state:",
+#'       list(`East Coast` = c("NY", "NJ", "CT"),
+#'            `West Coast` = c("WA", "OR", "CA"),
+#'            `Midwest` = c("MN", "WI", "IA"))
+#'     ),
+#'     textOutput("result")
+#'   ),
+#'   server = function(input, output) {
+#'     output$result <- renderText({
+#'       paste("You chose", input$state)
+#'     })
+#'   }
+#' )
 #' }
 #' @export
 selectInput <- function(inputId, label, choices, selected = NULL,
@@ -133,7 +155,7 @@ needOptgroup <- function(choices) {
 #' @rdname selectInput
 #' @param ... Arguments passed to \code{selectInput()}.
 #' @param options A list of options. See the documentation of \pkg{selectize.js}
-#'   for possible options (character option values inside \code{\link{I}()} will
+#'   for possible options (character option values inside \code{\link[base]{I}()} will
 #'   be treated as literal JavaScript code; see \code{\link{renderDataTable}()}
 #'   for details).
 #' @param width The width of the input, e.g. \code{'400px'}, or \code{'100\%'};
diff --git a/R/input-slider.R b/R/input-slider.R
index b8d88f8..afcc5ca 100644
--- a/R/input-slider.R
+++ b/R/input-slider.R
@@ -36,7 +36,7 @@
 #'   format string, to be passed to the Javascript strftime library. See
 #'   \url{https://github.com/samsonjs/strftime} for more details. The allowed
 #'   format specifications are very similar, but not identical, to those for R's
-#'   \code{\link{strftime}} function. For Dates, the default is \code{"\%F"}
+#'   \code{\link[base]{strftime}} function. For Dates, the default is \code{"\%F"}
 #'   (like \code{"2015-07-01"}), and for POSIXt, the default is \code{"\%F \%T"}
 #'   (like \code{"2015-07-01 15:32:10"}).
 #' @param timezone Only used if the values are POSIXt objects. A string
@@ -51,6 +51,7 @@
 #' @examples
 #' ## Only run examples in interactive R sessions
 #' if (interactive()) {
+#' options(device.ask.default = FALSE)
 #'
 #' ui <- fluidPage(
 #'   sliderInput("obs", "Number of observations:",
diff --git a/R/input-submit.R b/R/input-submit.R
index a5461a1..e26dd28 100644
--- a/R/input-submit.R
+++ b/R/input-submit.R
@@ -1,8 +1,27 @@
 #' Create a submit button
 #'
-#' Create a submit button for an input form. Forms that include a submit
+#' 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 \code{submitButton} is generally discouraged in favor of
+#' the more versatile \code{\link{actionButton}} (see details below).
+#'
+#' Submit buttons are unusual Shiny inputs, and we recommend using
+#' \code{\link{actionButton}} instead of \code{submitButton} when you
+#' want to delay a reaction.
+#' See \href{http://shiny.rstudio.com/articles/action-buttons.html}{this
+#' article} for more information (including a demo of how to "translate"
+#' code using a \code{submitButton} to code using an \code{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 \emph{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 \code{\link{renderUI}}
+#' or \code{\link{insertUI}}) will not work.
 #'
 #' @param text Button caption
 #' @param icon Optional \code{\link{icon}} to appear on the button
@@ -13,8 +32,26 @@
 #' @family input elements
 #'
 #' @examples
-#' submitButton("Update View")
-#' submitButton("Update View", icon("refresh"))
+#' 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(
diff --git a/R/progress.R b/R/progress.R
index 98d5b0a..7acf942 100644
--- a/R/progress.R
+++ b/R/progress.R
@@ -245,6 +245,7 @@ Progress <- R6Class(
 #' @examples
 #' ## Only run examples in interactive R sessions
 #' if (interactive()) {
+#' options(device.ask.default = FALSE)
 #'
 #' ui <- fluidPage(
 #'   plotOutput("plot")
diff --git a/R/reactives.R b/R/reactives.R
index e9b84ff..51a7100 100644
--- a/R/reactives.R
+++ b/R/reactives.R
@@ -344,7 +344,7 @@ as.list.reactivevalues <- function(x, all.names=FALSE, ...) {
 
 #' Convert a reactivevalues object to a list
 #'
-#' This function does something similar to what you might \code{\link{as.list}}
+#' This function does something similar to what you might \code{\link[base]{as.list}}
 #' to do. The difference is that the calling context will take dependencies on
 #' every object in the reactivevalues object. To avoid taking dependencies on
 #' all the objects, you can wrap the call with \code{\link{isolate}()}.
@@ -526,6 +526,7 @@ Observable <- R6Class(
       .mostRecentCtxId <<- ctx$id
       ctx$onInvalidate(function() {
         .invalidated <<- TRUE
+        .value <<- NULL # Value can be GC'd, it won't be read once invalidated
         .dependents$invalidate()
       })
       .execCount <<- .execCount + 1L
@@ -1109,7 +1110,7 @@ setAutoflush <- local({
 #' @return A no-parameter function that can be called from a reactive context,
 #'   in order to cause that context to be invalidated the next time the timer
 #'   interval elapses. Calling the returned function also happens to yield the
-#'   current time (as in \code{\link{Sys.time}}).
+#'   current time (as in \code{\link[base]{Sys.time}}).
 #' @seealso \code{\link{invalidateLater}}
 #'
 #' @examples
@@ -1417,7 +1418,7 @@ reactiveFileReader <- function(intervalMillis, session, filePath, readFunc, ...)
 #' The expression given to \code{isolate()} is evaluated in the calling
 #' environment. This means that if you assign a variable inside the
 #' \code{isolate()}, its value will be visible outside of the \code{isolate()}.
-#' If you want to avoid this, you can use \code{\link{local}()} inside the
+#' If you want to avoid this, you can use \code{\link[base]{local}()} inside the
 #' \code{isolate()}.
 #'
 #' This function can also be useful for calling reactive expression at the
@@ -1530,6 +1531,8 @@ maskReactiveContext <- function(expr) {
 #' invalidations that come from its reactive dependencies; it only invalidates
 #' in response to the given event.
 #'
+#' @section \code{ignoreNULL} and \code{ignoreInit}:
+#'
 #' Both \code{observeEvent} and \code{eventReactive} take an \code{ignoreNULL}
 #' parameter that affects behavior when the \code{eventExpr} evaluates to
 #' \code{NULL} (or in the special case of an \code{\link{actionButton}},
@@ -1542,6 +1545,44 @@ maskReactiveContext <- function(expr) {
 #' the action/calculation and just let the user re-initiate it (like a
 #' "Recalculate" button).
 #'
+#' Unlike what happens for \code{ignoreNULL}, only \code{observeEvent} takes in an
+#' \code{ignoreInit} argument. By default, \code{observeEvent} will run right when
+#' it is created (except if, at that moment, \code{eventExpr} evaluates to \code{NULL}
+#' and \code{ignoreNULL} is \code{TRUE}). But when responding to a click of an action
+#' button, it may often be useful to set \code{ignoreInit} to \code{TRUE}. For
+#' example, if you're setting up an \code{observeEvent} for a dynamically created
+#' button, then \code{ignoreInit = TRUE} will guarantee that the action (in
+#' \code{handlerExpr}) will only be triggered when the button is actually clicked,
+#' instead of also being triggered when it is created/initialized.
+#'
+#' Even though \code{ignoreNULL} and \code{ignoreInit} can be used for similar
+#' purposes they are independent from one another. Here's the result of combining
+#' these:
+#'
+#' \describe{
+#'   \item{\code{ignoreNULL = TRUE} and \code{ignoreInit = FALSE}}{
+#'      This is the default. This combination means that \code{handlerExpr} will
+#'      run every time that \code{eventExpr} is not \code{NULL}. If, at the time
+#'      of the \code{observeEvent}'s creation, \code{handleExpr} happens to
+#'      \emph{not} be \code{NULL}, then the code runs.
+#'   }
+#'   \item{\code{ignoreNULL = FALSE} and \code{ignoreInit = FALSE}}{
+#'      This combination means that \code{handlerExpr} will run every time no
+#'      matter what.
+#'   }
+#'   \item{\code{ignoreNULL = FALSE} and \code{ignoreInit = TRUE}}{
+#'      This combination means that \code{handlerExpr} will \emph{not} run when
+#'      the \code{observeEvent} is created (because \code{ignoreInit = TRUE}),
+#'      but it will run every other time.
+#'   }
+#'   \item{\code{ignoreNULL = TRUE} and \code{ignoreInit = TRUE}}{
+#'      This combination means that \code{handlerExpr} will \emph{not} run when
+#'      the \code{observeEvent} is created (because \code{ignoreInit = TRUE}).
+#'      After that, \code{handlerExpr} will run every time that \code{eventExpr}
+#'      is not \code{NULL}.
+#'   }
+#' }
+#'
 #' @param eventExpr A (quoted or unquoted) expression that represents the event;
 #'   this can be a simple reactive value like \code{input$click}, a call to a
 #'   reactive expression like \code{dataset()}, or even a complex expression
@@ -1583,6 +1624,15 @@ maskReactiveContext <- function(expr) {
 #' @param ignoreNULL Whether the action should be triggered (or value
 #'   calculated, in the case of \code{eventReactive}) when the input is
 #'   \code{NULL}. See Details.
+#' @param ignoreInit If \code{TRUE}, then, when this \code{observeEvent} is
+#'   first created/initialized, ignore the \code{handlerExpr} (the second
+#'   argument), whether it is otherwise supposed to run or not. The default is
+#'   \code{FALSE}. See Details.
+#' @param once Whether this \code{observeEvent} should be immediately destroyed
+#'   after the first time that the code in \code{handlerExpr} is run. This
+#'   pattern is useful when you want to subscribe to a event that should only
+#'   happen once.
+#'
 #' @return \code{observeEvent} returns an observer reference class object (see
 #'   \code{\link{observe}}). \code{eventReactive} returns a reactive expression
 #'   object (see \code{\link{reactive}}).
@@ -1592,37 +1642,71 @@ maskReactiveContext <- function(expr) {
 #' @examples
 #' ## Only run this example in interactive R sessions
 #' if (interactive()) {
-#'   ui <- fluidPage(
-#'     column(4,
-#'       numericInput("x", "Value", 5),
-#'       br(),
-#'       actionButton("button", "Show")
+#'
+#'   ## App 1: Sample usage
+#'   shinyApp(
+#'     ui = fluidPage(
+#'       column(4,
+#'         numericInput("x", "Value", 5),
+#'         br(),
+#'         actionButton("button", "Show")
+#'       ),
+#'       column(8, tableOutput("table"))
 #'     ),
-#'     column(8, tableOutput("table"))
+#'     server = function(input, output) {
+#'       # Take an action every time button is pressed;
+#'       # here, we just print a message to the console
+#'       observeEvent(input$button, {
+#'         cat("Showing", input$x, "rows\n")
+#'       })
+#'       # Take a reactive dependency on input$button, but
+#'       # not on any of the stuff inside the function
+#'       df <- eventReactive(input$button, {
+#'         head(cars, input$x)
+#'       })
+#'       output$table <- renderTable({
+#'         df()
+#'       })
+#'     }
+#'   )
+#'
+#'   ## App 2: Using `once`
+#'   shinyApp(
+#'     ui = basicPage( actionButton("go", "Go")),
+#'     server = function(input, output, session) {
+#'       observeEvent(input$go, {
+#'         print(paste("This will only be printed once; all",
+#'               "subsequent button clicks won't do anything"))
+#'       }, once = TRUE)
+#'     }
+#'   )
+#'
+#'   ## App 3: Using `ignoreInit` and `once`
+#'   shinyApp(
+#'     ui = basicPage(actionButton("go", "Go")),
+#'     server = function(input, output, session) {
+#'       observeEvent(input$go, {
+#'         insertUI("#go", "afterEnd",
+#'                  actionButton("dynamic", "click to remove"))
+#'
+#'         # set up an observer that depends on the dynamic
+#'         # input, so that it doesn't run when the input is
+#'         # created, and only runs once after that (since
+#'         # the side effect is remove the input from the DOM)
+#'         observeEvent(input$dynamic, {
+#'           removeUI("#dynamic")
+#'         }, ignoreInit = TRUE, once = TRUE)
+#'       })
+#'     }
 #'   )
-#'   server <- function(input, output) {
-#'     # Take an action every time button is pressed;
-#'     # here, we just print a message to the console
-#'     observeEvent(input$button, {
-#'       cat("Showing", input$x, "rows\n")
-#'     })
-#'     # Take a reactive dependency on input$button, but
-#'     # not on any of the stuff inside the function
-#'     df <- eventReactive(input$button, {
-#'       head(cars, input$x)
-#'     })
-#'     output$table <- renderTable({
-#'       df()
-#'     })
-#'   }
-#'   shinyApp(ui=ui, server=server)
 #' }
 #' @export
 observeEvent <- function(eventExpr, handlerExpr,
   event.env = parent.frame(), event.quoted = FALSE,
   handler.env = parent.frame(), handler.quoted = FALSE,
-  label=NULL, suspended=FALSE, priority=0, domain=getDefaultReactiveDomain(),
-  autoDestroy = TRUE, ignoreNULL = TRUE) {
+  label = NULL, suspended = FALSE, priority = 0,
+  domain = getDefaultReactiveDomain(), autoDestroy = TRUE,
+  ignoreNULL = TRUE, ignoreInit = FALSE, once = FALSE) {
 
   eventFunc <- exprToFunction(eventExpr, event.env, event.quoted)
   if (is.null(label))
@@ -1632,16 +1716,29 @@ observeEvent <- function(eventExpr, handlerExpr,
   handlerFunc <- exprToFunction(handlerExpr, handler.env, handler.quoted)
   handlerFunc <- wrapFunctionLabel(handlerFunc, "observeEventHandler", ..stacktraceon = TRUE)
 
-  invisible(observe({
+  initialized <- FALSE
+
+  o <- observe({
     e <- eventFunc()
 
+    if (ignoreInit && !initialized) {
+      initialized <<- TRUE
+      return()
+    }
+
     if (ignoreNULL && isNullEvent(e)) {
       return()
     }
 
+    if (once) {
+      on.exit(o$destroy())
+    }
+
     isolate(handlerFunc())
   }, label = label, suspended = suspended, priority = priority, domain = domain,
-    autoDestroy = TRUE, ..stacktraceon = FALSE))
+  autoDestroy = TRUE, ..stacktraceon = FALSE)
+
+  invisible(o)
 }
 
 #' @rdname observeEvent
@@ -1649,8 +1746,8 @@ observeEvent <- function(eventExpr, handlerExpr,
 eventReactive <- function(eventExpr, valueExpr,
   event.env = parent.frame(), event.quoted = FALSE,
   value.env = parent.frame(), value.quoted = FALSE,
-  label=NULL, domain=getDefaultReactiveDomain(),
-  ignoreNULL = TRUE) {
+  label = NULL, domain = getDefaultReactiveDomain(),
+  ignoreNULL = TRUE, ignoreInit = FALSE) {
 
   eventFunc <- exprToFunction(eventExpr, event.env, event.quoted)
   if (is.null(label))
@@ -1660,13 +1757,17 @@ eventReactive <- function(eventExpr, valueExpr,
   handlerFunc <- exprToFunction(valueExpr, value.env, value.quoted)
   handlerFunc <- wrapFunctionLabel(handlerFunc, "eventReactiveHandler", ..stacktraceon = TRUE)
 
+  initialized <- FALSE
+
   invisible(reactive({
     e <- eventFunc()
 
-    validate(need(
-      !ignoreNULL || !isNullEvent(e),
-      message = FALSE
-    ))
+    if (ignoreInit && !initialized) {
+      initialized <<- TRUE
+      req(FALSE)
+    }
+
+    req(!ignoreNULL || !isNullEvent(e))
 
     isolate(handlerFunc())
   }, label = label, domain = domain, ..stacktraceon = FALSE))
@@ -1675,3 +1776,246 @@ eventReactive <- function(eventExpr, valueExpr,
 isNullEvent <- function(value) {
   is.null(value) || (inherits(value, 'shinyActionButtonValue') && value == 0)
 }
+
+#' Slow down a reactive expression with debounce/throttle
+#'
+#' Transforms a reactive expression by preventing its invalidation signals from
+#' being sent unnecessarily often. This lets you ignore a very "chatty" reactive
+#' expression until it becomes idle, which is useful when the intermediate
+#' values don't matter as much as the final value, and the downstream
+#' calculations that depend on the reactive expression take a long time.
+#' \code{debounce} and \code{throttle} use different algorithms for slowing down
+#' invalidation signals; see Details.
+#'
+#' @section Limitations:
+#'
+#'   Because R is single threaded, we can't come close to guaranteeing that the
+#'   timing of debounce/throttle (or any other timing-related functions in
+#'   Shiny) will be consistent or accurate; at the time we want to emit an
+#'   invalidation signal, R may be performing a different task and we have no
+#'   way to interrupt it (nor would we necessarily want to if we could).
+#'   Therefore, it's best to think of the time windows you pass to these
+#'   functions as minimums.
+#'
+#'   You may also see undesirable behavior if the amount of time spent doing
+#'   downstream processing for each change approaches or exceeds the time
+#'   window: in this case, debounce/throttle may not have any effect, as the
+#'   time each subsequent event is considered is already after the time window
+#'   has expired.
+#'
+#' @details
+#'
+#' This is not a true debounce/throttle in that it will not prevent \code{r}
+#' from being called many times (in fact it may be called more times than
+#' usual), but rather, the reactive invalidation signal that is produced by
+#' \code{r} is debounced/throttled instead. Therefore, these functions should be
+#' used when \code{r} is cheap but the things it will trigger (downstream
+#' outputs and reactives) are expensive.
+#'
+#' Debouncing means that every invalidation from \code{r} will be held for the
+#' specified time window. If \code{r} invalidates again within that time window,
+#' then the timer starts over again. This means that as long as invalidations
+#' continually arrive from \code{r} within the time window, the debounced
+#' reactive will not invalidate at all. Only after the invalidations stop (or
+#' slow down sufficiently) will the downstream invalidation be sent.
+#'
+#' \code{ooo-oo-oo---- => -----------o-}
+#'
+#' (In this graphical depiction, each character represents a unit of time, and
+#' the time window is 3 characters.)
+#'
+#' Throttling, on the other hand, delays invalidation if the \emph{throttled}
+#' reactive recently (within the time window) invalidated. New \code{r}
+#' invalidations do not reset the time window. This means that if invalidations
+#' continually come from \code{r} within the time window, the throttled reactive
+#' will invalidate regularly, at a rate equal to or slower than than the time
+#' window.
+#'
+#' \code{ooo-oo-oo---- => o--o--o--o---}
+#'
+#' @param r A reactive expression (that invalidates too often).
+#' @param millis The debounce/throttle time window. You may optionally pass a
+#'   no-arg function or reactive expression instead, e.g. to let the end-user
+#'   control the time window.
+#' @param priority Debounce/throttle is implemented under the hood using
+#'   \link[=observe]{observers}. Use this parameter to set the priority of
+#'   these observers. Generally, this should be higher than the priorities of
+#'   downstream observers and outputs (which default to zero).
+#' @param domain See \link{domains}.
+#'
+#' @examples
+#' ## Only run examples in interactive R sessions
+#' if (interactive()) {
+#' options(device.ask.default = FALSE)
+#'
+#' library(shiny)
+#' library(magrittr)
+#'
+#' ui <- fluidPage(
+#'   plotOutput("plot", click = clickOpts("hover")),
+#'   helpText("Quickly click on the plot above, while watching the result table below:"),
+#'   tableOutput("result")
+#' )
+#'
+#' server <- function(input, output, session) {
+#'   hover <- reactive({
+#'     if (is.null(input$hover))
+#'       list(x = NA, y = NA)
+#'     else
+#'       input$hover
+#'   })
+#'   hover_d <- hover %>% debounce(1000)
+#'   hover_t <- hover %>% throttle(1000)
+#'
+#'   output$plot <- renderPlot({
+#'     plot(cars)
+#'   })
+#'
+#'   output$result <- renderTable({
+#'     data.frame(
+#'       mode = c("raw", "throttle", "debounce"),
+#'       x = c(hover()$x, hover_t()$x, hover_d()$x),
+#'       y = c(hover()$y, hover_t()$y, hover_d()$y)
+#'     )
+#'   })
+#' }
+#'
+#' shinyApp(ui, server)
+#' }
+#'
+#' @export
+debounce <- function(r, millis, priority = 100, domain = getDefaultReactiveDomain()) {
+
+  # TODO: make a nice label for the observer(s)
+
+  force(r)
+  force(millis)
+
+  if (!is.function(millis)) {
+    origMillis <- millis
+    millis <- function() origMillis
+  }
+
+  v <- reactiveValues(
+    trigger = NULL,
+    when = NULL # the deadline for the timer to fire; NULL if not scheduled
+  )
+
+  # Responsible for tracking when f() changes.
+  firstRun <- TRUE
+  observe({
+    r()
+
+    if (firstRun) {
+      # During the first run we don't want to set v$when, as this will kick off
+      # the timer. We only want to do that when we see r() change.
+      firstRun <<- FALSE
+      return()
+    }
+
+    # The value (or possibly millis) changed. Start or reset the timer.
+    v$when <- Sys.time() + millis()/1000
+  }, label = "debounce tracker", domain = domain, priority = priority)
+
+  # This observer is the timer. It rests until v$when elapses, then touches
+  # v$trigger.
+  observe({
+    if (is.null(v$when))
+      return()
+
+    now <- Sys.time()
+    if (now >= v$when) {
+      # Mod by 999999999 to get predictable overflow behavior
+      v$trigger <- isolate(v$trigger %OR% 0) %% 999999999 + 1
+      v$when <- NULL
+    } else {
+      invalidateLater((v$when - now) * 1000)
+    }
+  }, label = "debounce timer", domain = domain, priority = priority)
+
+  # This is the actual reactive that is returned to the user. It returns the
+  # value of r(), but only invalidates/updates when v$trigger is touched.
+  er <- eventReactive(v$trigger, {
+    r()
+  }, label = "debounce result", ignoreNULL = FALSE, domain = domain)
+
+  # Force the value of er to be immediately cached upon creation. It's very hard
+  # to explain why this observer is needed, but if you want to understand, try
+  # commenting it out and studying the unit test failure that results.
+  primer <- observe({
+    primer$destroy()
+    er()
+  }, label = "debounce primer", domain = domain, priority = priority)
+
+  er
+}
+
+#' @rdname debounce
+#' @export
+throttle <- function(r, millis, priority = 100, domain = getDefaultReactiveDomain()) {
+
+  # TODO: make a nice label for the observer(s)
+
+  force(r)
+  force(millis)
+
+  if (!is.function(millis)) {
+    origMillis <- millis
+    millis <- function() origMillis
+  }
+
+  v <- reactiveValues(
+    trigger = 0,
+    lastTriggeredAt = NULL, # Last time we fired; NULL if never
+    pending = FALSE # If TRUE, trigger again when timer elapses
+  )
+
+  blackoutMillisLeft <- function() {
+    if (is.null(v$lastTriggeredAt)) {
+      0
+    } else {
+      max(0, (v$lastTriggeredAt + millis()/1000) - Sys.time()) * 1000
+    }
+  }
+
+  trigger <- function() {
+    v$lastTriggeredAt <- Sys.time()
+    # Mod by 999999999 to get predictable overflow behavior
+    v$trigger <- isolate(v$trigger) %% 999999999 + 1
+    v$pending <- FALSE
+  }
+
+  # Responsible for tracking when f() changes.
+  observeEvent(r(), {
+    if (v$pending) {
+      # In a blackout period and someone already scheduled; do nothing
+    } else if (blackoutMillisLeft() > 0) {
+      # In a blackout period but this is the first change in that period; set
+      # v$pending so that a trigger will be scheduled at the end of the period
+      v$pending <- TRUE
+    } else {
+      # Not in a blackout period. Trigger, which will start a new blackout
+      # period.
+      trigger()
+    }
+  }, label = "throttle tracker", ignoreNULL = FALSE, priority = priority, domain = domain)
+
+  observe({
+    if (!v$pending) {
+      return()
+    }
+
+    timeout <- blackoutMillisLeft()
+    if (timeout > 0) {
+      invalidateLater(timeout)
+    } else {
+      trigger()
+    }
+  }, priority = priority, domain = domain)
+
+  # This is the actual reactive that is returned to the user. It returns the
+  # value of r(), but only invalidates/updates when v$trigger is touched.
+  eventReactive(v$trigger, {
+    r()
+  }, label = "throttle result", ignoreNULL = FALSE, domain = domain)
+}
diff --git a/R/render-plot.R b/R/render-plot.R
index 94e2b74..634d06b 100644
--- a/R/render-plot.R
+++ b/R/render-plot.R
@@ -28,7 +28,7 @@
 #'   inline plot, you must provide numeric values (in pixels) to both
 #'   \code{width} and \code{height}.
 #' @param res Resolution of resulting plot, in pixels per inch. This value is
-#'   passed to \code{\link{png}}. Note that this affects the resolution of PNG
+#'   passed to \code{\link[grDevices]{png}}. 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.
diff --git a/R/server.R b/R/server.R
index a341bde..fcf52b6 100644
--- a/R/server.R
+++ b/R/server.R
@@ -34,7 +34,7 @@ registerClient <- function(client) {
 #' JavaScript/CSS files available to their components.
 #'
 #' @param prefix The URL prefix (without slashes). Valid characters are a-z,
-#'   A-Z, 0-9, hyphen, period, and underscore; and must begin with a-z or 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
@@ -52,7 +52,7 @@ registerClient <- function(client) {
 #' @export
 addResourcePath <- function(prefix, directoryPath) {
   prefix <- prefix[1]
-  if (!grepl('^[a-z][a-z0-9\\-_.]*$', prefix, ignore.case=TRUE, perl=TRUE)) {
+  if (!grepl('^[a-z0-9\\-_][a-z0-9\\-_.]*$', prefix, ignore.case=TRUE, perl=TRUE)) {
     stop("addResourcePath called with invalid prefix; please see documentation")
   }
 
@@ -462,6 +462,9 @@ serviceApp <- function() {
 
 .shinyServerMinVersion <- '0.3.4'
 
+# Global flag that's TRUE whenever we're inside of the scope of a call to runApp
+.globals$running <- FALSE
+
 #' Run Shiny Application
 #'
 #' Runs a Shiny application. This function normally does not return; interrupt R
@@ -503,6 +506,9 @@ serviceApp <- function() {
 #'   application. If set to \code{"normal"}, displays the application normally.
 #'   Defaults to \code{"auto"}, which displays the application in the mode given
 #'   in its \code{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
+#'   \code{shiny.testmode} option, or FALSE if the option is not set.
 #'
 #' @examples
 #' \dontrun{
@@ -515,6 +521,8 @@ serviceApp <- function() {
 #'
 #' ## 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(
@@ -546,25 +554,73 @@ runApp <- function(appDir=getwd(),
                                             interactive()),
                    host=getOption('shiny.host', '127.0.0.1'),
                    workerId="", quiet=FALSE,
-                   display.mode=c("auto", "normal", "showcase")) {
+                   display.mode=c("auto", "normal", "showcase"),
+                   test.mode=getOption('shiny.testmode', FALSE)) {
   on.exit({
     handlerManager$clear()
   }, add = TRUE)
 
+  if (.globals$running) {
+    stop("Can't call `runApp()` from within `runApp()`. If your ,",
+         "application code contains `runApp()`, please remove it.")
+  }
+  .globals$running <- TRUE
+  on.exit({
+    .globals$running <- FALSE
+  }, add = TRUE)
+
   # Enable per-app Shiny options
   oldOptionSet <- .globals$options
   on.exit({
     .globals$options <- oldOptionSet
   },add = TRUE)
 
-  if (is.null(host) || is.na(host))
-    host <- '0.0.0.0'
-
   # Make warnings print immediately
   # Set pool.scheduler to support pool package
   ops <- options(warn = 1, pool.scheduler = scheduleTask)
   on.exit(options(ops), add = TRUE)
 
+  appParts <- as.shiny.appobj(appDir)
+
+  # The lines below set some of the app's running options, which
+  # can be:
+  #   - left unspeficied (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'
+
   workerId(workerId)
 
   if (inShinyServer()) {
@@ -584,6 +640,11 @@ runApp <- function(appDir=getwd(),
   # the display.mode parameter. The latter takes precedence.
   setShowcaseDefault(0)
 
+  .globals$testMode <- test.mode
+  if (test.mode) {
+    message("Running application in test mode.")
+  }
+
   # If appDir specifies a path, and display mode is specified in the
   # DESCRIPTION file at that path, apply it here.
   if (is.character(appDir)) {
@@ -671,8 +732,6 @@ runApp <- function(appDir=getwd(),
     }
   }
 
-  appParts <- as.shiny.appobj(appDir)
-
   # 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.)
@@ -716,12 +775,16 @@ runApp <- function(appDir=getwd(),
   # Top-level ..stacktraceoff..; matches with ..stacktraceon in observe(),
   # reactive(), Callbacks$invoke(), and others
   ..stacktraceoff..(
-    captureStackTraces(
+    captureStackTraces({
+      # If any observers were created before runApp was called, this will make
+      # sure they run once the app starts. (Issue #1013)
+      scheduleFlush()
+
       while (!.globals$stopped) {
         serviceApp()
         Sys.sleep(0.001)
       }
-    )
+    })
   )
 
   if (isTRUE(.globals$reterror)) {
diff --git a/R/shiny.R b/R/shiny.R
index e6f49f9..f30bd1a 100644
--- a/R/shiny.R
+++ b/R/shiny.R
@@ -276,6 +276,10 @@ workerId <- local({
 #'   This is the request that was used to initiate the websocket connection
 #'   (as opposed to the request that downloaded the web page for the app).
 #' }
+#' \item{userData}{
+#'   An environment for app authors and module/package authors to store whatever
+#'   session-specific data they want.
+#' }
 #' \item{resetBrush(brushId)}{
 #'   Resets/clears the brush with the given \code{brushId}, if it exists on
 #'   any \code{imageOutput} or \code{plotOutput} in the app.
@@ -331,15 +335,15 @@ workerId <- local({
 #' }
 #' \item{exportTestValues()}{
 #'   Registers expressions for export in test mode, available at the test
-#'   endpoint URL.
+#'   snapshot URL.
 #' }
-#' \item{getTestEndpointUrl(inputs=TRUE, outputs=TRUE, exports=TRUE,
-#'   format="rds")}{
-#'   Returns a URL for the test endpoint. Only has an effect when the
-#'   \code{shiny.testmode} option is set to TRUE. For the inputs, outputs, and
-#'   exports arguments, TRUE means to return all of these values. It is also
+#' \item{getTestSnapshotUrl(input=TRUE, output=TRUE, export=TRUE,
+#'   format="json")}{
+#'   Returns a URL for the test snapshots. Only has an effect when the
+#'   \code{shiny.testmode} option is set to TRUE. For the input, output, and
+#'   export arguments, TRUE means to return all of these values. It is also
 #'   possible to specify by name which values to return by providing a
-#'   character vector, as in \code{inputs=c("x", "y")}. The format can be
+#'   character vector, as in \code{input=c("x", "y")}. The format can be
 #'   "rds" or "json".
 #' }
 #'
@@ -412,9 +416,10 @@ ShinySession <- R6Class(
     restoredCallbacks = 'Callbacks',
     bookmarkExclude = character(0),  # Names of inputs to exclude from bookmarking
 
-    testValueExprs = list(),
+    testMode = FALSE,                # Are we running in test mode?
+    testExportExprs = list(),
     outputValues = list(),           # Saved output values (for testing mode)
-    testEndpointUrl = character(0),
+    testSnapshotUrl = character(0),
 
     sendResponse = function(requestMsg, value) {
       if (is.null(requestMsg$tag)) {
@@ -579,71 +584,84 @@ ShinySession <- R6Class(
       private$outputValues <- mergeVectors(private$outputValues, values)
     },
 
-    enableTestEndpoint = function() {
-      private$testEndpointUrl <- self$registerDataObj("shinytest", NULL,
+    enableTestSnapshot = function() {
+      private$testSnapshotUrl <- self$registerDataObj("shinytest", NULL,
         function(data, req) {
-          if (!isTRUE(getOption("shiny.testmode"))) {
+          if (!isTRUE(private$testMode)) {
             return()
           }
 
           params <- parseQueryString(req$QUERY_STRING)
-          # The format of the response that will be sent back. Default to "rds"
-          # unless requested otherwise. The only other valid value is "json".
-          format <- params$format %OR% "rds"
+          # The format of the response that will be sent back. Defaults to
+          # "json" unless requested otherwise. The only other valid value is
+          # "rds".
+          format <- params$format %OR% "json"
 
           values <- list()
 
-          if (!is.null(params$inputs)) {
+          if (!is.null(params$input)) {
 
             allInputs <- isolate(
               reactiveValuesToList(self$input, all.names = TRUE)
             )
 
-            # If params$inputs is "1", return all; otherwise return just the
-            # inputs that are named in params$inputs, like "x,y,z".
-            if (params$inputs == "1") {
-              values$inputs <- allInputs
+            # If params$input is "1", return all; otherwise return just the
+            # inputs that are named in params$input, like "x,y,z".
+            if (params$input == "1") {
+              values$input <- allInputs
             } else {
-              items <- strsplit(params$inputs, ",")[[1]]
+              items <- strsplit(params$input, ",")[[1]]
               items <- intersect(items, names(allInputs))
-              values$inputs <- allInputs[items]
+              values$input <- allInputs[items]
             }
+
+            values$input <- sortByName(values$input)
           }
 
-          if (!is.null(params$outputs)) {
+          if (!is.null(params$output)) {
 
-            if (params$outputs == "1") {
-              values$outputs <- private$outputValues
+            if (params$output == "1") {
+              values$output <- private$outputValues
             } else {
-              items <- strsplit(params$outputs, ",")[[1]]
+              items <- strsplit(params$output, ",")[[1]]
               items <- intersect(items, names(private$outputValues))
-              values$outputs <- private$outputValues[items]
+              values$output <- private$outputValues[items]
             }
+
+            values$output <- sortByName(values$output)
           }
 
-          if (!is.null(params$exports)) {
+          if (!is.null(params$export)) {
 
-            testValueExprs <- private$testValueExprs
-            if (params$exports == "1") {
-              values$exports <- isolate(
-                lapply(private$testValueExprs, function(item) {
+            if (params$export == "1") {
+              values$export <- isolate(
+                lapply(private$testExportExprs, function(item) {
                   eval(item$expr, envir = item$env)
                 })
               )
             } else {
-              items <- strsplit(params$exports, ",")[[1]]
-              items <- intersect(items, names(private$testValueExprs))
-              values$exports <- isolate(
-                lapply(private$testValueExprs[items], function(item) {
+              items <- strsplit(params$export, ",")[[1]]
+              items <- intersect(items, names(private$testExportExprs))
+              values$export <- isolate(
+                lapply(private$testExportExprs[items], function(item) {
                   eval(item$expr, envir = item$env)
                 })
               )
             }
+
+            values$export <- sortByName(values$export)
           }
 
+          # Make sure input, output, and export are all named lists (at this
+          # point, they could be unnamed if they are empty lists). This is so
+          # that the resulting object is represented as an object in JSON
+          # instead of an array, and so that the RDS data structure is of a
+          # consistent type.
+          values <- lapply(values, asNamedVector)
+
           if (length(values) == 0) {
             return(httpResponse(400, "text/plain",
-              "No exports, inputs, or outputs requested."
+              "None of export, input, or output requested."
             ))
           }
 
@@ -678,6 +696,7 @@ ShinySession <- R6Class(
     closed = logical(0),
     request = 'ANY',      # Websocket request object
     singletons = character(0),  # Tracks singleton HTML fragments sent to the page
+    userData = 'environment',
     user = NULL,
     groups = NULL,
 
@@ -698,6 +717,7 @@ ShinySession <- R6Class(
       self$progressStack <- Stack$new()
       self$files <- Map$new()
       self$downloads <- Map$new()
+      self$userData <- new.env(parent = emptyenv())
 
       self$input <- .createReactiveValues(private$.input, readonly=TRUE)
       .setLabel(self$input, 'input')
@@ -716,7 +736,8 @@ ShinySession <- R6Class(
       private$restoredCallbacks <- Callbacks$new()
       private$createBookmarkObservers()
 
-      private$enableTestEndpoint()
+      private$testMode <- .globals$testMode
+      private$enableTestSnapshot()
 
       private$registerSessionEndCallbacks()
 
@@ -1030,17 +1051,17 @@ ShinySession <- R6Class(
             shinyCallingHandlers(func()),
             shiny.custom.error = function(cond) {
               if (isTRUE(getOption("show.error.messages"))) printError(cond)
-              structure(NULL, class = "try-error", condition = cond)
+              structure(list(), class = "try-error", condition = cond)
             },
             shiny.output.cancel = function(cond) {
-              structure(NULL, class = "cancel-output")
+              structure(list(), class = "cancel-output")
             },
             shiny.silent.error = function(cond) {
               # Don't let shiny.silent.error go through the normal stop
               # path of try, because we don't want it to print. But we
               # do want to try to return the same looking result so that
               # the code below can send the error to the browser.
-              structure(NULL, class = "try-error", condition = cond)
+              structure(list(), class = "try-error", condition = cond)
             },
             error = function(cond) {
               if (isTRUE(getOption("show.error.messages"))) printError(cond)
@@ -1049,7 +1070,7 @@ ShinySession <- R6Class(
                                           "logs or contact the app author for",
                                           "clarification."))
               }
-              invisible(structure(NULL, class = "try-error", condition = cond))
+              invisible(structure(list(), class = "try-error", condition = cond))
             },
             finally = {
               private$sendMessage(recalculating = list(
@@ -1135,7 +1156,7 @@ ShinySession <- R6Class(
       inputMessages <- private$inputMessageQueue
       private$inputMessageQueue <- list()
 
-      if (isTRUE(getOption("shiny.testmode"))) {
+      if (isTRUE(private$testMode)) {
         private$storeOutputValues(mergeVectors(values, errors))
       }
 
@@ -1331,11 +1352,11 @@ ShinySession <- R6Class(
         list(expr = expr, env = env_)
       })
 
-      private$testValueExprs <- mergeVectors(private$testValueExprs, items)
+      private$testExportExprs <- mergeVectors(private$testExportExprs, items)
     },
 
-    getTestEndpointUrl = function(inputs = TRUE, outputs = TRUE, exports = TRUE,
-                                  format = "rds") {
+    getTestSnapshotUrl = function(input = TRUE, output = TRUE, export = TRUE,
+                                  format = "json") {
       reqString <- function(group, value) {
         if (isTRUE(value))
           paste0(group, "=1")
@@ -1345,10 +1366,10 @@ ShinySession <- R6Class(
           ""
       }
       paste(
-        private$testEndpointUrl,
-        reqString("inputs", inputs),
-        reqString("outputs", outputs),
-        reqString("exports", exports),
+        private$testSnapshotUrl,
+        reqString("input", input),
+        reqString("output", output),
+        reqString("export", export),
         paste0("format=", format),
         sep = "&"
       )
diff --git a/R/shinyui.R b/R/shinyui.R
index e803c47..c3f4a5b 100644
--- a/R/shinyui.R
+++ b/R/shinyui.R
@@ -24,7 +24,7 @@ withMathJax <- function(...) {
   )
 }
 
-renderPage <- function(ui, connection, showcase=0) {
+renderPage <- function(ui, connection, showcase=0, testMode=FALSE) {
   # If the ui is a NOT complete document (created by htmlTemplate()), then do some
   # preprocessing and make sure it's a complete document.
   if (!inherits(ui, "html_document")) {
@@ -50,6 +50,14 @@ renderPage <- function(ui, connection, showcase=0) {
       script = if (getOption("shiny.minified", TRUE)) "shiny.min.js" else "shiny.js",
       stylesheet = "shiny.css")
   )
+
+  if (testMode) {
+    # Add code injection listener if in test mode
+    shiny_deps[[length(shiny_deps) + 1]] <-
+      htmlDependency("shiny-testmode", utils::packageVersion("shiny"),
+        c(href="shared"), script = "shiny-testmode.js")
+  }
+
   html <- renderDocument(ui, shiny_deps, processDep = createWebDependency)
   writeUTF8(html, con = connection)
 }
@@ -91,6 +99,8 @@ uiHttpHandler <- function(ui, uiPattern = "^/$") {
         showcaseMode <- mode
     }
 
+    testMode <- .globals$testMode %OR% FALSE
+
     # Create a restore context using query string
     bookmarkStore <- getShinyOption("bookmarkStore", default = "disable")
     if (bookmarkStore == "disable") {
@@ -121,7 +131,7 @@ uiHttpHandler <- function(ui, uiPattern = "^/$") {
     if (is.null(uiValue))
       return(NULL)
 
-    renderPage(uiValue, textConn, showcaseMode)
+    renderPage(uiValue, textConn, showcaseMode, testMode)
     html <- paste(readLines(textConn, encoding = 'UTF-8'), collapse='\n')
     return(httpResponse(200, content=enc2utf8(html)))
   }
diff --git a/R/shinywrappers.R b/R/shinywrappers.R
index 3559aa0..c12f939 100644
--- a/R/shinywrappers.R
+++ b/R/shinywrappers.R
@@ -127,6 +127,7 @@ as.tags.shiny.render.function <- function(x, ..., inline = FALSE) {
 #' @examples
 #' ## Only run examples in interactive R sessions
 #' if (interactive()) {
+#' options(device.ask.default = FALSE)
 #'
 #' ui <- fluidPage(
 #'   sliderInput("n", "Number of observations", 2, 1000, 500),
@@ -220,7 +221,7 @@ renderImage <- function(expr, env=parent.frame(), quoted=FALSE,
 #'
 #' Makes a reactive version of the given function that captures any printed
 #' output, and also captures its printable result (unless
-#' \code{\link{invisible}}), into a string. The resulting function is suitable
+#' \code{\link[base]{invisible}}), into a string. The resulting function is suitable
 #' for assigning to an  \code{output} slot.
 #'
 #' The corresponding HTML output tag can be anything (though \code{pre} is
@@ -232,14 +233,14 @@ renderImage <- function(expr, env=parent.frame(), quoted=FALSE,
 #'
 #' Note that unlike most other Shiny output functions, if the given function
 #' returns \code{NULL} then \code{NULL} will actually be visible in the output.
-#' To display nothing, make your function return \code{\link{invisible}()}.
+#' To display nothing, make your function return \code{\link[base]{invisible}()}.
 #'
 #' @param expr An expression that may print output and/or return a printable R
 #'   object.
 #' @param env The environment in which to evaluate \code{expr}.
 #' @param quoted Is \code{expr} a quoted expression (with \code{quote()})? This
 #'   is useful if you want to save an expression in a variable.
-#' @param width The value for \code{\link{options}('width')}.
+#' @param width The value for \code{\link[base]{options}('width')}.
 #' @param outputArgs A list of arguments to be passed through to the implicit
 #'   call to \code{\link{verbatimTextOutput}} when \code{renderPrint} is used
 #'   in an interactive R Markdown document.
@@ -420,7 +421,7 @@ downloadHandler <- function(filename, content, contentType=NA, outputArgs=list()
 #' the server infrastructure.
 #'
 #' For the \code{options} argument, the character elements that have the class
-#' \code{"AsIs"} (usually returned from \code{\link{I}()}) will be evaluated in
+#' \code{"AsIs"} (usually returned from \code{\link[base]{I}()}) will be evaluated in
 #' JavaScript. This is useful when the type of the option value is not supported
 #' in JSON, e.g., a JavaScript function, which can be obtained by evaluating a
 #' character string. Note this only applies to the root-level elements of the
diff --git a/R/test-export.R b/R/test-export.R
index a9b3b68..78ba34f 100644
--- a/R/test-export.R
+++ b/R/test-export.R
@@ -1,23 +1,24 @@
 #' Register expressions for export in test mode
 #'
 #' This function registers expressions that will be evaluated when a test export
-#' event occurs. These events are triggered by accessing an API endpoint URL.
+#' event occurs. These events are triggered by accessing a snapshot URL.
 #'
-#' This function only has an effect if the global option \code{shiny.testmode}
-#' is set to \code{TRUE}.
+#' This function only has an effect if the app is launched in test mode. This is
+#' done by calling \code{runApp()} with \code{test.mode=TRUE}, or by setting the
+#' global option \code{shiny.testmode} to \code{TRUE}.
 #'
 #' @param quoted_ Are the expression quoted? Default is \code{FALSE}.
 #' @param env_ The environment in which the expression should be evaluated.
 #' @param session_ A Shiny session object.
 #' @param ... Named arguments that are quoted or unquoted expressions that will
-#'   be captured and evaluated when API endpoint is visited.
+#'   be captured and evaluated when snapshot URL is visited.
 #' @examples
 #' ## Only run this example in interactive R sessions
 #' if (interactive()) {
 #'
 #' options(shiny.testmode = TRUE)
 #'
-#' # This application shows the test endpoint URL; clicking on it will
+#' # This application shows the test snapshot URL; clicking on it will
 #' # fetch the input, output, and exported values in JSON format.
 #' shinyApp(
 #'   ui = basicPage(
@@ -42,7 +43,7 @@
 #'     )
 #'
 #'     output$url <- renderUI({
-#'       url <- session$getTestEndpointUrl(format="json")
+#'       url <- session$getTestSnapshotUrl(format="json")
 #'       a(href = url, url)
 #'     })
 #'
diff --git a/R/utils.R b/R/utils.R
index 1d8961b..bf324ce 100644
--- a/R/utils.R
+++ b/R/utils.R
@@ -182,6 +182,16 @@ anyUnnamed <- function(x) {
   any(!nzchar(nms))
 }
 
+
+# Given a vector/list, returns a named vector (the labels will be blank).
+asNamedVector <- function(x) {
+  if (!is.null(names(x)))
+    return(x)
+
+  names(x) <- rep.int("", length(x))
+  x
+}
+
 # Given two named vectors, join them together, and keep only the last element
 # with a given name in the resulting vector. If b has any elements with the same
 # name as elements in a, the element in a is dropped. Also, if there are any
@@ -196,6 +206,20 @@ mergeVectors <- function(a, b) {
   x[!drop_idx]
 }
 
+# Sort a vector by the names of items. If there are multiple items with the
+# same name, preserve the original order of those items. For empty
+# vectors/lists/NULL, return the original value.
+sortByName <- function(x) {
+  if (anyUnnamed(x))
+    stop("All items must be named")
+
+  # Special case for empty vectors/lists, and NULL
+  if (length(x) == 0)
+    return(x)
+
+  x[order(names(x))]
+}
+
 # Wrapper around list2env with a NULL check. In R <3.2.0, if an empty unnamed
 # list is passed to list2env(), it errors. But an empty named list is OK. For
 # R >=3.2.0, this wrapper is not necessary.
@@ -1104,6 +1128,7 @@ reactiveStop <- function(message = "", class = NULL) {
 #' @examples
 #' ## Only run examples in interactive R sessions
 #' if (interactive()) {
+#' options(device.ask.default = FALSE)
 #'
 #' ui <- fluidPage(
 #'   checkboxGroupInput('in1', 'Check some letters', choices = head(LETTERS)),
@@ -1206,7 +1231,7 @@ need <- function(expr, message = paste(label, "must be provided"), label) {
 #' \strong{Truthy and falsy values}
 #'
 #' The terms "truthy" and "falsy" generally indicate whether a value, when
-#' coerced to a \code{\link{logical}}, is \code{TRUE} or \code{FALSE}. We use
+#' coerced to a \code{\link[base]{logical}}, is \code{TRUE} or \code{FALSE}. We use
 #' the term a little loosely here; our usage tries to match the intuitive
 #' notions of "Is this value missing or available?", or "Has the user provided
 #' an answer?", or in the case of action buttons, "Has the button been
diff --git a/README.md b/README.md
index a4b3add..fee1779 100644
--- a/README.md
+++ b/README.md
@@ -59,6 +59,10 @@ devtools::install_version("shiny", version = "0.10.2.2")
 
 The Javascript code in Shiny is minified using tools that run on Node.js. See the tools/ directory for more information.
 
+## Guidelines for contributing
+
+We welcome contributions to the **shiny** package. Please see our [CONTRIBUTING.md](CONTRIBUTING.md) file for detailed guidelines of how to contribute.
+
 ## License
 
 The shiny package is licensed under the GPLv3. See these files in the inst directory for additional details:
diff --git a/inst/examples/07_widgets/Readme.md b/inst/examples/07_widgets/Readme.md
index 7175f2b..25a4ad0 100644
--- a/inst/examples/07_widgets/Readme.md
+++ b/inst/examples/07_widgets/Readme.md
@@ -1 +1 @@
-This example demonstrates some additional widgets included in Shiny, such as `helpText` and `submitButton`. The latter is used to delay rendering output until the user explicitly requests it.
+This example demonstrates some additional widgets included in Shiny, such as `helpText` and `actionButton`. The latter is used to delay rendering output until the user explicitly requests it (a construct which also introduces two important server functions, `eventReactive` and `isolate`).
diff --git a/inst/examples/07_widgets/server.R b/inst/examples/07_widgets/server.R
index f3d7f7a..238b5bc 100644
--- a/inst/examples/07_widgets/server.R
+++ b/inst/examples/07_widgets/server.R
@@ -1,26 +1,32 @@
 library(shiny)
 library(datasets)
 
-# Define server logic required to summarize and view the 
+# Define server logic required to summarize and view the
 # selected dataset
 function(input, output) {
-  
-  # Return the requested dataset
-  datasetInput <- reactive({
+
+  # Return the requested dataset. Note that we use `eventReactive()`
+  # here, which takes a dependency on input$update (the action
+  # button), so that the output is only updated when the user
+  # clicks the button.
+  datasetInput <- eventReactive(input$update, {
     switch(input$dataset,
            "rock" = rock,
            "pressure" = pressure,
            "cars" = cars)
-  })
-  
+  }, ignoreNULL = FALSE)
+
   # Generate a summary of the dataset
   output$summary <- renderPrint({
     dataset <- datasetInput()
     summary(dataset)
   })
-  
-  # Show the first "n" observations
+
+  # Show the first "n" observations. The use of `isolate()` here
+  # is necessary because we don't want the table to update
+  # whenever input$obs changes (only when the user clicks the
+  # action button).
   output$view <- renderTable({
-    head(datasetInput(), n = input$obs)
+    head(datasetInput(), n = isolate(input$obs))
   })
 }
diff --git a/inst/examples/07_widgets/ui.R b/inst/examples/07_widgets/ui.R
index 5e50838..be59cf1 100644
--- a/inst/examples/07_widgets/ui.R
+++ b/inst/examples/07_widgets/ui.R
@@ -2,32 +2,32 @@ library(shiny)
 
 # Define UI for dataset viewer application
 fluidPage(
-  
+
   # Application title.
   titlePanel("More Widgets"),
-  
+
   # Sidebar with controls to select a dataset and specify the
   # number of observations to view. The helpText function is
   # also used to include clarifying text. Most notably, the
-  # inclusion of a submitButton defers the rendering of output
+  # inclusion of an actionButton defers the rendering of output
   # until the user explicitly clicks the button (rather than
   # doing it immediately when inputs change). This is useful if
   # the computations required to render output are inordinately
   # time-consuming.
   sidebarLayout(
     sidebarPanel(
-      selectInput("dataset", "Choose a dataset:", 
+      selectInput("dataset", "Choose a dataset:",
                   choices = c("rock", "pressure", "cars")),
-      
+
       numericInput("obs", "Number of observations to view:", 10),
-      
+
       helpText("Note: while the data view will show only the specified",
                "number of observations, the summary will still be based",
                "on the full dataset."),
-      
-      submitButton("Update View")
+
+      actionButton("update", "Update View")
     ),
-    
+
     # Show a summary of the dataset and an HTML table with the
     # requested number of observations. Note the use of the h4
     # function to provide an additional header above each output
@@ -35,7 +35,7 @@ fluidPage(
     mainPanel(
       h4("Summary"),
       verbatimTextOutput("summary"),
-      
+
       h4("Observations"),
       tableOutput("view")
     )
diff --git a/inst/staticdocs/index.r b/inst/staticdocs/index.r
index 0b633dc..a50447e 100644
--- a/inst/staticdocs/index.r
+++ b/inst/staticdocs/index.r
@@ -115,24 +115,25 @@ sd_section("Rendering functions",
     "reactiveUI"
   )
 )
-sd_section("Reactive constructs",
+sd_section("Reactive programming",
   "A sub-library that provides reactive programming facilities for R.",
   c(
-    "invalidateLater",
+    "reactive",
+    "observe",
+    "observeEvent",
+    "reactiveValues",
+    "reactiveValuesToList",
     "is.reactivevalues",
     "isolate",
+    "invalidateLater",
+    "debounce",
+    "showReactLog",
     "makeReactiveBinding",
-    "observe",
-    "observeEvent",
-    "reactive",
     "reactiveFileReader",
     "reactivePoll",
     "reactiveTimer",
-    "reactiveValues",
-    "reactiveValuesToList",
-    "freezeReactiveValue",
     "domains",
-    "showReactLog"
+    "freezeReactiveValue"
   )
 )
 sd_section("Boilerplate",
diff --git a/inst/www/shared/shiny-testmode.js b/inst/www/shared/shiny-testmode.js
new file mode 100644
index 0000000..2f78853
--- /dev/null
+++ b/inst/www/shared/shiny-testmode.js
@@ -0,0 +1,8 @@
+// Listen for messages from parent frame. This file is only added when the
+// shiny.testmode option is TRUE.
+window.addEventListener("message", function(e) {
+  var message = e.data;
+
+  if (message.code)
+    eval(message.code);
+});
diff --git a/inst/www/shared/shiny.css b/inst/www/shared/shiny.css
index e612702..1784010 100644
--- a/inst/www/shared/shiny.css
+++ b/inst/www/shared/shiny.css
@@ -1,3 +1,17 @@
+/* This is necessary so that an empty verbatimTextOutput slot
+is the same height as a non-empty one (only important when
+* placeholder = TRUE) */
+pre.shiny-text-output:empty::before {
+  content: " ";
+}
+
+pre.shiny-text-output.noplaceholder:empty {
+  margin: 0;
+  padding: 0;
+  border-width: 0;
+  height: 0;
+}
+
 #shiny-disconnected-overlay {
   position: fixed;
   top: 0;
diff --git a/inst/www/shared/shiny.js b/inst/www/shared/shiny.js
index 6225d27..e5f34b2 100644
--- a/inst/www/shared/shiny.js
+++ b/inst/www/shared/shiny.js
@@ -1160,7 +1160,8 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
         // render the HTML and deps to a null target, so
         // the side-effect of rendering the deps, singletons,
         // and <head> still occur
-        exports.renderHtml($([]), message.content.html, message.content.deps);
+        console.warn('The selector you chose ("' + message.selector + '") could not be found in the DOM.');
+        exports.renderHtml(message.content.html, $([]), message.content.deps);
       } else {
         targets.each(function (i, target) {
           exports.renderContent(target, message.content, message.where);
@@ -1314,8 +1315,22 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
 
     // Returns a URL which can be queried to get values from inside the server
     // function. This is enabled with `options(shiny.testmode=TRUE)`.
-    this.getTestEndpointUrl = function () {
-      return "session/" + encodeURIComponent(this.config.sessionId) + "/dataobj/shinytest?w=" + encodeURIComponent(this.config.workerId) + "&nonce=" + randomId();
+    this.getTestSnapshotBaseUrl = function () {
+      var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
+
+      var _ref$fullUrl = _ref.fullUrl;
+      var fullUrl = _ref$fullUrl === undefined ? true : _ref$fullUrl;
+
+      var loc = window.location;
+      var url = "";
+
+      if (fullUrl) {
+        // Strip off everything after last slash in path, like dirname() in R
+        url = loc.origin + loc.pathname.replace(/\/[^/]*$/, "");
+      }
+      url += "/session/" + encodeURIComponent(this.config.sessionId) + "/dataobj/shinytest?w=" + encodeURIComponent(this.config.workerId) + "&nonce=" + randomId();
+
+      return url;
     };
   }).call(ShinyApp.prototype);
 
@@ -1373,22 +1388,22 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
     var fadeDuration = 250;
 
     function show() {
-      var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
+      var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
 
-      var _ref$html = _ref.html;
-      var html = _ref$html === undefined ? '' : _ref$html;
-      var _ref$action = _ref.action;
-      var action = _ref$action === undefined ? '' : _ref$action;
-      var _ref$deps = _ref.deps;
-      var deps = _ref$deps === undefined ? [] : _ref$deps;
-      var _ref$duration = _ref.duration;
-      var duration = _ref$duration === undefined ? 5000 : _ref$duration;
-      var _ref$id = _ref.id;
-      var id = _ref$id === undefined ? null : _ref$id;
-      var _ref$closeButton = _ref.closeButton;
-      var closeButton = _ref$closeButton === undefined ? true : _ref$closeButton;
-      var _ref$type = _ref.type;
-      var type = _ref$type === undefined ? null : _ref$type;
+      var _ref2$html = _ref2.html;
+      var html = _ref2$html === undefined ? '' : _ref2$html;
+      var _ref2$action = _ref2.action;
+      var action = _ref2$action === undefined ? '' : _ref2$action;
+      var _ref2$deps = _ref2.deps;
+      var deps = _ref2$deps === undefined ? [] : _ref2$deps;
+      var _ref2$duration = _ref2.duration;
+      var duration = _ref2$duration === undefined ? 5000 : _ref2$duration;
+      var _ref2$id = _ref2.id;
+      var id = _ref2$id === undefined ? null : _ref2$id;
+      var _ref2$closeButton = _ref2.closeButton;
+      var closeButton = _ref2$closeButton === undefined ? true : _ref2$closeButton;
+      var _ref2$type = _ref2.type;
+      var type = _ref2$type === undefined ? null : _ref2$type;
 
       if (!id) id = randomId();
 
@@ -1532,12 +1547,12 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
     // content is non-Bootstrap. Bootstrap modals require some special handling,
     // which is coded in here.
     show: function show() {
-      var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
+      var _ref3 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
 
-      var _ref2$html = _ref2.html;
-      var html = _ref2$html === undefined ? '' : _ref2$html;
-      var _ref2$deps = _ref2.deps;
-      var deps = _ref2$deps === undefined ? [] : _ref2$deps;
+      var _ref3$html = _ref3.html;
+      var html = _ref3$html === undefined ? '' : _ref3$html;
+      var _ref3$deps = _ref3.deps;
+      var deps = _ref3$deps === undefined ? [] : _ref3$deps;
 
 
       // If there was an existing Bootstrap modal, then there will be a modal-
@@ -1561,6 +1576,20 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
         });
       }
 
+      $modal.on('keydown.shinymodal', function (e) {
+        // If we're listening for Esc, don't let the event propagate. See
+        // https://github.com/rstudio/shiny/issues/1453. The value of
+        // data("keyboard") needs to be checked inside the handler, because at
+        // the time that $modal.on() is called, the $("#shiny-modal") div doesn't
+        // yet exist.
+        if ($("#shiny-modal").data("keyboard") === false) return;
+
+        if (e.keyCode === 27) {
+          e.stopPropagation();
+          e.preventDefault();
+        }
+      });
+
       // Set/replace contents of wrapper with html.
       exports.renderContent($modal, { html: html, deps: deps });
     },
@@ -1568,6 +1597,8 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
     remove: function remove() {
       var $modal = $('#shiny-modal-wrapper');
 
+      $modal.off('keydown.shinymodal');
+
       // Look for a Bootstrap modal and if present, trigger hide event. This will
       // trigger the hidden.bs.modal callback that we set in show(), which unbinds
       // and removes the element.
@@ -3091,6 +3122,10 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
   exports.renderContent = function (el, content) {
     var where = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : "replace";
 
+    if (where === "replace") {
+      exports.unbindAll(el);
+    }
+
     exports.unbindAll(el);
 
     var html;
@@ -3148,8 +3183,10 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
     var $head = $("head").first();
 
     if (dep.meta) {
-      var metas = $.map(asArray(dep.meta), function (content, name) {
-        return $("<meta>").attr("name", name).attr("content", content);
+      var metas = $.map(asArray(dep.meta), function (obj, idx) {
+        // only one named pair is expected in obj as it's already been decomposed
+        var name = Object.keys(obj)[0];
+        return $("<meta>").attr("name", name).attr("content", obj[name]);
       });
       $head.append(metas);
     }
@@ -4742,6 +4779,18 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
         self.onError(error);
       });
       this.$bar().text('Finishing upload');
+
+      // Trigger event when all files are finished uploading.
+      var evt = jQuery.Event("shiny:fileuploaded");
+      evt.name = this.id;
+      evt.files = $.map(this.files, function (file, i) {
+        return {
+          name: file.name,
+          size: file.size,
+          type: file.type
+        };
+      });
+      $(document).trigger(evt);
     };
     this.onError = function (message) {
       this.$setError(message || '');
diff --git a/inst/www/shared/shiny.js.map b/inst/www/shared/shiny.js.map
index 7fdad4c..7cda50a 100644
--- a/inst/www/shared/shiny.js.map
+++ b/inst/www/shared/shiny.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../../srcjs/_start.js","../../srcjs/utils.js","../../srcjs/browser.js","../../srcjs/input_rate.js","../../srcjs/shinyapp.js","../../srcjs/notifications.js","../../srcjs/modal.js","../../srcjs/file_processor.js","../../srcjs/binding_registry.js","../../srcjs/output_binding.js","../../srcjs/output_binding_text.js","../../srcjs/output_binding_image.js","../../srcjs/output_binding_html.js","../../srcjs/output_binding_downloadlink.js","../../srcjs/output_binding_datat [...]
\ No newline at end of file
+{"version":3,"sources":["../../srcjs/_start.js","../../srcjs/utils.js","../../srcjs/browser.js","../../srcjs/input_rate.js","../../srcjs/shinyapp.js","../../srcjs/notifications.js","../../srcjs/modal.js","../../srcjs/file_processor.js","../../srcjs/binding_registry.js","../../srcjs/output_binding.js","../../srcjs/output_binding_text.js","../../srcjs/output_binding_image.js","../../srcjs/output_binding_html.js","../../srcjs/output_binding_downloadlink.js","../../srcjs/output_binding_datat [...]
\ No newline at end of file
diff --git a/inst/www/shared/shiny.min.js b/inst/www/shared/shiny.min.js
index ec1a6df..a32a51f 100644
--- a/inst/www/shared/shiny.min.js
+++ b/inst/www/shared/shiny.min.js
@@ -1,6 +1,6 @@
-/*! shiny 0.14.2 | (c) 2012-2016 RStudio, Inc. | License: GPL-3 | file LICENSE */
+/*! shiny 1.0.0 | (c) 2012-2017 RStudio, Inc. | License: GPL-3 | file LICENSE */
 
-"use strict";var _typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(a){return typeof a}:function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a};!function(){function escapeHTML(a){return a.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"&#x2F;")}function randomId(){return Math.floor(4294967296+64424509440*Math.random()).toString(16 [...]
-},this.onValueError=function(a,b){this.renderError(a,b)},this.renderError=function(a,b){if(this.clearError(a),""===b.message)return void $(a).empty();var c="shiny-output-error";null!==b.type&&(c=c+" "+$.map(asArray(b.type),function(a){return c+"-"+a}).join(" ")),$(a).addClass(c).text(b.message)},this.clearError=function(a){$(a).attr("class",function(a,b){return b.replace(/(^|\s)shiny-output-error\S*/g,"")})},this.showProgress=function(a,b){var c="recalculating";b?$(a).addClass(c):$(a).re [...]
-var c=this._selectize(a);"undefined"!=typeof c?c.setValue(b):$(a).val(b)},getState:function(a){for(var b=new Array(a.length),c=0;c<a.length;c++)b[c]={value:a[c].value,label:a[c].label};return{label:$(a).parent().find('label[for="'+$escape(a.id)+'"]').text(),value:this.getValue(a),options:b}},receiveMessage:function(a,b){var c,d=$(a);if(b.hasOwnProperty("options")&&(c=this._selectize(a),c&&c.destroy(),d.empty().append(b.options),this._selectize(a)),b.hasOwnProperty("config")&&(d.parent(). [...]
+"use strict";var _typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(a){return typeof a}:function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a};!function(){function escapeHTML(a){return a.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"&#x2F;")}function randomId(){return Math.floor(4294967296+64424509440*Math.random()).toString(16 [...]
+return mergeSort(this.bindings,function(a,b){return b.priority-a.priority})}}).call(BindingRegistry.prototype);var inputBindings=exports.inputBindings=new BindingRegistry,outputBindings=exports.outputBindings=new BindingRegistry,OutputBinding=exports.OutputBinding=function(){};(function(){this.find=function(a){throw"Not implemented"},this.getId=function(a){return a["data-input-id"]||a.id},this.onValueChange=function(a,b){this.clearError(a),this.renderValue(a,b)},this.onValueError=functio [...]
+b(!0)}),$(a).on("changeDate.dateRangeInputBinding change.dateRangeInputBinding",function(a){b(!1)})},unsubscribe:function(a){$(a).off(".dateRangeInputBinding")}}),inputBindings.register(dateRangeInputBinding,"shiny.dateRangeInput");var selectInputBinding=new InputBinding;$.extend(selectInputBinding,{find:function(a){return $(a).find("select")},getId:function(a){return InputBinding.prototype.getId.call(this,a)||a.name},getValue:function(a){return $(a).val()},setValue:function(a,b){var c=t [...]
 //# sourceMappingURL=shiny.min.js.map
\ No newline at end of file
diff --git a/inst/www/shared/shiny.min.js.map b/inst/www/shared/shiny.min.js.map
index a496671..816a860 100644
--- a/inst/www/shared/shiny.min.js.map
+++ b/inst/www/shared/shiny.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../../srcjs/_start.js","../../srcjs/utils.js","../../srcjs/input_rate.js","../../srcjs/output_binding_html.js","../../srcjs/input_binding_slider.js","../../srcjs/input_binding_fileinput.js","../../srcjs/init_shiny.js","../../srcjs/browser.js","../../srcjs/shinyapp.js","../../srcjs/notifications.js","../../srcjs/modal.js","../../srcjs/file_processor.js","../../srcjs/binding_registry.js","../../srcjs/output_binding.js","../../srcjs/output_binding_text.js","../../sr [...]
\ No newline at end of file
+{"version":3,"sources":["../../srcjs/_start.js","../../srcjs/utils.js","../../srcjs/input_rate.js","../../srcjs/output_binding_html.js","../../srcjs/input_binding_slider.js","../../srcjs/input_binding_fileinput.js","../../srcjs/init_shiny.js","../../srcjs/browser.js","../../srcjs/shinyapp.js","../../srcjs/notifications.js","../../srcjs/modal.js","../../srcjs/file_processor.js","../../srcjs/binding_registry.js","../../srcjs/output_binding.js","../../srcjs/output_binding_text.js","../../sr [...]
\ No newline at end of file
diff --git a/man/addResourcePath.Rd b/man/addResourcePath.Rd
index b99a8e2..492ff7a 100644
--- a/man/addResourcePath.Rd
+++ b/man/addResourcePath.Rd
@@ -8,7 +8,7 @@ addResourcePath(prefix, directoryPath)
 }
 \arguments{
 \item{prefix}{The URL prefix (without slashes). Valid characters are a-z,
-A-Z, 0-9, hyphen, period, and underscore; and must begin with a-z or 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.}
 
diff --git a/man/builder.Rd b/man/builder.Rd
index 712cb21..461e761 100644
--- a/man/builder.Rd
+++ b/man/builder.Rd
@@ -75,7 +75,7 @@ Dedicated functions are available for the most common HTML tags that do not
 conflict with common R functions.
 
 The result from these functions is a tag object, which can be converted using
-\code{\link{as.character}()}.
+\code{\link[base]{as.character}()}.
 }
 \examples{
 doc <- tags$html(
diff --git a/man/dateInput.Rd b/man/dateInput.Rd
index fef0fc0..d3e403c 100644
--- a/man/dateInput.Rd
+++ b/man/dateInput.Rd
@@ -56,7 +56,7 @@ the browser. It allows the following values:
   \item \code{yy} Year without century (12)
   \item \code{yyyy} Year with century (2012)
   \item \code{mm} Month number, with leading zero (01-12)
-  \item \code{m} Month number, without leading zero (01-12)
+  \item \code{m} Month number, without leading zero (1-12)
   \item \code{M} Abbreviated month name
   \item \code{MM} Full month name
   \item \code{dd} Day of month with leading zero
diff --git a/man/dateRangeInput.Rd b/man/dateRangeInput.Rd
index 0c72c12..7a6cb11 100644
--- a/man/dateRangeInput.Rd
+++ b/man/dateRangeInput.Rd
@@ -62,7 +62,7 @@ the browser. It allows the following values:
   \item \code{yy} Year without century (12)
   \item \code{yyyy} Year with century (2012)
   \item \code{mm} Month number, with leading zero (01-12)
-  \item \code{m} Month number, without leading zero (01-12)
+  \item \code{m} Month number, without leading zero (1-12)
   \item \code{M} Abbreviated month name
   \item \code{MM} Full month name
   \item \code{dd} Day of month with leading zero
diff --git a/man/debounce.Rd b/man/debounce.Rd
new file mode 100644
index 0000000..37803da
--- /dev/null
+++ b/man/debounce.Rd
@@ -0,0 +1,122 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/reactives.R
+\name{debounce}
+\alias{debounce}
+\alias{throttle}
+\title{Slow down a reactive expression with debounce/throttle}
+\usage{
+debounce(r, millis, priority = 100, domain = getDefaultReactiveDomain())
+
+throttle(r, millis, priority = 100, domain = getDefaultReactiveDomain())
+}
+\arguments{
+\item{r}{A reactive expression (that invalidates too often).}
+
+\item{millis}{The debounce/throttle time window. You may optionally pass a
+no-arg function or reactive expression instead, e.g. to let the end-user
+control the time window.}
+
+\item{priority}{Debounce/throttle is implemented under the hood using
+\link[=observe]{observers}. Use this parameter to set the priority of
+these observers. Generally, this should be higher than the priorities of
+downstream observers and outputs (which default to zero).}
+
+\item{domain}{See \link{domains}.}
+}
+\description{
+Transforms a reactive expression by preventing its invalidation signals from
+being sent unnecessarily often. This lets you ignore a very "chatty" reactive
+expression until it becomes idle, which is useful when the intermediate
+values don't matter as much as the final value, and the downstream
+calculations that depend on the reactive expression take a long time.
+\code{debounce} and \code{throttle} use different algorithms for slowing down
+invalidation signals; see Details.
+}
+\details{
+This is not a true debounce/throttle in that it will not prevent \code{r}
+from being called many times (in fact it may be called more times than
+usual), but rather, the reactive invalidation signal that is produced by
+\code{r} is debounced/throttled instead. Therefore, these functions should be
+used when \code{r} is cheap but the things it will trigger (downstream
+outputs and reactives) are expensive.
+
+Debouncing means that every invalidation from \code{r} will be held for the
+specified time window. If \code{r} invalidates again within that time window,
+then the timer starts over again. This means that as long as invalidations
+continually arrive from \code{r} within the time window, the debounced
+reactive will not invalidate at all. Only after the invalidations stop (or
+slow down sufficiently) will the downstream invalidation be sent.
+
+\code{ooo-oo-oo---- => -----------o-}
+
+(In this graphical depiction, each character represents a unit of time, and
+the time window is 3 characters.)
+
+Throttling, on the other hand, delays invalidation if the \emph{throttled}
+reactive recently (within the time window) invalidated. New \code{r}
+invalidations do not reset the time window. This means that if invalidations
+continually come from \code{r} within the time window, the throttled reactive
+will invalidate regularly, at a rate equal to or slower than than the time
+window.
+
+\code{ooo-oo-oo---- => o--o--o--o---}
+}
+\section{Limitations}{
+
+
+  Because R is single threaded, we can't come close to guaranteeing that the
+  timing of debounce/throttle (or any other timing-related functions in
+  Shiny) will be consistent or accurate; at the time we want to emit an
+  invalidation signal, R may be performing a different task and we have no
+  way to interrupt it (nor would we necessarily want to if we could).
+  Therefore, it's best to think of the time windows you pass to these
+  functions as minimums.
+
+  You may also see undesirable behavior if the amount of time spent doing
+  downstream processing for each change approaches or exceeds the time
+  window: in this case, debounce/throttle may not have any effect, as the
+  time each subsequent event is considered is already after the time window
+  has expired.
+}
+\examples{
+## Only run examples in interactive R sessions
+if (interactive()) {
+options(device.ask.default = FALSE)
+
+library(shiny)
+library(magrittr)
+
+ui <- fluidPage(
+  plotOutput("plot", click = clickOpts("hover")),
+  helpText("Quickly click on the plot above, while watching the result table below:"),
+  tableOutput("result")
+)
+
+server <- function(input, output, session) {
+  hover <- reactive({
+    if (is.null(input$hover))
+      list(x = NA, y = NA)
+    else
+      input$hover
+  })
+  hover_d <- hover \%>\% debounce(1000)
+  hover_t <- hover \%>\% throttle(1000)
+
+  output$plot <- renderPlot({
+    plot(cars)
+  })
+
+  output$result <- renderTable({
+    data.frame(
+      mode = c("raw", "throttle", "debounce"),
+      x = c(hover()$x, hover_t()$x, hover_d()$x),
+      y = c(hover()$y, hover_t()$y, hover_d()$y)
+    )
+  })
+}
+
+shinyApp(ui, server)
+}
+
+}
+
diff --git a/man/downloadButton.Rd b/man/downloadButton.Rd
index 32b7728..5a5018e 100644
--- a/man/downloadButton.Rd
+++ b/man/downloadButton.Rd
@@ -5,9 +5,9 @@
 \alias{downloadLink}
 \title{Create a download button or link}
 \usage{
-downloadButton(outputId, label = "Download", class = NULL)
+downloadButton(outputId, label = "Download", class = NULL, ...)
 
-downloadLink(outputId, label = "Download", class = NULL)
+downloadLink(outputId, label = "Download", class = NULL, ...)
 }
 \arguments{
 \item{outputId}{The name of the output slot that the \code{downloadHandler}
@@ -16,6 +16,8 @@ is assigned to.}
 \item{label}{The label that should appear on the button.}
 
 \item{class}{Additional CSS classes to apply to the tag, if any.}
+
+\item{...}{Other arguments to pass to the container tag function.}
 }
 \description{
 Use these functions to create a download button or link; when clicked, it
diff --git a/man/exportTestValues.Rd b/man/exportTestValues.Rd
index bcfbbc8..a11f3ca 100644
--- a/man/exportTestValues.Rd
+++ b/man/exportTestValues.Rd
@@ -9,7 +9,7 @@ exportTestValues(..., quoted_ = FALSE, env_ = parent.frame(),
 }
 \arguments{
 \item{...}{Named arguments that are quoted or unquoted expressions that will
-be captured and evaluated when API endpoint is visited.}
+be captured and evaluated when snapshot URL is visited.}
 
 \item{quoted_}{Are the expression quoted? Default is \code{FALSE}.}
 
@@ -19,11 +19,12 @@ be captured and evaluated when API endpoint is visited.}
 }
 \description{
 This function registers expressions that will be evaluated when a test export
-event occurs. These events are triggered by accessing an API endpoint URL.
+event occurs. These events are triggered by accessing a snapshot URL.
 }
 \details{
-This function only has an effect if the global option \code{shiny.testmode}
-is set to \code{TRUE}.
+This function only has an effect if the app is launched in test mode. This is
+done by calling \code{runApp()} with \code{test.mode=TRUE}, or by setting the
+global option \code{shiny.testmode} to \code{TRUE}.
 }
 \examples{
 ## Only run this example in interactive R sessions
@@ -31,7 +32,7 @@ if (interactive()) {
 
 options(shiny.testmode = TRUE)
 
-# This application shows the test endpoint URL; clicking on it will
+# This application shows the test snapshot URL; clicking on it will
 # fetch the input, output, and exported values in JSON format.
 shinyApp(
   ui = basicPage(
@@ -56,7 +57,7 @@ shinyApp(
     )
 
     output$url <- renderUI({
-      url <- session$getTestEndpointUrl(format="json")
+      url <- session$getTestSnapshotUrl(format="json")
       a(href = url, url)
     })
 
diff --git a/man/isolate.Rd b/man/isolate.Rd
index 3bb4ff6..61a3a63 100644
--- a/man/isolate.Rd
+++ b/man/isolate.Rd
@@ -25,7 +25,7 @@ relationship.
 The expression given to \code{isolate()} is evaluated in the calling
 environment. This means that if you assign a variable inside the
 \code{isolate()}, its value will be visible outside of the \code{isolate()}.
-If you want to avoid this, you can use \code{\link{local}()} inside the
+If you want to avoid this, you can use \code{\link[base]{local}()} inside the
 \code{isolate()}.
 
 This function can also be useful for calling reactive expression at the
diff --git a/man/observeEvent.Rd b/man/observeEvent.Rd
index 889d3e7..d95aa0d 100644
--- a/man/observeEvent.Rd
+++ b/man/observeEvent.Rd
@@ -9,11 +9,12 @@ observeEvent(eventExpr, handlerExpr, event.env = parent.frame(),
   event.quoted = FALSE, handler.env = parent.frame(),
   handler.quoted = FALSE, label = NULL, suspended = FALSE, priority = 0,
   domain = getDefaultReactiveDomain(), autoDestroy = TRUE,
-  ignoreNULL = TRUE)
+  ignoreNULL = TRUE, ignoreInit = FALSE, once = FALSE)
 
 eventReactive(eventExpr, valueExpr, event.env = parent.frame(),
   event.quoted = FALSE, value.env = parent.frame(), value.quoted = FALSE,
-  label = NULL, domain = getDefaultReactiveDomain(), ignoreNULL = TRUE)
+  label = NULL, domain = getDefaultReactiveDomain(), ignoreNULL = TRUE,
+  ignoreInit = FALSE)
 }
 \arguments{
 \item{eventExpr}{A (quoted or unquoted) expression that represents the event;
@@ -61,6 +62,16 @@ automatically destroyed when its domain (if any) ends.}
 calculated, in the case of \code{eventReactive}) when the input is
 \code{NULL}. See Details.}
 
+\item{ignoreInit}{If \code{TRUE}, then, when this \code{observeEvent} is
+first created/initialized, ignore the \code{handlerExpr} (the second
+argument), whether it is otherwise supposed to run or not. The default is
+\code{FALSE}. See Details.}
+
+\item{once}{Whether this \code{observeEvent} should be immediately destroyed
+after the first time that the code in \code{handlerExpr} is run. This
+pattern is useful when you want to subscribe to a event that should only
+happen once.}
+
 \item{valueExpr}{The expression that produces the return value of the
 \code{eventReactive}. It will be executed within an \code{\link{isolate}}
 scope.}
@@ -108,6 +119,9 @@ updates in response to an event. This is just like a normal
 \link[=reactive]{reactive expression} except it ignores all the usual
 invalidations that come from its reactive dependencies; it only invalidates
 in response to the given event.
+}
+\section{\code{ignoreNULL} and \code{ignoreInit}}{
+
 
 Both \code{observeEvent} and \code{eventReactive} take an \code{ignoreNULL}
 parameter that affects behavior when the \code{eventExpr} evaluates to
@@ -120,34 +134,105 @@ wait for the user to initiate the action first (like a "Submit" button);
 whereas \code{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).
+
+Unlike what happens for \code{ignoreNULL}, only \code{observeEvent} takes in an
+\code{ignoreInit} argument. By default, \code{observeEvent} will run right when
+it is created (except if, at that moment, \code{eventExpr} evaluates to \code{NULL}
+and \code{ignoreNULL} is \code{TRUE}). But when responding to a click of an action
+button, it may often be useful to set \code{ignoreInit} to \code{TRUE}. For
+example, if you're setting up an \code{observeEvent} for a dynamically created
+button, then \code{ignoreInit = TRUE} will guarantee that the action (in
+\code{handlerExpr}) will only be triggered when the button is actually clicked,
+instead of also being triggered when it is created/initialized.
+
+Even though \code{ignoreNULL} and \code{ignoreInit} can be used for similar
+purposes they are independent from one another. Here's the result of combining
+these:
+
+\describe{
+  \item{\code{ignoreNULL = TRUE} and \code{ignoreInit = FALSE}}{
+     This is the default. This combination means that \code{handlerExpr} will
+     run every time that \code{eventExpr} is not \code{NULL}. If, at the time
+     of the \code{observeEvent}'s creation, \code{handleExpr} happens to
+     \emph{not} be \code{NULL}, then the code runs.
+  }
+  \item{\code{ignoreNULL = FALSE} and \code{ignoreInit = FALSE}}{
+     This combination means that \code{handlerExpr} will run every time no
+     matter what.
+  }
+  \item{\code{ignoreNULL = FALSE} and \code{ignoreInit = TRUE}}{
+     This combination means that \code{handlerExpr} will \emph{not} run when
+     the \code{observeEvent} is created (because \code{ignoreInit = TRUE}),
+     but it will run every other time.
+  }
+  \item{\code{ignoreNULL = TRUE} and \code{ignoreInit = TRUE}}{
+     This combination means that \code{handlerExpr} will \emph{not} run when
+     the \code{observeEvent} is created (because \code{ignoreInit = TRUE}).
+     After that, \code{handlerExpr} will run every time that \code{eventExpr}
+     is not \code{NULL}.
+  }
+}
 }
 \examples{
 ## Only run this example in interactive R sessions
 if (interactive()) {
-  ui <- fluidPage(
-    column(4,
-      numericInput("x", "Value", 5),
-      br(),
-      actionButton("button", "Show")
+
+  ## App 1: Sample usage
+  shinyApp(
+    ui = fluidPage(
+      column(4,
+        numericInput("x", "Value", 5),
+        br(),
+        actionButton("button", "Show")
+      ),
+      column(8, tableOutput("table"))
     ),
-    column(8, tableOutput("table"))
+    server = function(input, output) {
+      # Take an action every time button is pressed;
+      # here, we just print a message to the console
+      observeEvent(input$button, {
+        cat("Showing", input$x, "rows\\n")
+      })
+      # Take a reactive dependency on input$button, but
+      # not on any of the stuff inside the function
+      df <- eventReactive(input$button, {
+        head(cars, input$x)
+      })
+      output$table <- renderTable({
+        df()
+      })
+    }
+  )
+
+  ## App 2: Using `once`
+  shinyApp(
+    ui = basicPage( actionButton("go", "Go")),
+    server = function(input, output, session) {
+      observeEvent(input$go, {
+        print(paste("This will only be printed once; all",
+              "subsequent button clicks won't do anything"))
+      }, once = TRUE)
+    }
+  )
+
+  ## App 3: Using `ignoreInit` and `once`
+  shinyApp(
+    ui = basicPage(actionButton("go", "Go")),
+    server = function(input, output, session) {
+      observeEvent(input$go, {
+        insertUI("#go", "afterEnd",
+                 actionButton("dynamic", "click to remove"))
+
+        # set up an observer that depends on the dynamic
+        # input, so that it doesn't run when the input is
+        # created, and only runs once after that (since
+        # the side effect is remove the input from the DOM)
+        observeEvent(input$dynamic, {
+          removeUI("#dynamic")
+        }, ignoreInit = TRUE, once = TRUE)
+      })
+    }
   )
-  server <- function(input, output) {
-    # Take an action every time button is pressed;
-    # here, we just print a message to the console
-    observeEvent(input$button, {
-      cat("Showing", input$x, "rows\\n")
-    })
-    # Take a reactive dependency on input$button, but
-    # not on any of the stuff inside the function
-    df <- eventReactive(input$button, {
-      head(cars, input$x)
-    })
-    output$table <- renderTable({
-      df()
-    })
-  }
-  shinyApp(ui=ui, server=server)
 }
 }
 \seealso{
diff --git a/man/plotOutput.Rd b/man/plotOutput.Rd
index 376027c..5b4ff79 100644
--- a/man/plotOutput.Rd
+++ b/man/plotOutput.Rd
@@ -86,7 +86,7 @@ application page.
 }
 \note{
 The arguments \code{clickId} and \code{hoverId} only work for R base
-  graphics (see the \pkg{\link{graphics}} package). They do not work for
+  graphics (see the \pkg{\link[graphics:graphics-package]{graphics}} package). They do not work for
   \pkg{\link[grid:grid-package]{grid}}-based graphics, such as \pkg{ggplot2},
   \pkg{lattice}, and so on.
 }
diff --git a/man/plotPNG.Rd b/man/plotPNG.Rd
index a1c1981..a300c3f 100644
--- a/man/plotPNG.Rd
+++ b/man/plotPNG.Rd
@@ -18,7 +18,7 @@ extension \code{.png}.}
 \item{height}{Height in pixels.}
 
 \item{res}{Resolution in pixels per inch. This value is passed to
-\code{\link{png}}. Note that this affects the resolution of PNG rendering in
+\code{\link[grDevices]{png}}. Note that this affects the resolution of PNG rendering in
 R; it won't change the actual ppi of the browser.}
 
 \item{...}{Arguments to be passed through to \code{\link[grDevices]{png}}.
diff --git a/man/reactiveTimer.Rd b/man/reactiveTimer.Rd
index d81a2e9..ec47226 100644
--- a/man/reactiveTimer.Rd
+++ b/man/reactiveTimer.Rd
@@ -18,7 +18,7 @@ occur.}
 A no-parameter function that can be called from a reactive context,
   in order to cause that context to be invalidated the next time the timer
   interval elapses. Calling the returned function also happens to yield the
-  current time (as in \code{\link{Sys.time}}).
+  current time (as in \code{\link[base]{Sys.time}}).
 }
 \description{
 Creates a reactive timer with the given interval. A reactive timer is like a
diff --git a/man/reactiveValuesToList.Rd b/man/reactiveValuesToList.Rd
index 86028bb..5bef437 100644
--- a/man/reactiveValuesToList.Rd
+++ b/man/reactiveValuesToList.Rd
@@ -13,7 +13,7 @@ reactiveValuesToList(x, all.names = FALSE)
 \code{FALSE} (the default) don't include those objects.}
 }
 \description{
-This function does something similar to what you might \code{\link{as.list}}
+This function does something similar to what you might \code{\link[base]{as.list}}
 to do. The difference is that the calling context will take dependencies on
 every object in the reactivevalues object. To avoid taking dependencies on
 all the objects, you can wrap the call with \code{\link{isolate}()}.
diff --git a/man/renderDataTable.Rd b/man/renderDataTable.Rd
index 7033ef9..355c68f 100644
--- a/man/renderDataTable.Rd
+++ b/man/renderDataTable.Rd
@@ -45,7 +45,7 @@ the server infrastructure.
 }
 \details{
 For the \code{options} argument, the character elements that have the class
-\code{"AsIs"} (usually returned from \code{\link{I}()}) will be evaluated in
+\code{"AsIs"} (usually returned from \code{\link[base]{I}()}) will be evaluated in
 JavaScript. This is useful when the type of the option value is not supported
 in JSON, e.g., a JavaScript function, which can be obtained by evaluating a
 character string. Note this only applies to the root-level elements of the
diff --git a/man/renderImage.Rd b/man/renderImage.Rd
index cb820ef..170217f 100644
--- a/man/renderImage.Rd
+++ b/man/renderImage.Rd
@@ -47,6 +47,7 @@ the CSS class name \code{shiny-image-output}.
 \examples{
 ## Only run examples in interactive R sessions
 if (interactive()) {
+options(device.ask.default = FALSE)
 
 ui <- fluidPage(
   sliderInput("n", "Number of observations", 2, 1000, 500),
diff --git a/man/renderPlot.Rd b/man/renderPlot.Rd
index a178f37..0c49444 100644
--- a/man/renderPlot.Rd
+++ b/man/renderPlot.Rd
@@ -20,7 +20,7 @@ inline plot, you must provide numeric values (in pixels) to both
 \code{width} and \code{height}.}
 
 \item{res}{Resolution of resulting plot, in pixels per inch. This value is
-passed to \code{\link{png}}. Note that this affects the resolution of PNG
+passed to \code{\link[grDevices]{png}}. Note that this affects the resolution of PNG
 rendering in R; it won't change the actual ppi of the browser.}
 
 \item{...}{Arguments to be passed through to \code{\link[grDevices]{png}}.
diff --git a/man/renderPrint.Rd b/man/renderPrint.Rd
index 0cde079..aa29727 100644
--- a/man/renderPrint.Rd
+++ b/man/renderPrint.Rd
@@ -16,7 +16,7 @@ object.}
 \item{quoted}{Is \code{expr} a quoted expression (with \code{quote()})? This
 is useful if you want to save an expression in a variable.}
 
-\item{width}{The value for \code{\link{options}('width')}.}
+\item{width}{The value for \code{\link[base]{options}('width')}.}
 
 \item{outputArgs}{A list of arguments to be passed through to the implicit
 call to \code{\link{verbatimTextOutput}} when \code{renderPrint} is used
@@ -25,7 +25,7 @@ in an interactive R Markdown document.}
 \description{
 Makes a reactive version of the given function that captures any printed
 output, and also captures its printable result (unless
-\code{\link{invisible}}), into a string. The resulting function is suitable
+\code{\link[base]{invisible}}), into a string. The resulting function is suitable
 for assigning to an  \code{output} slot.
 }
 \details{
@@ -38,7 +38,7 @@ The result of executing \code{func} will be printed inside a
 
 Note that unlike most other Shiny output functions, if the given function
 returns \code{NULL} then \code{NULL} will actually be visible in the output.
-To display nothing, make your function return \code{\link{invisible}()}.
+To display nothing, make your function return \code{\link[base]{invisible}()}.
 }
 \examples{
 isolate({
diff --git a/man/req.Rd b/man/req.Rd
index 8e8f9d5..3fdd5d6 100644
--- a/man/req.Rd
+++ b/man/req.Rd
@@ -60,7 +60,7 @@ way to check for a value "inline" with its first use.
 \strong{Truthy and falsy values}
 
 The terms "truthy" and "falsy" generally indicate whether a value, when
-coerced to a \code{\link{logical}}, is \code{TRUE} or \code{FALSE}. We use
+coerced to a \code{\link[base]{logical}}, is \code{TRUE} or \code{FALSE}. We use
 the term a little loosely here; our usage tries to match the intuitive
 notions of "Is this value missing or available?", or "Has the user provided
 an answer?", or in the case of action buttons, "Has the button been
diff --git a/man/runApp.Rd b/man/runApp.Rd
index 2f274bc..d4d620d 100644
--- a/man/runApp.Rd
+++ b/man/runApp.Rd
@@ -7,7 +7,8 @@
 runApp(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"))
+  quiet = FALSE, display.mode = c("auto", "normal", "showcase"),
+  test.mode = getOption("shiny.testmode", FALSE))
 }
 \arguments{
 \item{appDir}{The application to run. Should be one of the following:
@@ -46,6 +47,10 @@ the value \code{"showcase"}, shows application code and metadata from a
 application. If set to \code{"normal"}, displays the application normally.
 Defaults to \code{"auto"}, which displays the application in the mode given
 in its \code{DESCRIPTION} file, if any.}
+
+\item{test.mode}{Should the application be launched in test mode? This is
+only used for recording or running automated tests. Defaults to the
+\code{shiny.testmode} option, or FALSE if the option is not set.}
 }
 \description{
 Runs a Shiny application. This function normally does not return; interrupt R
@@ -69,6 +74,8 @@ 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(
diff --git a/man/selectInput.Rd b/man/selectInput.Rd
index eb41a7c..eaafef8 100644
--- a/man/selectInput.Rd
+++ b/man/selectInput.Rd
@@ -16,7 +16,12 @@ selectizeInput(inputId, ..., options = NULL, width = NULL)
 \item{label}{Display label for the control, or \code{NULL} for no label.}
 
 \item{choices}{List of values to select from. If elements of the list are
-named then that name rather than the value is displayed to the user.}
+named, then that name rather than the value is displayed to the user.
+This can also be a named list whose elements are (either named or
+unnamed) lists or vectors. If this is the case, the outermost names
+will be used as the "optgroup" label for the elements in the respective
+sublist. This allows you to group and label similar choices. See the
+example section for a small demo of this feature.}
 
 \item{selected}{The initially selected value (or multiple values if
 \code{multiple = TRUE}). If not specified then defaults to the first value
@@ -37,7 +42,7 @@ list, but when \code{size} is set, it will be a box instead.}
 \item{...}{Arguments passed to \code{selectInput()}.}
 
 \item{options}{A list of options. See the documentation of \pkg{selectize.js}
-for possible options (character option values inside \code{\link{I}()} will
+for possible options (character option values inside \code{\link[base]{I}()} will
 be treated as literal JavaScript code; see \code{\link{renderDataTable}()}
 for details).}
 }
@@ -73,21 +78,38 @@ The selectize input created from \code{selectizeInput()} allows
 ## Only run examples in interactive R sessions
 if (interactive()) {
 
-ui <- fluidPage(
-  selectInput("variable", "Variable:",
-              c("Cylinders" = "cyl",
-                "Transmission" = "am",
-                "Gears" = "gear")),
-  tableOutput("data")
+# 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)
+  }
 )
 
-server <- function(input, output) {
-  output$data <- renderTable({
-    mtcars[, c("mpg", input$variable), drop = FALSE]
-  }, rownames = TRUE)
-}
-
-shinyApp(ui, server)
+# demoing optgroup support in the `choices` arg
+shinyApp(
+  ui = fluidPage(
+    selectInput("state", "Choose a state:",
+      list(`East Coast` = c("NY", "NJ", "CT"),
+           `West Coast` = c("WA", "OR", "CA"),
+           `Midwest` = c("MN", "WI", "IA"))
+    ),
+    textOutput("result")
+  ),
+  server = function(input, output) {
+    output$result <- renderText({
+      paste("You chose", input$state)
+    })
+  }
+)
 }
 }
 \seealso{
diff --git a/man/session.Rd b/man/session.Rd
index 50ef6ea..ff5c508 100644
--- a/man/session.Rd
+++ b/man/session.Rd
@@ -102,6 +102,10 @@
   This is the request that was used to initiate the websocket connection
   (as opposed to the request that downloaded the web page for the app).
 }
+\item{userData}{
+  An environment for app authors and module/package authors to store whatever
+  session-specific data they want.
+}
 \item{resetBrush(brushId)}{
   Resets/clears the brush with the given \code{brushId}, if it exists on
   any \code{imageOutput} or \code{plotOutput} in the app.
@@ -157,15 +161,15 @@
 }
 \item{exportTestValues()}{
   Registers expressions for export in test mode, available at the test
-  endpoint URL.
+  snapshot URL.
 }
-\item{getTestEndpointUrl(inputs=TRUE, outputs=TRUE, exports=TRUE,
-  format="rds")}{
-  Returns a URL for the test endpoint. Only has an effect when the
-  \code{shiny.testmode} option is set to TRUE. For the inputs, outputs, and
-  exports arguments, TRUE means to return all of these values. It is also
+\item{getTestSnapshotUrl(input=TRUE, output=TRUE, export=TRUE,
+  format="json")}{
+  Returns a URL for the test snapshots. Only has an effect when the
+  \code{shiny.testmode} option is set to TRUE. For the input, output, and
+  export arguments, TRUE means to return all of these values. It is also
   possible to specify by name which values to return by providing a
-  character vector, as in \code{inputs=c("x", "y")}. The format can be
+  character vector, as in \code{input=c("x", "y")}. The format can be
   "rds" or "json".
 }
 }
diff --git a/man/shinyApp.Rd b/man/shinyApp.Rd
index 81e9d66..122d990 100644
--- a/man/shinyApp.Rd
+++ b/man/shinyApp.Rd
@@ -44,9 +44,11 @@ is.shiny.appobj(x)
 This is only needed for \code{shinyAppObj}, since in the \code{shinyAppDir}
 case, a \code{global.R} file can be used for this purpose.}
 
-\item{options}{Named options that should be passed to the `runApp` call. You
-can also specify \code{width} and \code{height} parameters which provide a
-hint to the embedding environment about the ideal height/width for the app.}
+\item{options}{Named options that should be passed to the \code{runApp} call
+(these can be any of the following: "port", "launch.browser", "host", "quiet",
+"display.mode" and "test.mode"). You can also specify \code{width} and
+\code{height} parameters which provide a hint to the embedding environment
+about the ideal height/width for the app.}
 
 \item{uiPattern}{A regular expression that will be applied to each \code{GET}
 request to determine whether the \code{ui} should be used to handle the
@@ -90,6 +92,8 @@ object to \code{print()} or \code{\link{runApp}()}.
 \examples{
 ## Only run this example in interactive R sessions
 if (interactive()) {
+  options(device.ask.default = FALSE)
+
   shinyApp(
     ui = fluidPage(
       numericInput("n", "n", 1),
diff --git a/man/sidebarLayout.Rd b/man/sidebarLayout.Rd
index 31a3ed2..4a5848a 100644
--- a/man/sidebarLayout.Rd
+++ b/man/sidebarLayout.Rd
@@ -26,6 +26,7 @@ area occupies 2/3 of the horizontal width and typically contains outputs.
 \examples{
 ## Only run examples in interactive R sessions
 if (interactive()) {
+options(device.ask.default = FALSE)
 
 # Define UI
 ui <- fluidPage(
diff --git a/man/sliderInput.Rd b/man/sliderInput.Rd
index 0bb2171..a4ff1be 100644
--- a/man/sliderInput.Rd
+++ b/man/sliderInput.Rd
@@ -62,7 +62,7 @@ see \code{\link{validateCssUnit}}.}
 format string, to be passed to the Javascript strftime library. See
 \url{https://github.com/samsonjs/strftime} for more details. The allowed
 format specifications are very similar, but not identical, to those for R's
-\code{\link{strftime}} function. For Dates, the default is \code{"\%F"}
+\code{\link[base]{strftime}} function. For Dates, the default is \code{"\%F"}
 (like \code{"2015-07-01"}), and for POSIXt, the default is \code{"\%F \%T"}
 (like \code{"2015-07-01 15:32:10"}).}
 
@@ -95,6 +95,7 @@ Constructs a slider widget to select a numeric value from a range.
 \examples{
 ## Only run examples in interactive R sessions
 if (interactive()) {
+options(device.ask.default = FALSE)
 
 ui <- fluidPage(
   sliderInput("obs", "Number of observations:",
diff --git a/man/splitLayout.Rd b/man/splitLayout.Rd
index 465cbbf..0920e49 100644
--- a/man/splitLayout.Rd
+++ b/man/splitLayout.Rd
@@ -25,6 +25,7 @@ equal parts (by default).
 \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) {
diff --git a/man/submitButton.Rd b/man/submitButton.Rd
index 6ce82aa..9aeb5fe 100644
--- a/man/submitButton.Rd
+++ b/man/submitButton.Rd
@@ -18,13 +18,51 @@ see \code{\link{validateCssUnit}}.}
 A submit button that can be added to a UI definition.
 }
 \description{
-Create a submit button for an input form. Forms that include a submit
+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 \code{submitButton} is generally discouraged in favor of
+the more versatile \code{\link{actionButton}} (see details below).
+}
+\details{
+Submit buttons are unusual Shiny inputs, and we recommend using
+\code{\link{actionButton}} instead of \code{submitButton} when you
+want to delay a reaction.
+See \href{http://shiny.rstudio.com/articles/action-buttons.html}{this
+article} for more information (including a demo of how to "translate"
+code using a \code{submitButton} to code using an \code{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 \emph{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 \code{\link{renderUI}}
+or \code{\link{insertUI}}) will not work.
 }
 \examples{
-submitButton("Update View")
-submitButton("Update View", icon("refresh"))
+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 })
+  }
+)
+}
 }
 \seealso{
 Other input.elements: \code{\link{actionButton}},
diff --git a/man/tag.Rd b/man/tag.Rd
index 51fc2ac..05db944 100644
--- a/man/tag.Rd
+++ b/man/tag.Rd
@@ -39,7 +39,7 @@ contain tags, text nodes, and HTML.}
 }
 \value{
 An HTML tag object that can be rendered as HTML using
-  \code{\link{as.character}()}.
+  \code{\link[base]{as.character}()}.
 }
 \description{
 \code{tag()} creates an HTML tag definition. Note that all of the valid HTML5
diff --git a/man/updateSelectInput.Rd b/man/updateSelectInput.Rd
index 57b4108..6c3f5a6 100644
--- a/man/updateSelectInput.Rd
+++ b/man/updateSelectInput.Rd
@@ -20,14 +20,19 @@ updateSelectizeInput(session, inputId, label = NULL, choices = NULL,
 \item{label}{The label to set for the input object.}
 
 \item{choices}{List of values to select from. If elements of the list are
-named then that name rather than the value is displayed to the user.}
+named, then that name rather than the value is displayed to the user.
+This can also be a named list whose elements are (either named or
+unnamed) lists or vectors. If this is the case, the outermost names
+will be used as the "optgroup" label for the elements in the respective
+sublist. This allows you to group and label similar choices. See the
+example section for a small demo of this feature.}
 
 \item{selected}{The initially selected value (or multiple values if
 \code{multiple = TRUE}). If not specified then defaults to the first value
 for single-select lists and no values for multiple select lists.}
 
 \item{options}{A list of options. See the documentation of \pkg{selectize.js}
-for possible options (character option values inside \code{\link{I}()} will
+for possible options (character option values inside \code{\link[base]{I}()} will
 be treated as literal JavaScript code; see \code{\link{renderDataTable}()}
 for details).}
 
diff --git a/man/validate.Rd b/man/validate.Rd
index befa483..9f2ba52 100644
--- a/man/validate.Rd
+++ b/man/validate.Rd
@@ -80,6 +80,7 @@ as \code{a} does validate it.
 \examples{
 ## Only run examples in interactive R sessions
 if (interactive()) {
+options(device.ask.default = FALSE)
 
 ui <- fluidPage(
   checkboxGroupInput('in1', 'Check some letters', choices = head(LETTERS)),
diff --git a/man/verbatimTextOutput.Rd b/man/verbatimTextOutput.Rd
index 94f65e2..05fd583 100644
--- a/man/verbatimTextOutput.Rd
+++ b/man/verbatimTextOutput.Rd
@@ -4,10 +4,14 @@
 \alias{verbatimTextOutput}
 \title{Create a verbatim text output element}
 \usage{
-verbatimTextOutput(outputId)
+verbatimTextOutput(outputId, placeholder = FALSE)
 }
 \arguments{
 \item{outputId}{output variable to read the value from}
+
+\item{placeholder}{if the output is empty or \code{NULL}, should an empty
+rectangle be displayed to serve as a placeholder? (does not affect
+behavior when the the output in nonempty)}
 }
 \value{
 A verbatim text output element that can be included in a panel
@@ -18,16 +22,23 @@ application page. The text will be included within an HTML \code{pre} tag.
 }
 \details{
 Text is HTML-escaped prior to rendering. This element is often used
-with the \link{renderPrint} function to preserve fixed-width formatting
-of printed objects.
+  with the \link{renderPrint} function to preserve fixed-width formatting
+  of printed objects.
 }
 \examples{
-mainPanel(
-  h4("Summary"),
-  verbatimTextOutput("summary"),
-
-  h4("Observations"),
-  tableOutput("view")
-)
+## Only run this example in interactive R sessions
+if (interactive()) {
+  shinyApp(
+    ui = basicPage(
+      textInput("txt", "Enter the text to display below:"),
+      verbatimTextOutput("default"),
+      verbatimTextOutput("placeholder", placeholder = TRUE)
+    ),
+    server = function(input, output) {
+      output$default <- renderText({ input$txt })
+      output$placeholder <- renderText({ input$txt })
+    }
+  )
+}
 }
 
diff --git a/man/withProgress.Rd b/man/withProgress.Rd
index 86fd3ee..53298ce 100644
--- a/man/withProgress.Rd
+++ b/man/withProgress.Rd
@@ -90,6 +90,7 @@ function.
 \examples{
 ## Only run examples in interactive R sessions
 if (interactive()) {
+options(device.ask.default = FALSE)
 
 ui <- fluidPage(
   plotOutput("plot")
diff --git a/tests/testthat/test-reactivity.r b/tests/testthat/test-reactivity.r
index 51c4537..9f5edcb 100644
--- a/tests/testthat/test-reactivity.r
+++ b/tests/testthat/test-reactivity.r
@@ -976,3 +976,83 @@ test_that("event handling helpers take correct dependencies", {
   expect_equal(execCount(o1), 2)
   expect_equal(execCount(o2), 2)
 })
+
+run_debounce_throttle <- function(do_priming) {
+  # The changing of rv$a will be the (chatty) source of reactivity.
+  rv <- reactiveValues(a = 0)
+
+  # This observer will be what changes rv$a.
+  src <- observe({
+    invalidateLater(100)
+    rv$a <- isolate(rv$a) + 1
+  })
+  on.exit(src$destroy(), add = TRUE)
+
+  # Make a debounced reactive to test.
+  dr <- debounce(reactive(rv$a), 500)
+
+  # Make a throttled reactive to test.
+  tr <- throttle(reactive(rv$a), 500)
+
+  # Keep track of how often dr/tr are fired
+  dr_fired <- 0
+  dr_monitor <- observeEvent(dr(), {
+    dr_fired <<- dr_fired + 1
+  })
+  on.exit(dr_monitor$destroy(), add = TRUE)
+
+  tr_fired <- 0
+  tr_monitor <- observeEvent(tr(), {
+    tr_fired <<- tr_fired + 1
+  })
+  on.exit(tr_monitor$destroy(), add = TRUE)
+
+  # Starting values are both 0. Earlier I found that the tests behaved
+  # differently if I accessed the values of dr/tr before the first call to
+  # flushReact(). That bug was fixed, but to ensure that similar bugs don't
+  # appear undetected, we run this test with and without do_priming.
+  if (do_priming) {
+    expect_identical(isolate(dr()), 0)
+    expect_identical(isolate(tr()), 0)
+  }
+
+  # Pump timer and reactives for about 1.4 seconds
+  stopAt <- Sys.time() + 1.4
+  while (Sys.time() < stopAt) {
+    timerCallbacks$executeElapsed()
+    flushReact()
+    Sys.sleep(0.001)
+  }
+
+  # dr() should not have had time to fire, other than the initial run, since
+  # there haven't been long enough gaps between invalidations.
+  expect_identical(dr_fired, 1)
+  # The value of dr() should not have updated either.
+  expect_identical(isolate(dr()), 0)
+
+  # tr() however, has had time to fire multiple times and update its value.
+  expect_identical(tr_fired, 3)
+  expect_identical(isolate(tr()), 10)
+
+  # Now let some time pass without any more updates.
+  src$destroy() # No more updates
+  stopAt <- Sys.time() + 1
+  while (Sys.time() < stopAt) {
+    timerCallbacks$executeElapsed()
+    flushReact()
+    Sys.sleep(0.001)
+  }
+
+  # dr should've fired, and we should have converged on the right answer.
+  expect_identical(dr_fired, 2)
+  isolate(expect_identical(rv$a, dr()))
+  expect_identical(tr_fired, 4)
+  isolate(expect_identical(rv$a, tr()))
+}
+
+test_that("debounce/throttle work properly (with priming)", {
+  run_debounce_throttle(TRUE)
+})
+test_that("debounce/throttle work properly (without priming)", {
+  run_debounce_throttle(FALSE)
+})
diff --git a/tests/testthat/test-utils.R b/tests/testthat/test-utils.R
index 3c346b5..efaa846 100644
--- a/tests/testthat/test-utils.R
+++ b/tests/testthat/test-utils.R
@@ -129,6 +129,31 @@ test_that("anyUnnamed works as expected", {
   expect_true(anyUnnamed(x))
 })
 
+test_that("sortByName works as expected", {
+  # Error if any unnamed elements
+  expect_error(sortByName(c("a", "b")))
+  expect_error(sortByName(list(a=1, 2)))
+
+  expect_identical(sortByName(NULL), NULL)
+  expect_identical(sortByName(numeric(0)), numeric(0))
+  expect_identical(sortByName(character(0)), character(0))
+  # Empty unnamed list
+  expect_identical(sortByName(list()), list())
+  # Empty named list
+  expect_identical(sortByName(list(a=1)[0]), list(a=1)[0])
+
+  expect_identical(sortByName(list(b=1, a=2)), list(a=2, b=1))
+  expect_identical(sortByName(list(b=1)), list(b=1))
+
+  # Ties are resolved by using original order
+  expect_identical(sortByName(list(b=1, a=2, b=3)), list(a=2, b=1, b=3))
+  expect_identical(sortByName(list(b=3, a=2, b=1)), list(a=2, b=3, b=1))
+
+  # Make sure atomic vectors work
+  expect_identical(sortByName(c(b=1, a=2)), c(a=2, b=1))
+  expect_identical(sortByName(c(b=1, a=2, b=3)), c(a=2, b=1, b=3))
+})
+
 test_that("Callbacks fire in predictable order", {
   cb <- Callbacks$new()
 

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/r-cran-shiny.git



More information about the debian-med-commit mailing list