mirror of
https://github.com/rstudio/shiny.git
synced 2026-01-10 23:48:01 -05:00
Compare commits
232 Commits
joe/featur
...
barret/deb
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2acaea1444 | ||
|
|
1120cfdfd7 | ||
|
|
d95560db09 | ||
|
|
98f64df738 | ||
|
|
8634e372da | ||
|
|
cbda7633e0 | ||
|
|
8f00cf50ca | ||
|
|
acca28075b | ||
|
|
9a563463dd | ||
|
|
1ede94b09e | ||
|
|
7f41a54c4e | ||
|
|
6cfab79ce9 | ||
|
|
f33b3c7eef | ||
|
|
93d78ae2b0 | ||
|
|
c498b02289 | ||
|
|
30b62e6f18 | ||
|
|
ec18ef651b | ||
|
|
aad23686fa | ||
|
|
1c85ecd7c0 | ||
|
|
a1ff765235 | ||
|
|
a30ba9226d | ||
|
|
980a1e53a7 | ||
|
|
00092cd2a8 | ||
|
|
53ddb54936 | ||
|
|
ea1e307a51 | ||
|
|
17bc1e2e06 | ||
|
|
ed8f3b730b | ||
|
|
0e109d5237 | ||
|
|
f672226a3d | ||
|
|
481dccd085 | ||
|
|
9612f1c3c8 | ||
|
|
9e1e5f61a3 | ||
|
|
99a566f473 | ||
|
|
1012307467 | ||
|
|
b729f45eaf | ||
|
|
cab799e6ee | ||
|
|
a06322d155 | ||
|
|
d836cb2a2c | ||
|
|
2249c7a28a | ||
|
|
0d0422c0a7 | ||
|
|
5ea556ee77 | ||
|
|
a34496663b | ||
|
|
abeaa71d8d | ||
|
|
281a427718 | ||
|
|
03ab966cdc | ||
|
|
3dcb810346 | ||
|
|
d6eef8b3e1 | ||
|
|
a770f1cbf2 | ||
|
|
a5687df9b4 | ||
|
|
202881cbbd | ||
|
|
24ac3b9d8b | ||
|
|
47c1fb88b9 | ||
|
|
170b143b17 | ||
|
|
3854b49c35 | ||
|
|
bae4f604b5 | ||
|
|
36f32e14d3 | ||
|
|
9e521e6927 | ||
|
|
4176f541fc | ||
|
|
18f2afbf85 | ||
|
|
f9a94d9758 | ||
|
|
d1e672e3e3 | ||
|
|
202b924e63 | ||
|
|
4c3342aa99 | ||
|
|
b1e5dd1d1d | ||
|
|
d43ebfbdb9 | ||
|
|
cfadd8307b | ||
|
|
fa6cf9832d | ||
|
|
0075b0da33 | ||
|
|
59c6367cb5 | ||
|
|
194323a9ee | ||
|
|
1ca437e4ee | ||
|
|
77e43b9f50 | ||
|
|
a23f4b0224 | ||
|
|
0541c90980 | ||
|
|
b73a263de8 | ||
|
|
d7ffee68cf | ||
|
|
89cd42b904 | ||
|
|
404185eb8c | ||
|
|
8c29a81b12 | ||
|
|
9b42c6c379 | ||
|
|
03c2dd9e4b | ||
|
|
d8274c3d8c | ||
|
|
85b5fb090f | ||
|
|
2adef311ed | ||
|
|
7050d0b8ad | ||
|
|
8358144a4f | ||
|
|
44e083e0a9 | ||
|
|
a5418cf6ee | ||
|
|
c74630d6eb | ||
|
|
157d4ac9a9 | ||
|
|
8228613c01 | ||
|
|
b907e17b70 | ||
|
|
aa7000427c | ||
|
|
8562c90454 | ||
|
|
5a9a04cd72 | ||
|
|
6b32611356 | ||
|
|
770ebc394f | ||
|
|
c0d35e84b1 | ||
|
|
5e74478864 | ||
|
|
46852e2051 | ||
|
|
b9dded0bef | ||
|
|
6d05f403a5 | ||
|
|
8368634f85 | ||
|
|
8d57d909b4 | ||
|
|
9b7855d597 | ||
|
|
6a5e1b9998 | ||
|
|
af6e558699 | ||
|
|
26d4dddffd | ||
|
|
e2765b4881 | ||
|
|
9796b25f33 | ||
|
|
01b8d3a314 | ||
|
|
50c48de0de | ||
|
|
bfc90da054 | ||
|
|
9d8d6fd6b1 | ||
|
|
43344d9a78 | ||
|
|
01a593c857 | ||
|
|
1b2dd11a4c | ||
|
|
d90a2c4801 | ||
|
|
f065c21ee6 | ||
|
|
d0324bd497 | ||
|
|
e57fba07db | ||
|
|
5cb279cf4e | ||
|
|
4f728b0387 | ||
|
|
927ae08a47 | ||
|
|
a28dc47e30 | ||
|
|
b43ee13dd8 | ||
|
|
ad5ad5a675 | ||
|
|
198f7d171e | ||
|
|
549425cb81 | ||
|
|
6023165268 | ||
|
|
2a7273c254 | ||
|
|
8640934410 | ||
|
|
20bc4e7caa | ||
|
|
9f83058b78 | ||
|
|
ffedf29db4 | ||
|
|
00219d342a | ||
|
|
753400144d | ||
|
|
854a732f47 | ||
|
|
03eaf07526 | ||
|
|
d04c12d8cb | ||
|
|
afddd3543e | ||
|
|
d9459a855d | ||
|
|
efbcfca126 | ||
|
|
916675a9bd | ||
|
|
7b43617954 | ||
|
|
09b89bccfd | ||
|
|
1190ee07a9 | ||
|
|
c4dcf405bb | ||
|
|
c844ea6f07 | ||
|
|
19704c151a | ||
|
|
1281ba18cd | ||
|
|
f1f2fae420 | ||
|
|
5809070b05 | ||
|
|
2c492540ce | ||
|
|
61556b505d | ||
|
|
d6a4bc87e8 | ||
|
|
e49f4696e6 | ||
|
|
4219f50141 | ||
|
|
19da003291 | ||
|
|
f0765e3d6a | ||
|
|
8dac345512 | ||
|
|
ce101843f0 | ||
|
|
d56dc3a237 | ||
|
|
28cffb2e25 | ||
|
|
d2d169fea3 | ||
|
|
a5eb1b15d2 | ||
|
|
23dbb0b41c | ||
|
|
c72ae68de5 | ||
|
|
7c1f87aed3 | ||
|
|
6ec0ac1651 | ||
|
|
9dc84e5c2b | ||
|
|
1e17b55f49 | ||
|
|
6a4c8556a3 | ||
|
|
488f1c8b83 | ||
|
|
e2537d8e93 | ||
|
|
6d35cb6c77 | ||
|
|
8ce7f64679 | ||
|
|
5cd6250f05 | ||
|
|
4872cd91a5 | ||
|
|
08e84e2ca0 | ||
|
|
40889c9637 | ||
|
|
010ba6f214 | ||
|
|
2f8dc860ff | ||
|
|
88f61f0d45 | ||
|
|
16a5aa7489 | ||
|
|
89fd2b2ed3 | ||
|
|
a16769061e | ||
|
|
3be76145b7 | ||
|
|
e9d27fa632 | ||
|
|
be706e4bb7 | ||
|
|
b87c4d5623 | ||
|
|
03a260f26a | ||
|
|
ae3e007a5f | ||
|
|
cfbf76d898 | ||
|
|
0b82b121cb | ||
|
|
643ebb4946 | ||
|
|
8693eed3ec | ||
|
|
766b910150 | ||
|
|
545843ffe6 | ||
|
|
39e7b23d5b | ||
|
|
9d0db6f74c | ||
|
|
78fb25329c | ||
|
|
7db6a7b57a | ||
|
|
76f70179c0 | ||
|
|
d6aecfe9ae | ||
|
|
1354d3dec1 | ||
|
|
955ae817d8 | ||
|
|
aee9589c1a | ||
|
|
48ac0f55c3 | ||
|
|
831c0a340c | ||
|
|
210d297d18 | ||
|
|
afbcf9039e | ||
|
|
e8eadc1a09 | ||
|
|
f234b7015c | ||
|
|
8de38b3415 | ||
|
|
0f132fc180 | ||
|
|
e597c24f35 | ||
|
|
1d7a913d29 | ||
|
|
f89131205d | ||
|
|
d616cf045b | ||
|
|
9f55cd46d8 | ||
|
|
5956f6b123 | ||
|
|
c7618e3991 | ||
|
|
8c6a830521 | ||
|
|
9142cf19c0 | ||
|
|
887b7fb34a | ||
|
|
1392547783 | ||
|
|
735b9b8c7a | ||
|
|
cba974ec34 | ||
|
|
421d588a2f | ||
|
|
8b848277d2 | ||
|
|
8ae19c7243 |
35
DESCRIPTION
35
DESCRIPTION
@@ -1,13 +1,18 @@
|
||||
Package: shiny
|
||||
Type: Package
|
||||
Title: Web Application Framework for R
|
||||
Version: 1.5.0.9001
|
||||
Version: 1.5.0.9004
|
||||
Authors@R: c(
|
||||
person("Winston", "Chang", role = c("aut", "cre"), email = "winston@rstudio.com"),
|
||||
person("Joe", "Cheng", role = "aut", email = "joe@rstudio.com"),
|
||||
person("JJ", "Allaire", role = "aut", email = "jj@rstudio.com"),
|
||||
person("Carson", "Sievert", role = "aut", email = "carson@rstudio.com"),
|
||||
person("Barret", "Schloerke", role = "aut", email = "barret@rstudio.com"),
|
||||
person("Yihui", "Xie", role = "aut", email = "yihui@rstudio.com"),
|
||||
person("Jeff", "Allen", role = "aut", email = "jeff@rstudio.com"),
|
||||
person("Jonathan", "McPherson", role = "aut", email = "jonathan@rstudio.com"),
|
||||
person("Alan", "Dipert", role = "aut"),
|
||||
person("Barbara", "Borges", role = "aut"),
|
||||
person(family = "RStudio", role = "cph"),
|
||||
person(family = "jQuery Foundation", role = "cph",
|
||||
comment = "jQuery library and jQuery UI library"),
|
||||
@@ -43,10 +48,8 @@ Authors@R: c(
|
||||
comment = "Font-Awesome font"),
|
||||
person("Brian", "Reavis", role = c("ctb", "cph"),
|
||||
comment = "selectize.js library"),
|
||||
person("Kristopher Michael", "Kowal", role = c("ctb", "cph"),
|
||||
comment = "es5-shim library"),
|
||||
person(family = "es5-shim contributors", role = c("ctb", "cph"),
|
||||
comment = "es5-shim library"),
|
||||
person("Salmen", "Bejaoui", role = c("ctb", "cph"),
|
||||
comment = "selectize-plugin-a11y library"),
|
||||
person("Denis", "Ineshin", role = c("ctb", "cph"),
|
||||
comment = "ion.rangeSlider library"),
|
||||
person("Sami", "Samhuri", role = c("ctb", "cph"),
|
||||
@@ -78,7 +81,7 @@ Imports:
|
||||
jsonlite (>= 0.9.16),
|
||||
xtable,
|
||||
digest,
|
||||
htmltools (>= 0.4.0.9003),
|
||||
htmltools (>= 0.5.0.9001),
|
||||
R6 (>= 2.0),
|
||||
sourcetools,
|
||||
later (>= 1.0.0),
|
||||
@@ -89,7 +92,8 @@ Imports:
|
||||
fastmap (>= 1.0.0),
|
||||
withr,
|
||||
commonmark (>= 1.7),
|
||||
glue (>= 1.3.2)
|
||||
glue (>= 1.3.2),
|
||||
bootstraplib (>= 0.2.0.9001)
|
||||
Suggests:
|
||||
datasets,
|
||||
Cairo (>= 1.5-5),
|
||||
@@ -105,23 +109,27 @@ Suggests:
|
||||
future,
|
||||
dygraphs,
|
||||
ragg,
|
||||
showtext
|
||||
showtext,
|
||||
sass
|
||||
Remotes:
|
||||
rstudio/htmltools,
|
||||
rstudio/sass,
|
||||
rstudio/bootstraplib
|
||||
URL: http://shiny.rstudio.com
|
||||
BugReports: https://github.com/rstudio/shiny/issues
|
||||
Collate:
|
||||
'app.R'
|
||||
'globals.R'
|
||||
'app-state.R'
|
||||
'app_template.R'
|
||||
'bookmark-state-local.R'
|
||||
'stack.R'
|
||||
'bookmark-state.R'
|
||||
'bootstrap-deprecated.R'
|
||||
'bootstrap-layout.R'
|
||||
'globals.R'
|
||||
'conditions.R'
|
||||
'map.R'
|
||||
'utils.R'
|
||||
'bootstrap.R'
|
||||
'cache-context.R'
|
||||
'cache-disk.R'
|
||||
'cache-memory.R'
|
||||
'cache-utils.R'
|
||||
@@ -156,6 +164,7 @@ Collate:
|
||||
'insert-tab.R'
|
||||
'insert-ui.R'
|
||||
'jqueryui.R'
|
||||
'knitr.R'
|
||||
'middleware-shiny.R'
|
||||
'middleware.R'
|
||||
'timer.R'
|
||||
@@ -172,10 +181,13 @@ Collate:
|
||||
'render-plot.R'
|
||||
'render-table.R'
|
||||
'run-url.R'
|
||||
'runapp.R'
|
||||
'serializers.R'
|
||||
'server-input-handlers.R'
|
||||
'server-resource-paths.R'
|
||||
'server.R'
|
||||
'shiny-options.R'
|
||||
'shinyapp.R'
|
||||
'shinyui.R'
|
||||
'shinywrappers.R'
|
||||
'showcase.R'
|
||||
@@ -185,6 +197,7 @@ Collate:
|
||||
'test-server.R'
|
||||
'test.R'
|
||||
'update-input.R'
|
||||
'viewer.R'
|
||||
RoxygenNote: 7.1.1
|
||||
Encoding: UTF-8
|
||||
Roxygen: list(markdown = TRUE)
|
||||
|
||||
24
LICENSE
24
LICENSE
@@ -12,7 +12,7 @@ these components are included below):
|
||||
- bootstrap-datepicker, https://github.com/eternicode/bootstrap-datepicker
|
||||
- Font Awesome, https://github.com/FortAwesome/Font-Awesome
|
||||
- selectize.js, https://github.com/selectize/selectize.js
|
||||
- es5-shim, https://github.com/es-shims/es5-shim
|
||||
- selectize-plugin-a11y, https://github.com/SLMNBJ/selectize-plugin-a11y
|
||||
- ion.rangeSlider, https://github.com/IonDen/ion.rangeSlider
|
||||
- strftime for Javascript, https://github.com/samsonjs/strftime
|
||||
- DataTables, https://github.com/DataTables/DataTables
|
||||
@@ -957,30 +957,18 @@ selectize.js
|
||||
limitations under the License.
|
||||
|
||||
|
||||
es5-shim License
|
||||
selectize-plugin-a11y License
|
||||
----------------------------------------------------------------------
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (C) 2009-2014 Kristopher Michael Kowal and contributors
|
||||
Copyright 2018-present Salmen Bejaoui
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
|
||||
ion.rangeSlider License
|
||||
|
||||
@@ -99,6 +99,7 @@ export(formatStackTrace)
|
||||
export(freezeReactiveVal)
|
||||
export(freezeReactiveValue)
|
||||
export(getCurrentOutputInfo)
|
||||
export(getCurrentTheme)
|
||||
export(getDefaultReactiveDomain)
|
||||
export(getQueryString)
|
||||
export(getShinyOption)
|
||||
@@ -182,6 +183,7 @@ export(printError)
|
||||
export(printStackTrace)
|
||||
export(radioButtons)
|
||||
export(reactive)
|
||||
export(reactiveConsole)
|
||||
export(reactiveFileReader)
|
||||
export(reactivePlot)
|
||||
export(reactivePoll)
|
||||
@@ -197,6 +199,7 @@ export(reactlog)
|
||||
export(reactlogReset)
|
||||
export(reactlogShow)
|
||||
export(registerInputHandler)
|
||||
export(registerThemeDependency)
|
||||
export(removeInputHandler)
|
||||
export(removeModal)
|
||||
export(removeNotification)
|
||||
|
||||
57
NEWS.md
57
NEWS.md
@@ -2,28 +2,78 @@
|
||||
shiny 1.5.0.9000
|
||||
================
|
||||
|
||||
## Full changelog
|
||||
|
||||
### Breaking changes
|
||||
|
||||
* Closed #3074: Shiny no longer supports file uploads for Internet Explorer 8 or 9. (#3075)
|
||||
|
||||
* Subtle changes, and some soft-deprecations, have come to `freezeReactiveValue` and `freezeReactiveVal` (#3055). These functions have been fragile at best in previous releases (issues #1791, #2463, #2946). In this release, we've solved all the problems we know about with `freezeReactiveValue(input, "x")`, by 1) invalidating `input$x` and set it to `NULL` whenever we freeze, and 2) ensuring that, after a freeze, even if the effect of `renderUI` or `updateXXXInput` is to set `input$x` to the same value it already has, this will result in an invalidation (whereas by default, Shiny filters out such spurious assignments).
|
||||
|
||||
Similar problems may exist when using `freezeReactiveVal`, and when using `freezeReactiveValue` with non-`input` reactive values objects. But support for those was added mostly for symmetry with `freezeReactiveValue(input)`, and given the above issues, it's not clear to us how you could have used these successfully in the past, or why you would even want to. For this release, we're soft-deprecating both of those uses, but we're more than willing to un-deprecate if it turns out people are using these; if that includes you, please join the conversation at https://github.com/rstudio/shiny/issues/3063. In the meantime, you can squelch the deprecation messages for these functions specifically, by setting `options(shiny.deprecation.messages.freeze = FALSE)`.
|
||||
|
||||
### Accessibility
|
||||
|
||||
* Added [bootstrap accessibility plugin](https://github.com/paypal/bootstrap-accessibility-plugin) under the hood to improve accessibility of shiny apps for screen-reader and keyboard users: the enhancements include better navigations for alert, tooltip, popover, modal dialog, dropdown, tab Panel, collapse, and carousel elements (#2911)
|
||||
* Added [bootstrap accessibility plugin](https://github.com/paypal/bootstrap-accessibility-plugin) under the hood to improve accessibility of shiny apps for screen-reader and keyboard users: the enhancements include better navigations for alert, tooltip, popover, modal dialog, dropdown, tab Panel, collapse, and carousel elements. (#2911)
|
||||
|
||||
* Added appropriate labels to `icon()` element to provide screen-reader users with alternative descriptions for the `fontawesome` and `glyphicon`: `aria-label` is automatically applied based on the fontawesome name. For example, `icon("calendar")` will be announced as "calendar icon" to screen readers. "presentation" aria role has also been attached to `icon()` to remove redundant semantic info for screen readers (#2917)
|
||||
* Added appropriate labels to `icon()` element to provide screen-reader users with alternative descriptions for the `fontawesome` and `glyphicon`: `aria-label` is automatically applied based on the fontawesome name. For example, `icon("calendar")` will be announced as "calendar icon" to screen readers. "presentation" aria role has also been attached to `icon()` to remove redundant semantic info for screen readers. (#2917)
|
||||
|
||||
* Closed #2929: Fixed keyboard accessibility for file picker button: keyboard users can now tab to focus on `fileInput()` widget (#2937)
|
||||
* Closed #2929: Fixed keyboard accessibility for file picker button: keyboard users can now tab to focus on `fileInput()` widget. (#2937)
|
||||
|
||||
* Fixed #2951: screen readers correctly announce labels and date formats for `dateInput()` and `dateRangeInput()` widgets. (#2978)
|
||||
|
||||
* Closed #2847: `selectInput()` is reasonably accessible for screen readers even when `selectize` option is set to TRUE. To improve `selectize.js` accessibility, we have added [selectize-plugin-a11y](https://github.com/SLMNBJ/selectize-plugin-a11y) by default. (#2993)
|
||||
|
||||
* Closed #612: Added `alt` argument to `renderPlot()` and `renderCachedPlot()` to specify descriptive texts for `plotOutput()` objects, which is essential for screen readers. By default, alt text is set to the static text, "Plot object," but even dynamic text can be made with reactive function. (#3006, thanks @trafficonese and @leonawicz for the original PR and discussion via #2494)
|
||||
|
||||
* Added semantic landmarks for `mainPanel()` and `sidebarPanel()` so that assistive technologies can recognize them as "main" and "complementary" region respectively. (#3009)
|
||||
|
||||
* Closed #2844: Added `lang` argument to ui `*Page()` functions (e.g., `fluidPage`, `bootstrapPage`) that specifies document-level language within the app for the accessibility of screen readers and search-engine parsers. By default, it is set to empty string which is commonly recognized as a browser's default locale. (#2920)
|
||||
|
||||
### Minor new features and improvements
|
||||
|
||||
* New `reactiveConsole()` makes it easier to interactively experiment with reactivity at the console (#2518).
|
||||
|
||||
* When UI is specified as a function (e.g. `ui <- function(req) { ... }`), the response can now be an HTTP response as returned from the (newly exported) `httpResponse()` function. (#2970)
|
||||
|
||||
* `selectInput` and `selectizeInput` now warn about performance implications when thousands of choices are used, and recommend [server-side selectize](https://shiny.rstudio.com/articles/selectize.html) be used instead. (#2959)
|
||||
|
||||
* Closed #2980: `addResourcePath()` now allows paths with a leading `.` (thanks to @ColinFay). (#2981)
|
||||
|
||||
* Closed #2972: `runExample()` now supports the `shiny.port` option (thanks to @ColinFay). (#2982)
|
||||
|
||||
* Closed #2692: `downloadButton()` icon can now be changed via the `icon` parameter (thanks to @ColinFay). (#3010)
|
||||
|
||||
* Closed #2984: improved documentation for `renderCachedPlot()` (thanks to @aalucaci). (#3016)
|
||||
|
||||
* `reactiveValuesToList()` will save its `reactlog` label as `reactiveValuesToList(<ID>)` vs `as.list(<ID>)` (#3017)
|
||||
|
||||
* Removed unused (and non-exported) `cacheContext` class.
|
||||
|
||||
* `testServer()` can accept a single server function as input (#2965).
|
||||
|
||||
* `shinyOptions()` now has session-level scoping, in addition to global and application-level scoping. (#3080)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
* Fixed #2859: `renderPlot()` wasn't correctly setting `showtext::showtext_opts()`'s `dpi` setting with the correct resolution on high resolution displays; which means, if the font was rendered by showtext, font sizes would look smaller than they should on such displays. (#2941)
|
||||
|
||||
* Fixed #1942: Calling `runApp("app.R")` no longer ignores options passed into `shinyApp()`. This makes it possible for Shiny apps to specify what port/host should be used by default. (#2969)
|
||||
|
||||
* Fixed #3033: When a `DiskCache` was created with both `max_n` and `max_size`, too many items could get pruned when `prune()` was called. (#3034)
|
||||
|
||||
* Fixed #2936: `dateYMD` was giving a warning when passed a vector of dates from `dateInput` which was greater than length 1. The length check was removed because it was not needed. (#3061)
|
||||
|
||||
* Fixed #2266, #2688: `radioButtons` and `updateRadioButtons` now accept `character(0)` to indicate that none of the options should be selected (thanks to @ColinFay). (#3043)
|
||||
|
||||
* Fixed a bug that `textAreaInput()` doesn't work as expected for relative `width` (thanks to @shrektan). (#2049)
|
||||
|
||||
### Library updates
|
||||
|
||||
* Removed html5shiv and respond.js, which were used for IE 8 and IE 9 compatibility. (#2973)
|
||||
|
||||
* Removed es5-shim library, which was internally used within `selectInput()` for ECMAScript 5 compatibility. (#2993)
|
||||
|
||||
|
||||
shiny 1.5.0
|
||||
===========
|
||||
@@ -336,6 +386,7 @@ This is a significant release for Shiny, with a major new feature that was nearl
|
||||
|
||||
* Fixed #2021: Memory leak with `reactiveTimer` and `invalidateLater`. (#2022)
|
||||
|
||||
|
||||
### Library updates
|
||||
|
||||
* Updated to ion.rangeSlider 2.2.0. (#1955)
|
||||
|
||||
26
R/app-state.R
Normal file
26
R/app-state.R
Normal file
@@ -0,0 +1,26 @@
|
||||
#' @include globals.R
|
||||
NULL
|
||||
|
||||
# The current app state is a place to read and hang state for the
|
||||
# currently-running application. This is useful for setting options that will
|
||||
# last as long as the application is running.
|
||||
|
||||
.globals$appState <- NULL
|
||||
|
||||
initCurrentAppState <- function(appobj) {
|
||||
if (!is.null(.globals$appState)) {
|
||||
stop("Can't initialize current app state when another is currently active.")
|
||||
}
|
||||
.globals$appState <- new.env(parent = emptyenv())
|
||||
.globals$appState$app <- appobj
|
||||
# Copy over global options
|
||||
.globals$appState$options <- .globals$options
|
||||
}
|
||||
|
||||
getCurrentAppState <- function() {
|
||||
.globals$appState
|
||||
}
|
||||
|
||||
clearCurrentAppState <- function() {
|
||||
.globals$appState <- NULL
|
||||
}
|
||||
@@ -217,6 +217,22 @@ RestoreContext <- R6Class("RestoreContext",
|
||||
self$dir <- NULL
|
||||
},
|
||||
|
||||
# Completely replace the state
|
||||
set = function(active = FALSE, initErrorMessage = NULL, input = list(), values = list(), dir = NULL) {
|
||||
# Validate all inputs
|
||||
stopifnot(is.logical(active))
|
||||
stopifnot(is.null(initErrorMessage) || is.character(initErrorMessage))
|
||||
stopifnot(is.list(input))
|
||||
stopifnot(is.list(values))
|
||||
stopifnot(is.null(dir) || is.character(dir))
|
||||
|
||||
self$active <- active
|
||||
self$initErrorMessage <- initErrorMessage
|
||||
self$input <- RestoreInputSet$new(input)
|
||||
self$values <- list2env2(values, parent = emptyenv())
|
||||
self$dir <- dir
|
||||
},
|
||||
|
||||
# This should be called before a restore context is popped off the stack.
|
||||
flushPending = function() {
|
||||
self$input$flushPending()
|
||||
@@ -453,7 +469,7 @@ hasCurrentRestoreContext <- function() {
|
||||
domain <- getDefaultReactiveDomain()
|
||||
if (!is.null(domain) && !is.null(domain$restoreContext))
|
||||
return(TRUE)
|
||||
|
||||
|
||||
return(FALSE)
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#' @param theme Alternative Bootstrap stylesheet (normally a css file within the
|
||||
#' www directory). For example, to use the theme located at
|
||||
#' `www/bootstrap.css` you would use `theme = "bootstrap.css"`.
|
||||
#' @inheritParams bootstrapPage
|
||||
#'
|
||||
#' @return A UI defintion that can be passed to the [shinyUI] function.
|
||||
#'
|
||||
@@ -87,11 +88,12 @@
|
||||
#' }
|
||||
#' @rdname fluidPage
|
||||
#' @export
|
||||
fluidPage <- function(..., title = NULL, responsive = NULL, theme = NULL) {
|
||||
fluidPage <- function(..., title = NULL, responsive = NULL, theme = NULL, lang = NULL) {
|
||||
bootstrapPage(div(class = "container-fluid", ...),
|
||||
title = title,
|
||||
responsive = responsive,
|
||||
theme = theme)
|
||||
theme = theme,
|
||||
lang = lang)
|
||||
}
|
||||
|
||||
|
||||
@@ -118,6 +120,7 @@ fluidRow <- function(...) {
|
||||
#' @param theme Alternative Bootstrap stylesheet (normally a css file within the
|
||||
#' www directory). For example, to use the theme located at
|
||||
#' `www/bootstrap.css` you would use `theme = "bootstrap.css"`.
|
||||
#' @inheritParams bootstrapPage
|
||||
#'
|
||||
#' @return A UI defintion that can be passed to the [shinyUI] function.
|
||||
#'
|
||||
@@ -156,11 +159,12 @@ fluidRow <- function(...) {
|
||||
#'
|
||||
#' @rdname fixedPage
|
||||
#' @export
|
||||
fixedPage <- function(..., title = NULL, responsive = NULL, theme = NULL) {
|
||||
fixedPage <- function(..., title = NULL, responsive = NULL, theme = NULL, lang = NULL) {
|
||||
bootstrapPage(div(class = "container", ...),
|
||||
title = title,
|
||||
responsive = responsive,
|
||||
theme = theme)
|
||||
theme = theme,
|
||||
lang = lang)
|
||||
}
|
||||
|
||||
#' @rdname fixedPage
|
||||
@@ -355,6 +359,8 @@ sidebarLayout <- function(sidebarPanel,
|
||||
sidebarPanel <- function(..., width = 4) {
|
||||
div(class=paste0("col-sm-", width),
|
||||
tags$form(class="well",
|
||||
# A11y semantic landmark for sidebar
|
||||
role="complementary",
|
||||
...
|
||||
)
|
||||
)
|
||||
@@ -364,6 +370,8 @@ sidebarPanel <- function(..., width = 4) {
|
||||
#' @rdname sidebarLayout
|
||||
mainPanel <- function(..., width = 8) {
|
||||
div(class=paste0("col-sm-", width),
|
||||
# A11y semantic landmark for main region
|
||||
role="main",
|
||||
...
|
||||
)
|
||||
}
|
||||
|
||||
213
R/bootstrap.R
213
R/bootstrap.R
@@ -16,8 +16,15 @@ NULL
|
||||
#' @param title The browser window title (defaults to the host URL of the page)
|
||||
#' @param responsive This option is deprecated; it is no longer optional with
|
||||
#' Bootstrap 3.
|
||||
#' @param theme Alternative Bootstrap stylesheet (normally a css file within the
|
||||
#' www directory, e.g. `www/bootstrap.css`)
|
||||
#' @param theme One of the following:
|
||||
#' * `NULL` (the default), which implies a "stock" build of Bootstrap 3.
|
||||
#' * A [bootstraplib::bs_theme()] object. This can be used to replace a stock
|
||||
#' build of Bootstrap 3 with a customized version of Bootstrap 3 or higher.
|
||||
#' * A character string pointing to an alternative Bootstrap stylesheet
|
||||
#' (normally a css file within the www directory, e.g. `www/bootstrap.css`).
|
||||
#' @param lang ISO 639-1 language code for the HTML page, such as "en" or "ko".
|
||||
#' This will be used as the lang in the \code{<html>} tag, as in \code{<html lang="en">}.
|
||||
#' The default (NULL) results in an empty string.
|
||||
#'
|
||||
#' @return A UI defintion that can be passed to the [shinyUI] function.
|
||||
#'
|
||||
@@ -26,41 +33,177 @@ NULL
|
||||
#'
|
||||
#' @seealso [fluidPage()], [fixedPage()]
|
||||
#' @export
|
||||
bootstrapPage <- function(..., title = NULL, responsive = NULL, theme = NULL) {
|
||||
bootstrapPage <- function(..., title = NULL, responsive = NULL, theme = NULL, lang = NULL) {
|
||||
|
||||
if (!is.null(responsive)) {
|
||||
shinyDeprecated("The 'responsive' argument is no longer used with Bootstrap 3.")
|
||||
}
|
||||
|
||||
attachDependencies(
|
||||
tagList(
|
||||
if (!is.null(title)) tags$head(tags$title(title)),
|
||||
if (!is.null(theme)) {
|
||||
tags$head(tags$link(rel="stylesheet", type="text/css", href = theme))
|
||||
},
|
||||
|
||||
# remainder of tags passed to the function
|
||||
list(...)
|
||||
),
|
||||
bootstrapLib()
|
||||
ui <- tagList(
|
||||
bootstrapLib(theme),
|
||||
if (!is.null(title)) tags$head(tags$title(title)),
|
||||
# TODO: throw better error when length > 1?
|
||||
if (is.character(theme)) {
|
||||
tags$head(tags$link(rel="stylesheet", type="text/css", href = theme))
|
||||
},
|
||||
# remainder of tags passed to the function
|
||||
list(...)
|
||||
)
|
||||
|
||||
ui <- setLang(ui, lang)
|
||||
|
||||
return(ui)
|
||||
}
|
||||
|
||||
setLang <- function(ui, lang) {
|
||||
# Add lang attribute to be passed to renderPage function
|
||||
attr(ui, "lang") <- lang
|
||||
ui
|
||||
}
|
||||
getLang <- function(ui) {
|
||||
# Check if ui has lang attribute; otherwise, NULL
|
||||
attr(ui, "lang", exact = TRUE)
|
||||
}
|
||||
|
||||
#' Bootstrap libraries
|
||||
#'
|
||||
#' This function returns a set of web dependencies necessary for using Bootstrap
|
||||
#' This function defines a set of web dependencies necessary for using Bootstrap
|
||||
#' components in a web page.
|
||||
#'
|
||||
#' It isn't necessary to call this function if you use
|
||||
#' [bootstrapPage()] or others which use `bootstrapPage`, such
|
||||
#' [basicPage()], [fluidPage()], [fillPage()],
|
||||
#' [pageWithSidebar()], and [navbarPage()], because they
|
||||
#' already include the Bootstrap web dependencies.
|
||||
#' It isn't necessary to call this function if you use [bootstrapPage()] or
|
||||
#' others which use `bootstrapPage`, such [fluidPage()], [navbarPage()],
|
||||
#' [fillPage()], etc, because they already include the Bootstrap web dependencies.
|
||||
#'
|
||||
#' @inheritParams bootstrapPage
|
||||
#' @export
|
||||
bootstrapLib <- function(theme = NULL) {
|
||||
htmlDependency("bootstrap", "3.4.1",
|
||||
tagFunction(function() {
|
||||
# If we're not compiling Bootstrap Sass (from bootstraplib), return the
|
||||
# static Bootstrap build.
|
||||
if (!is_bs_theme(theme)) {
|
||||
# We'll enter here if `theme` is the path to a .css file, like that
|
||||
# provided by `shinythemes::shinytheme("darkly")`.
|
||||
return(bootstrapDependency(theme))
|
||||
}
|
||||
|
||||
# Make bootstrap Sass available so other tagFunction()s (e.g.,
|
||||
# sliderInput() et al) can resolve their HTML dependencies at render time
|
||||
# using getCurrentTheme(). Note that we're making an implicit assumption
|
||||
# that this tagFunction() executes *before* all other tagFunction()s; but
|
||||
# that should be fine considering that, DOM tree order is preorder,
|
||||
# depth-first traversal, and at least in the bootstrapPage(theme) case, we
|
||||
# have control over the relative ordering.
|
||||
# https://dom.spec.whatwg.org/#concept-tree
|
||||
# https://stackoverflow.com/a/16113998/1583084
|
||||
#
|
||||
# Note also that since this is shinyOptions() (and not options()), the
|
||||
# option is automatically reset when the app (or session) exits
|
||||
if (isRunning()) {
|
||||
setCurrentTheme(theme)
|
||||
print("is running! and registering bs_theme_dependencies_css")
|
||||
registerThemeDependency(bs_theme_dependencies_css)
|
||||
|
||||
} else {
|
||||
# Technically, this a potential issue (someone trying to execute/render
|
||||
# bootstrapLib outside of a Shiny app), but it seems that, in that case,
|
||||
# you likely have other problems, since sliderInput() et al. already assume
|
||||
# that Shiny is the one doing the rendering
|
||||
#warning(
|
||||
# "It appears `shiny::bootstrapLib()` was rendered outside of an Shiny ",
|
||||
# "application context, likely by calling `as.tags()`, `as.character()`, ",
|
||||
# "or `print()` directly on `bootstrapLib()` or UI components that may ",
|
||||
# "depend on it (e.g., `fluidPage()`, etc). For 'themable' UI components ",
|
||||
# "(e.g., `sliderInput()`, `selectInput()`, `dateInput()`, etc) to style ",
|
||||
# "themselves based on the Bootstrap theme, make sure `bootstrapLib()` is ",
|
||||
# "provided directly to the UI and that the UI is provided direction to ",
|
||||
# "`shinyApp()` (or `runApp()`)", call. = FALSE
|
||||
#)
|
||||
}
|
||||
|
||||
bootstraplib::bs_theme_dependencies(theme)
|
||||
})
|
||||
}
|
||||
|
||||
# This is defined outside of bootstrapLib() because registerThemeDependency()
|
||||
# wants non-anonymous functions.
|
||||
bs_theme_dependencies_css <- function(theme) {
|
||||
deps <- bootstraplib::bs_theme_dependencies(theme)
|
||||
# Extract out the CSS files only (no need to re-send JS files, even though
|
||||
# they wouldn't be re-rendered on the client anyway.)
|
||||
Filter(deps, f = function(dep) !is.null(dep$stylesheet))
|
||||
}
|
||||
|
||||
is_bs_theme <- function(x) {
|
||||
is_available("bootstraplib", "0.2.0.9000") &&
|
||||
bootstraplib::is_bs_theme(x)
|
||||
}
|
||||
|
||||
#' Obtain Shiny's Bootstrap Sass theme
|
||||
#'
|
||||
#' Intended for use by Shiny developers to create Shiny bindings with intelligent
|
||||
#' styling based on the [bootstrapLib()]'s `theme` value.
|
||||
#'
|
||||
#' @return If called at render-time (i.e., inside a [htmltools::tagFunction()]),
|
||||
#' and [bootstrapLib()]'s `theme` has been set to a [bootstraplib::bs_theme()]
|
||||
#' object, then this returns the `theme`. Otherwise, this returns `NULL`.
|
||||
#' @seealso [getCurrentOutputInfo()], [bootstrapLib()], [htmltools::tagFunction()]
|
||||
#'
|
||||
#' @keywords internal
|
||||
#' @export
|
||||
getCurrentTheme <- function() {
|
||||
getShinyOption("bootstrapTheme")
|
||||
}
|
||||
|
||||
setCurrentTheme <- function(theme) {
|
||||
shinyOptions(bootstrapTheme = theme)
|
||||
}
|
||||
|
||||
#' Register a theme dependency
|
||||
#'
|
||||
#' This function registers a function that returns an [htmlDependency()] or list
|
||||
#' of such objects. If `session$setCurrentTheme()` is called, the function will
|
||||
#' be re-executed, and the resulting html dependency will be sent to the client.
|
||||
#'
|
||||
#' Note that `func` should **not** be an anonymous function, or a function which
|
||||
#' is defined within the calling function. This is so that,
|
||||
#' `registerThemeDependency()` is called multiple times with the function, it
|
||||
#' tries to deduplicate them
|
||||
#'
|
||||
#' @param func A function that takes one argument, `theme` (which is a
|
||||
#' [sass::sass_layer()] object), and returns an htmlDependency object, or list
|
||||
#' of them.
|
||||
#'
|
||||
#' @export
|
||||
#' @keywords internal
|
||||
registerThemeDependency <- function(func) {
|
||||
func_expr <- substitute(func)
|
||||
if (is.call(func_expr) && identical(func_expr[[1]], as.symbol("function"))) {
|
||||
warning("`func` should not be an anonymous function. ",
|
||||
"It should be declared outside of the function that calls registerThemeDependency(); ",
|
||||
"otherwise it will not be deduplicated by Shiny and multiple copies of the ",
|
||||
"resulting htmlDependency may be computed and sent to the client.")
|
||||
}
|
||||
if (!is.function(func) || length(formals(func)) != 1) {
|
||||
stop("`func` must be a function with one argument (the current theme)")
|
||||
}
|
||||
|
||||
# Note that this will automatically scope to the app or session level,
|
||||
# depending on if this is called from within a session or not.
|
||||
funcs <- getShinyOption("themeDependencyFuncs", list())
|
||||
str(funcs)
|
||||
# Don't add func if it's already present.
|
||||
have_func <- any(vapply(funcs, identical, logical(1), func))
|
||||
if (!have_func) {
|
||||
funcs[[length(funcs) + 1]] <- func
|
||||
}
|
||||
str(funcs)
|
||||
|
||||
shinyOptions("themeDependencyFuncs" = funcs)
|
||||
}
|
||||
|
||||
bootstrapDependency <- function(theme) {
|
||||
htmlDependency(
|
||||
"bootstrap", "3.4.1",
|
||||
c(
|
||||
href = "shared/bootstrap",
|
||||
file = system.file("www/shared/bootstrap", package = "shiny")
|
||||
@@ -70,8 +213,8 @@ bootstrapLib <- function(theme = NULL) {
|
||||
# Safely adding accessibility plugin for screen readers and keyboard users; no break for sighted aspects (see https://github.com/paypal/bootstrap-accessibility-plugin)
|
||||
"accessibility/js/bootstrap-accessibility.min.js"
|
||||
),
|
||||
stylesheet = if (is.null(theme)) c(
|
||||
"css/bootstrap.min.css",
|
||||
stylesheet = c(
|
||||
theme %OR% "css/bootstrap.min.css",
|
||||
# Safely adding accessibility plugin for screen readers and keyboard users; no break for sighted aspects (see https://github.com/paypal/bootstrap-accessibility-plugin)
|
||||
"accessibility/css/bootstrap-accessibility.css"
|
||||
),
|
||||
@@ -79,6 +222,7 @@ bootstrapLib <- function(theme = NULL) {
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
#' @rdname bootstrapPage
|
||||
#' @export
|
||||
basicPage <- function(...) {
|
||||
@@ -132,6 +276,7 @@ basicPage <- function(...) {
|
||||
#' shown in the document).
|
||||
#' @param bootstrap If `TRUE`, load the Bootstrap CSS library.
|
||||
#' @param theme URL to alternative Bootstrap stylesheet.
|
||||
#' @inheritParams bootstrapPage
|
||||
#'
|
||||
#' @family layout functions
|
||||
#'
|
||||
@@ -159,7 +304,7 @@ basicPage <- function(...) {
|
||||
#' )
|
||||
#' @export
|
||||
fillPage <- function(..., padding = 0, title = NULL, bootstrap = TRUE,
|
||||
theme = NULL) {
|
||||
theme = NULL, lang = NULL) {
|
||||
|
||||
fillCSS <- tags$head(tags$style(type = "text/css",
|
||||
"html, body { width: 100%; height: 100%; overflow: hidden; }",
|
||||
@@ -167,14 +312,18 @@ fillPage <- function(..., padding = 0, title = NULL, bootstrap = TRUE,
|
||||
))
|
||||
|
||||
if (isTRUE(bootstrap)) {
|
||||
bootstrapPage(title = title, theme = theme, fillCSS, ...)
|
||||
ui <- bootstrapPage(title = title, theme = theme, fillCSS, lang = lang, ...)
|
||||
} else {
|
||||
tagList(
|
||||
ui <- tagList(
|
||||
fillCSS,
|
||||
if (!is.null(title)) tags$head(tags$title(title)),
|
||||
...
|
||||
)
|
||||
|
||||
ui <- setLang(ui, lang)
|
||||
}
|
||||
|
||||
return(ui)
|
||||
}
|
||||
|
||||
collapseSizes <- function(padding) {
|
||||
@@ -226,6 +375,7 @@ collapseSizes <- function(padding) {
|
||||
#' `www/bootstrap.css` you would use `theme = "bootstrap.css"`.
|
||||
#' @param windowTitle The title that should be displayed by the browser window.
|
||||
#' Useful if `title` is not a string.
|
||||
#' @inheritParams bootstrapPage
|
||||
#' @param icon Optional icon to appear on a `navbarMenu` tab.
|
||||
#'
|
||||
#' @return A UI defintion that can be passed to the [shinyUI] function.
|
||||
@@ -270,7 +420,8 @@ navbarPage <- function(title,
|
||||
fluid = TRUE,
|
||||
responsive = NULL,
|
||||
theme = NULL,
|
||||
windowTitle = title) {
|
||||
windowTitle = title,
|
||||
lang = NULL) {
|
||||
|
||||
if (!missing(collapsable)) {
|
||||
shinyDeprecated("`collapsable` is deprecated; use `collapsible` instead.")
|
||||
@@ -341,6 +492,7 @@ navbarPage <- function(title,
|
||||
title = windowTitle,
|
||||
responsive = responsive,
|
||||
theme = theme,
|
||||
lang = lang,
|
||||
tags$nav(class=navbarClass, role="navigation", containerDiv),
|
||||
contentDiv
|
||||
)
|
||||
@@ -1312,6 +1464,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 icon An [icon()] to appear on the button. Default is `icon("download")`.
|
||||
#' @param ... Other arguments to pass to the container tag function.
|
||||
#'
|
||||
#' @examples
|
||||
@@ -1342,13 +1495,15 @@ uiOutput <- htmlOutput
|
||||
#' @export
|
||||
downloadButton <- function(outputId,
|
||||
label="Download",
|
||||
class=NULL, ...) {
|
||||
class=NULL,
|
||||
...,
|
||||
icon = shiny::icon("download")) {
|
||||
aTag <- tags$a(id=outputId,
|
||||
class=paste('btn btn-default shiny-download-link', class),
|
||||
href='',
|
||||
target='_blank',
|
||||
download=NA,
|
||||
icon("download"),
|
||||
validateIcon(icon),
|
||||
label, ...)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
# A context object for tracking a cache that needs to be dirtied when a set of
|
||||
# files changes on disk. Each time the cache is dirtied, the set of files is
|
||||
# cleared. Therefore, the set of files needs to be re-built each time the cached
|
||||
# code executes. This approach allows for dynamic dependency graphs.
|
||||
CacheContext <- R6Class(
|
||||
'CacheContext',
|
||||
portable = FALSE,
|
||||
class = FALSE,
|
||||
public = list(
|
||||
.dirty = TRUE,
|
||||
# List of functions that return TRUE if dirty
|
||||
.tests = list(),
|
||||
|
||||
addDependencyFile = function(file) {
|
||||
if (.dirty)
|
||||
return()
|
||||
|
||||
file <- normalizePath(file)
|
||||
|
||||
mtime <- file.info(file)$mtime
|
||||
.tests <<- c(.tests, function() {
|
||||
newMtime <- try(file.info(file)$mtime, silent=TRUE)
|
||||
if (inherits(newMtime, 'try-error'))
|
||||
return(TRUE)
|
||||
return(!identical(mtime, newMtime))
|
||||
})
|
||||
invisible()
|
||||
},
|
||||
forceDirty = function() {
|
||||
.dirty <<- TRUE
|
||||
.tests <<- list()
|
||||
invisible()
|
||||
},
|
||||
isDirty = function() {
|
||||
if (.dirty)
|
||||
return(TRUE)
|
||||
|
||||
for (test in .tests) {
|
||||
if (test()) {
|
||||
forceDirty()
|
||||
return(TRUE)
|
||||
}
|
||||
}
|
||||
|
||||
return(FALSE)
|
||||
},
|
||||
reset = function() {
|
||||
.dirty <<- FALSE
|
||||
.tests <<- list()
|
||||
},
|
||||
with = function(func) {
|
||||
oldCC <- .currentCacheContext$cc
|
||||
.currentCacheContext$cc <- self
|
||||
on.exit(.currentCacheContext$cc <- oldCC)
|
||||
|
||||
return(func())
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
.currentCacheContext <- new.env()
|
||||
|
||||
# Indicates to Shiny that the given file path is part of the dependency graph
|
||||
# for whatever is currently executing (so far, only ui.R). By default, ui.R only
|
||||
# gets re-executed when it is detected to have changed; this function allows the
|
||||
# caller to indicate that it should also re-execute if the given file changes.
|
||||
#
|
||||
# If NULL or NA is given as the argument, then ui.R will re-execute next time.
|
||||
dependsOnFile <- function(filepath) {
|
||||
if (is.null(.currentCacheContext$cc))
|
||||
return()
|
||||
|
||||
if (is.null(filepath) || is.na(filepath))
|
||||
.currentCacheContext$cc$forceDirty()
|
||||
else
|
||||
.currentCacheContext$cc$addDependencyFile(filepath)
|
||||
}
|
||||
@@ -130,8 +130,8 @@
|
||||
#' if an object is in the cache, and then call `get(key)`, the object may
|
||||
#' be removed from the cache in between those two calls, and `get(key)`
|
||||
#' will throw an error. Instead of calling the two functions, it is better to
|
||||
#' simply call `get(key)`, and use `tryCatch()` to handle the error
|
||||
#' that is thrown if the object is not in the cache. This effectively tests for
|
||||
#' simply call `get(key)`, and check that the returned object is not a
|
||||
#' `key_missing()` object, using `is.key_missing()`. This effectively tests for
|
||||
#' existence and gets the object in one operation.
|
||||
#'
|
||||
#' It is also possible for one processes to prune objects at the same time that
|
||||
@@ -387,7 +387,7 @@ DiskCache <- R6Class("DiskCache",
|
||||
# is because it is expensive to find the size of the serialized object
|
||||
# before adding it.
|
||||
|
||||
private$log(paste0('prune'))
|
||||
private$log('prune')
|
||||
self$is_destroyed(throw = TRUE)
|
||||
|
||||
current_time <- Sys.time()
|
||||
@@ -407,7 +407,11 @@ DiskCache <- R6Class("DiskCache",
|
||||
rm_idx <- timediff > private$max_age
|
||||
if (any(rm_idx)) {
|
||||
private$log(paste0("prune max_age: Removing ", paste(info$name[rm_idx], collapse = ", ")))
|
||||
file.remove(info$name[rm_idx])
|
||||
rm_success <- file.remove(info$name[rm_idx])
|
||||
# This maps rm_success back into the TRUEs in the rm_idx vector.
|
||||
# If (for example) rm_idx is c(F,T,F,T,T) and rm_success is c(T,F,T),
|
||||
# then this line modifies rm_idx to be c(F,T,F,F,T).
|
||||
rm_idx[rm_idx] <- rm_success
|
||||
info <- info[!rm_idx, ]
|
||||
}
|
||||
}
|
||||
@@ -428,7 +432,8 @@ DiskCache <- R6Class("DiskCache",
|
||||
rm_idx <- seq_len(nrow(info)) > private$max_n
|
||||
private$log(paste0("prune max_n: Removing ", paste(info$name[rm_idx], collapse = ", ")))
|
||||
rm_success <- file.remove(info$name[rm_idx])
|
||||
info <- info[!rm_success, ]
|
||||
rm_idx[rm_idx] <- rm_success
|
||||
info <- info[!rm_idx, ]
|
||||
}
|
||||
|
||||
# 3. Remove files if cache is too large.
|
||||
@@ -438,7 +443,8 @@ DiskCache <- R6Class("DiskCache",
|
||||
rm_idx <- cum_size > private$max_size
|
||||
private$log(paste0("prune max_size: Removing ", paste(info$name[rm_idx], collapse = ", ")))
|
||||
rm_success <- file.remove(info$name[rm_idx])
|
||||
info <- info[!rm_success, ]
|
||||
rm_idx[rm_idx] <- rm_success
|
||||
info <- info[!rm_idx, ]
|
||||
}
|
||||
|
||||
private$prune_last_time <- as.numeric(current_time)
|
||||
@@ -555,7 +561,7 @@ DiskCache <- R6Class("DiskCache",
|
||||
if (is.null(private$logfile)) return()
|
||||
|
||||
text <- paste0(format(Sys.time(), "[%Y-%m-%d %H:%M:%OS3] DiskCache "), text)
|
||||
writeLines(text, private$logfile)
|
||||
cat(text, sep = "\n", file = private$logfile, append = TRUE)
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
@@ -359,7 +359,7 @@ MemoryCache <- R6Class("MemoryCache",
|
||||
if (is.null(private$logfile)) return()
|
||||
|
||||
text <- paste0(format(Sys.time(), "[%Y-%m-%d %H:%M:%OS3] MemoryCache "), text)
|
||||
writeLines(text, private$logfile)
|
||||
cat(text, sep = "\n", file = private$logfile, append = TRUE)
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
@@ -87,7 +87,8 @@ reactlog <- function() {
|
||||
}
|
||||
|
||||
#' @describeIn reactlog Display a full reactlog graph for all sessions.
|
||||
#' @inheritParams reactlog::reactlog_show
|
||||
#' @param time A boolean that specifies whether or not to display the
|
||||
#' time that each reactive takes to calculate a result.
|
||||
#' @export
|
||||
reactlogShow <- function(time = TRUE) {
|
||||
check_reactlog()
|
||||
@@ -179,10 +180,10 @@ RLog <- R6Class(
|
||||
paste0("names(", reactId, ")")
|
||||
},
|
||||
asListIdStr = function(reactId) {
|
||||
paste0("as.list(", reactId, ")")
|
||||
paste0("reactiveValuesToList(", reactId, ")")
|
||||
},
|
||||
asListAllIdStr = function(reactId) {
|
||||
paste0("as.list(", reactId, ", all.names = TRUE)")
|
||||
paste0("reactiveValuesToList(", reactId, ", all.names = TRUE)")
|
||||
},
|
||||
keyIdStr = function(reactId, key) {
|
||||
paste0(reactId, "$", key)
|
||||
|
||||
@@ -1,15 +1,26 @@
|
||||
#' Create an object representing click options
|
||||
#' Control interactive plot point events
|
||||
#'
|
||||
#' This generates an object representing click options, to be passed as the
|
||||
#' `click` argument of [imageOutput()] or
|
||||
#' [plotOutput()].
|
||||
#' These functions give control over the `click`, `dblClick` and
|
||||
#' `hover` events generated by [imageOutput()] and [plotOutput()].
|
||||
#'
|
||||
#' @param id Input value name. For example, if the value is `"plot_click"`,
|
||||
#' then the click coordinates will be available as `input$plot_click`.
|
||||
#' @param clip Should the click area be clipped to the plotting area? If FALSE,
|
||||
#' then the server will receive click events even when the mouse is outside
|
||||
#' the plotting area, as long as it is still inside the image.
|
||||
#' then the event data will be available as `input$plot_click`.
|
||||
#' @param clip Should the click area be clipped to the plotting area? If
|
||||
#' `FALSE`, then the server will receive click events even when the mouse is
|
||||
#' outside the plotting area, as long as it is still inside the image.
|
||||
#' @param delay For `dblClickOpts()`: the maximum delay (in ms) between a
|
||||
#' pair clicks for them to be counted as a double-click.
|
||||
#'
|
||||
#' For `hoverOpts()`: how long to delay (in ms) when debouncing or throttling
|
||||
#' before sending the mouse location to the server.
|
||||
#' @param delayType The type of algorithm for limiting the number of hover
|
||||
#' events. Use `"throttle"` to limit the number of hover events to one
|
||||
#' every `delay` milliseconds. Use `"debounce"` to suspend events
|
||||
#' while the cursor is moving, and wait until the cursor has been at rest for
|
||||
#' `delay` milliseconds before sending an event.
|
||||
#' @seealso [brushOpts()] for brushing events.
|
||||
#' @export
|
||||
#' @keywords internal
|
||||
clickOpts <- function(id, clip = TRUE) {
|
||||
if (is.null(id))
|
||||
stop("id must not be NULL")
|
||||
@@ -21,21 +32,8 @@ clickOpts <- function(id, clip = TRUE) {
|
||||
}
|
||||
|
||||
|
||||
#' Create an object representing double-click options
|
||||
#'
|
||||
#' This generates an object representing dobule-click options, to be passed as
|
||||
#' the `dblclick` argument of [imageOutput()] or
|
||||
#' [plotOutput()].
|
||||
#'
|
||||
#' @param id Input value name. For example, if the value is
|
||||
#' `"plot_dblclick"`, then the click coordinates will be available as
|
||||
#' `input$plot_dblclick`.
|
||||
#' @param clip Should the click area be clipped to the plotting area? If FALSE,
|
||||
#' then the server will receive double-click events even when the mouse is
|
||||
#' outside the plotting area, as long as it is still inside the image.
|
||||
#' @param delay Maximum delay (in ms) between a pair clicks for them to be
|
||||
#' counted as a double-click.
|
||||
#' @export
|
||||
#' @rdname clickOpts
|
||||
dblclickOpts <- function(id, clip = TRUE, delay = 400) {
|
||||
if (is.null(id))
|
||||
stop("id must not be NULL")
|
||||
@@ -47,28 +45,11 @@ dblclickOpts <- function(id, clip = TRUE, delay = 400) {
|
||||
)
|
||||
}
|
||||
|
||||
#' Create an object representing hover options
|
||||
#'
|
||||
#' This generates an object representing hovering options, to be passed as the
|
||||
#' `hover` argument of [imageOutput()] or
|
||||
#' [plotOutput()].
|
||||
#'
|
||||
#' @param id Input value name. For example, if the value is `"plot_hover"`,
|
||||
#' then the hover coordinates will be available as `input$plot_hover`.
|
||||
#' @param delay How long to delay (in milliseconds) when debouncing or
|
||||
#' throttling, before sending the mouse location to the server.
|
||||
#' @param delayType The type of algorithm for limiting the number of hover
|
||||
#' events. Use `"throttle"` to limit the number of hover events to one
|
||||
#' every `delay` milliseconds. Use `"debounce"` to suspend events
|
||||
#' while the cursor is moving, and wait until the cursor has been at rest for
|
||||
#' `delay` milliseconds before sending an event.
|
||||
#' @param clip Should the hover area be clipped to the plotting area? If FALSE,
|
||||
#' then the server will receive hover events even when the mouse is outside
|
||||
#' the plotting area, as long as it is still inside the image.
|
||||
#' @param nullOutside If `TRUE` (the default), the value will be set to
|
||||
#' `NULL` when the mouse exits the plotting area. If `FALSE`, the
|
||||
#' value will stop changing when the cursor exits the plotting area.
|
||||
#' @export
|
||||
#' @rdname clickOpts
|
||||
hoverOpts <- function(id, delay = 300,
|
||||
delayType = c("debounce", "throttle"), clip = TRUE,
|
||||
nullOutside = TRUE) {
|
||||
@@ -116,6 +97,7 @@ hoverOpts <- function(id, delay = 300,
|
||||
#' `FALSE`, is useful if you want to update the plot while keeping the
|
||||
#' brush. Using `TRUE` is useful if you want to clear the brush whenever
|
||||
#' the plot is updated.
|
||||
#' @seealso [clickOpts()] for clicking events.
|
||||
#' @export
|
||||
brushOpts <- function(id, fill = "#9cf", stroke = "#036",
|
||||
opacity = 0.25, delay = 300,
|
||||
|
||||
@@ -110,6 +110,10 @@ dateInput <- function(inputId, label, value = NULL, min = NULL, max = NULL,
|
||||
shinyInputLabel(inputId, label),
|
||||
tags$input(type = "text",
|
||||
class = "form-control",
|
||||
# `aria-labelledby` attribute is required for accessibility to avoid doubled labels (#2951).
|
||||
`aria-labelledby` = paste0(inputId, "-label"),
|
||||
# title attribute is announced for screen readers for date format.
|
||||
title = paste("Date format:", format),
|
||||
`data-date-language` = language,
|
||||
`data-date-week-start` = weekstart,
|
||||
`data-date-format` = format,
|
||||
@@ -124,19 +128,48 @@ dateInput <- function(inputId, label, value = NULL, min = NULL, max = NULL,
|
||||
`data-date-days-of-week-disabled` =
|
||||
jsonlite::toJSON(daysofweekdisabled, null = 'null')
|
||||
),
|
||||
datePickerDependency
|
||||
datePickerDependency()
|
||||
)
|
||||
}
|
||||
|
||||
datePickerDependency <- htmlDependency(
|
||||
"bootstrap-datepicker", "1.6.4", c(href = "shared/datepicker"),
|
||||
script = "js/bootstrap-datepicker.min.js",
|
||||
stylesheet = "css/bootstrap-datepicker3.min.css",
|
||||
# Need to enable noConflict mode. See #1346.
|
||||
head = "<script>
|
||||
(function() {
|
||||
var datepicker = $.fn.datepicker.noConflict();
|
||||
$.fn.bsDatepicker = datepicker;
|
||||
})();
|
||||
</script>"
|
||||
)
|
||||
|
||||
datePickerVersion <- "1.9.0"
|
||||
|
||||
datePickerDependency <- function(theme) {
|
||||
list(
|
||||
htmlDependency(
|
||||
name = "bootstrap-datepicker-js",
|
||||
version = datePickerVersion,
|
||||
src = c(href = "shared/datepicker"),
|
||||
script = "js/bootstrap-datepicker.min.js",
|
||||
# Need to enable noConflict mode. See #1346.
|
||||
head = "<script>(function() {
|
||||
var datepicker = $.fn.datepicker.noConflict();
|
||||
$.fn.bsDatepicker = datepicker;
|
||||
})();
|
||||
</script>"
|
||||
),
|
||||
bootstraplib::bs_dependency_defer(datePickerCSS)
|
||||
)
|
||||
}
|
||||
|
||||
datePickerCSS <- function(theme) {
|
||||
if (!is_bs_theme(theme)) {
|
||||
return(htmlDependency(
|
||||
name = "bootstrap-datepicker-css",
|
||||
version = datePickerVersion,
|
||||
src = c(href = "shared/datepicker"),
|
||||
stylesheet = "css/bootstrap-datepicker3.min.css"
|
||||
))
|
||||
}
|
||||
|
||||
scss_file <- system.file(package = "shiny", "www/shared/datepicker/scss/build3.scss")
|
||||
|
||||
bootstraplib::bs_dependency(
|
||||
input = sass::sass_file(scss_file),
|
||||
theme = theme,
|
||||
name = "bootstrap-datepicker",
|
||||
version = datePickerVersion,
|
||||
cache_key_extra = utils::packageVersion("shiny")
|
||||
)
|
||||
}
|
||||
|
||||
@@ -100,6 +100,10 @@ dateRangeInput <- function(inputId, label, start = NULL, end = NULL,
|
||||
tags$input(
|
||||
class = "form-control",
|
||||
type = "text",
|
||||
# `aria-labelledby` attribute is required for accessibility to avoid doubled labels (#2951).
|
||||
`aria-labelledby` = paste0(inputId, "-label"),
|
||||
# title attribute is announced for screen readers for date format.
|
||||
title = paste("Date format:", format),
|
||||
`data-date-language` = language,
|
||||
`data-date-week-start` = weekstart,
|
||||
`data-date-format` = format,
|
||||
@@ -118,6 +122,10 @@ dateRangeInput <- function(inputId, label, start = NULL, end = NULL,
|
||||
tags$input(
|
||||
class = "form-control",
|
||||
type = "text",
|
||||
# `aria-labelledby` attribute is required for accessibility to avoid doubled labels (#2951).
|
||||
`aria-labelledby` = paste0(inputId, "-label"),
|
||||
# title attribute is announced for screen readers for date format.
|
||||
title = paste("Date format:", format),
|
||||
`data-date-language` = language,
|
||||
`data-date-week-start` = weekstart,
|
||||
`data-date-format` = format,
|
||||
@@ -129,6 +137,6 @@ dateRangeInput <- function(inputId, label, start = NULL, end = NULL,
|
||||
)
|
||||
)
|
||||
),
|
||||
datePickerDependency
|
||||
datePickerDependency()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -11,22 +11,22 @@
|
||||
#' @inheritParams textInput
|
||||
#' @param choices List of values to select from (if elements of the list are
|
||||
#' named then that name rather than the value is displayed to the user). If
|
||||
#' this argument is provided, then `choiceNames` and `choiceValues`
|
||||
#' must not be provided, and vice-versa. The values should be strings; other
|
||||
#' types (such as logicals and numbers) will be coerced to strings.
|
||||
#' @param selected The initially selected value (if not specified then defaults
|
||||
#' to the first value)
|
||||
#' this argument is provided, then `choiceNames` and `choiceValues` must not
|
||||
#' be provided, and vice-versa. The values should be strings; other types
|
||||
#' (such as logicals and numbers) will be coerced to strings.
|
||||
#' @param selected The initially selected value. If not specified, then it
|
||||
#' defaults to the first item in `choices`. To start with no items selected,
|
||||
#' use `character(0)`.
|
||||
#' @param inline If `TRUE`, render the choices inline (i.e. horizontally)
|
||||
#' @return A set of radio buttons that can be added to a UI definition.
|
||||
#' @param choiceNames,choiceValues List of names and values, respectively, that
|
||||
#' are displayed to the user in the app and correspond to the each choice (for
|
||||
#' this reason, `choiceNames` and `choiceValues` must have the same
|
||||
#' length). If either of these arguments is provided, then the other
|
||||
#' *must* be provided and `choices` *must not* be provided. The
|
||||
#' advantage of using both of these over a named list for `choices` is
|
||||
#' that `choiceNames` allows any type of UI object to be passed through
|
||||
#' (tag objects, icons, HTML code, ...), instead of just simple text. See
|
||||
#' Examples.
|
||||
#' this reason, `choiceNames` and `choiceValues` must have the same length).
|
||||
#' If either of these arguments is provided, then the other *must* be provided
|
||||
#' and `choices` *must not* be provided. The advantage of using both of these
|
||||
#' over a named list for `choices` is that `choiceNames` allows any type of UI
|
||||
#' object to be passed through (tag objects, icons, HTML code, ...), instead
|
||||
#' of just simple text. See Examples.
|
||||
#'
|
||||
#' @family input elements
|
||||
#' @seealso [updateRadioButtons()]
|
||||
@@ -82,7 +82,8 @@
|
||||
#' }
|
||||
#'
|
||||
#' @section Server value:
|
||||
#' A character string containing the value of the selected button.
|
||||
#'
|
||||
#' A character string containing the value of the selected button.
|
||||
#'
|
||||
#' @export
|
||||
radioButtons <- function(inputId, label, choices = NULL, selected = NULL,
|
||||
|
||||
@@ -12,6 +12,14 @@
|
||||
#' name will be treated as a placeholder prompt. For example:
|
||||
#' `selectInput("letter", "Letter", c("Choose one" = "", LETTERS))`
|
||||
#'
|
||||
#' **Performance note:** `selectInput()` and `selectizeInput()` can slow down
|
||||
#' significantly when thousands of choices are used; with legacy browsers like
|
||||
#' Internet Explorer, the user interface may hang for many seconds. For large
|
||||
#' numbers of choices, Shiny offers a "server-side selectize" option that
|
||||
#' massively improves performance and efficiency; see
|
||||
#' [this selectize article](https://shiny.rstudio.com/articles/selectize.html)
|
||||
#' on the Shiny Dev Center for details.
|
||||
#'
|
||||
#' @inheritParams textInput
|
||||
#' @param choices List of values to select from. If elements of the list are
|
||||
#' named, then that name --- rather than the value --- is displayed to the
|
||||
@@ -100,7 +108,7 @@ selectInput <- function(inputId, label, choices, selected = NULL,
|
||||
id = inputId,
|
||||
class = if (!selectize) "form-control",
|
||||
size = size,
|
||||
selectOptions(choices, selected)
|
||||
selectOptions(choices, selected, inputId, selectize)
|
||||
)
|
||||
if (multiple)
|
||||
selectTag$attribs$multiple <- "multiple"
|
||||
@@ -125,16 +133,22 @@ firstChoice <- function(choices) {
|
||||
}
|
||||
|
||||
# Create tags for each of the options; use <optgroup> if necessary.
|
||||
# This returns a HTML string instead of tags, because of the 'selected'
|
||||
# attribute.
|
||||
selectOptions <- function(choices, selected = NULL) {
|
||||
# This returns a HTML string instead of tags for performance reasons.
|
||||
selectOptions <- function(choices, selected = NULL, inputId, perfWarning = FALSE) {
|
||||
if (length(choices) >= 1000) {
|
||||
warning("The select input \"", inputId, "\" contains a large number of ",
|
||||
"options; consider using server-side selectize for massively improved ",
|
||||
"performance. See the Details section of the ?selectizeInput help topic.",
|
||||
call. = FALSE)
|
||||
}
|
||||
|
||||
html <- mapply(choices, names(choices), FUN = function(choice, label) {
|
||||
if (is.list(choice)) {
|
||||
# If sub-list, create an optgroup and recurse into the sublist
|
||||
sprintf(
|
||||
'<optgroup label="%s">\n%s\n</optgroup>',
|
||||
htmlEscape(label, TRUE),
|
||||
selectOptions(choice, selected)
|
||||
selectOptions(choice, selected, inputId, perfWarning)
|
||||
)
|
||||
|
||||
} else {
|
||||
@@ -183,24 +197,25 @@ selectizeInput <- function(inputId, ..., options = NULL, width = NULL) {
|
||||
|
||||
# given a select input and its id, selectize it
|
||||
selectizeIt <- function(inputId, select, options, nonempty = FALSE) {
|
||||
# Make sure accessibility plugin is included
|
||||
if (!('selectize-plugin-a11y' %in% options$plugins)) {
|
||||
options$plugins <- c(options$plugins, list('selectize-plugin-a11y'))
|
||||
}
|
||||
|
||||
res <- checkAsIs(options)
|
||||
|
||||
selectizeDep <- htmlDependency(
|
||||
"selectize", "0.11.2", c(href = "shared/selectize"),
|
||||
stylesheet = "css/selectize.bootstrap3.css",
|
||||
head = format(tagList(
|
||||
HTML('<!--[if lt IE 9]>'),
|
||||
tags$script(src = 'shared/selectize/js/es5-shim.min.js'),
|
||||
HTML('<![endif]-->'),
|
||||
tags$script(src = 'shared/selectize/js/selectize.min.js')
|
||||
))
|
||||
)
|
||||
selectizeDep <- selectizeDependency()
|
||||
|
||||
if ('drag_drop' %in% options$plugins) {
|
||||
selectizeDep <- list(selectizeDep, htmlDependency(
|
||||
'jqueryui', '1.12.1', c(href = 'shared/jqueryui'),
|
||||
script = 'jquery-ui.min.js'
|
||||
))
|
||||
selectizeDep <- c(
|
||||
selectizeDep,
|
||||
htmlDependency(
|
||||
'jqueryui',
|
||||
'1.12.1',
|
||||
c(href = 'shared/jqueryui'),
|
||||
script = 'jquery-ui.min.js'
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
# Insert script on same level as <select> tag
|
||||
@@ -218,10 +233,50 @@ selectizeIt <- function(inputId, select, options, nonempty = FALSE) {
|
||||
}
|
||||
|
||||
|
||||
selectizeVersion <- "0.12.4"
|
||||
|
||||
selectizeDependency <- function(theme) {
|
||||
list(
|
||||
htmlDependency(
|
||||
"selectize-js",
|
||||
selectizeVersion,
|
||||
src = c(href = "shared/selectize"),
|
||||
script = c(
|
||||
"js/selectize.min.js",
|
||||
# Accessibility plugin for screen readers (https://github.com/SLMNBJ/selectize-plugin-a11y):
|
||||
"accessibility/js/selectize-plugin-a11y.min.js"
|
||||
)
|
||||
),
|
||||
bootstraplib::bs_dependency_defer(selectizeCSS)
|
||||
)
|
||||
}
|
||||
|
||||
selectizeCSS <- function(theme) {
|
||||
if (!is_bs_theme(theme)) {
|
||||
return(htmlDependency(
|
||||
name = "selectize-css",
|
||||
version = selectizeVersion,
|
||||
src = c(href = "shared/selectize"),
|
||||
stylesheet = "css/selectize.bootstrap3.css"
|
||||
))
|
||||
}
|
||||
|
||||
|
||||
scss_file <- system.file(
|
||||
package = "shiny", "www/shared/selectize/scss",
|
||||
if ("3" %in% bootstraplib::theme_version(theme)) {
|
||||
"selectize.bootstrap3.scss"
|
||||
} else {
|
||||
"selectize.bootstrap4.scss"
|
||||
}
|
||||
)
|
||||
bootstraplib::bs_dependency(
|
||||
input = sass::sass_file(scss_file),
|
||||
theme = theme,
|
||||
name = "selectize",
|
||||
version = selectizeVersion,
|
||||
cache_key_extra = utils::packageVersion("shiny")
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
#' Select variables from a data frame
|
||||
|
||||
@@ -79,8 +79,7 @@ sliderInput <- function(inputId, label, min, max, value, step = NULL,
|
||||
round = FALSE, format = NULL, locale = NULL,
|
||||
ticks = TRUE, animate = FALSE, width = NULL, sep = ",",
|
||||
pre = NULL, post = NULL, timeFormat = NULL,
|
||||
timezone = NULL, dragRange = TRUE)
|
||||
{
|
||||
timezone = NULL, dragRange = TRUE) {
|
||||
if (!missing(format)) {
|
||||
shinyDeprecated(msg = "The `format` argument to sliderInput is deprecated. Use `sep`, `pre`, and `post` instead.",
|
||||
version = "0.10.2.2")
|
||||
@@ -144,6 +143,7 @@ sliderInput <- function(inputId, label, min, max, value, step = NULL,
|
||||
sliderProps <- dropNulls(list(
|
||||
class = "js-range-slider",
|
||||
id = inputId,
|
||||
`data-skin` = "shiny",
|
||||
`data-type` = if (length(value) > 1) "double",
|
||||
`data-min` = formatNoSci(min),
|
||||
`data-max` = formatNoSci(max),
|
||||
@@ -205,20 +205,59 @@ sliderInput <- function(inputId, label, min, max, value, step = NULL,
|
||||
)
|
||||
}
|
||||
|
||||
dep <- list(
|
||||
htmlDependency("ionrangeslider", "2.1.6", c(href="shared/ionrangeslider"),
|
||||
script = "js/ion.rangeSlider.min.js",
|
||||
# ion.rangeSlider also needs normalize.css, which is already included in
|
||||
# Bootstrap.
|
||||
stylesheet = c("css/ion.rangeSlider.css",
|
||||
"css/ion.rangeSlider.skinShiny.css")
|
||||
attachDependencies(sliderTag, ionRangeSliderDependency())
|
||||
}
|
||||
|
||||
|
||||
ionRangeSliderVersion <- "2.3.1"
|
||||
|
||||
ionRangeSliderDependency <- function() {
|
||||
list(
|
||||
# ion.rangeSlider also needs normalize.css, which is already included in Bootstrap.
|
||||
htmlDependency(
|
||||
"ionrangeslider-javascript", ionRangeSliderVersion,
|
||||
src = c(href = "shared/ionrangeslider"),
|
||||
script = "js/ion.rangeSlider.min.js"
|
||||
),
|
||||
htmlDependency("strftime", "0.9.2", c(href="shared/strftime"),
|
||||
htmlDependency(
|
||||
"strftime", "0.9.2",
|
||||
src = c(href = "shared/strftime"),
|
||||
script = "strftime-min.js"
|
||||
),
|
||||
bootstraplib::bs_dependency_defer(ionRangeSliderDependencyCSS)
|
||||
)
|
||||
}
|
||||
|
||||
ionRangeSliderDependencyCSS <- function(theme) {
|
||||
if (!is_bs_theme(theme)) {
|
||||
return(htmlDependency(
|
||||
"ionrangeslider-css",
|
||||
ionRangeSliderVersion,
|
||||
src = c(href = "shared/ionrangeslider"),
|
||||
stylesheet = "css/ion.rangeSlider.css"
|
||||
))
|
||||
}
|
||||
|
||||
# Remap some variable names for ionRangeSlider's scss
|
||||
sass_input <- list(
|
||||
list(
|
||||
bg = "$input-bg",
|
||||
fg = "$input-color",
|
||||
accent = "$component-active-bg",
|
||||
`font-family` = "$font-family-base"
|
||||
),
|
||||
sass::sass_file(
|
||||
system.file(package = "shiny", "www/shared/ionrangeslider/scss/shiny.scss")
|
||||
)
|
||||
)
|
||||
|
||||
attachDependencies(sliderTag, dep)
|
||||
bootstraplib::bs_dependency(
|
||||
input = sass_input,
|
||||
theme = theme,
|
||||
name = "ionRangeSlider",
|
||||
version = ionRangeSliderVersion,
|
||||
cache_key_extra = utils::packageVersion("shiny")
|
||||
)
|
||||
}
|
||||
|
||||
hasDecimals <- function(value) {
|
||||
@@ -226,7 +265,6 @@ hasDecimals <- function(value) {
|
||||
return (!identical(value, truncatedValue))
|
||||
}
|
||||
|
||||
|
||||
# If step is NULL, use heuristic to set the step size.
|
||||
findStepSize <- function(min, max, step) {
|
||||
if (!is.null(step)) return(step)
|
||||
|
||||
@@ -51,7 +51,8 @@ textAreaInput <- function(inputId, label, value = "", width = NULL, height = NUL
|
||||
}
|
||||
|
||||
style <- paste(
|
||||
if (!is.null(width)) paste0("width: ", validateCssUnit(width), ";"),
|
||||
# The width is specified on the parent div.
|
||||
if (!is.null(width)) paste0("width: ", "100%", ";"),
|
||||
if (!is.null(height)) paste0("height: ", validateCssUnit(height), ";"),
|
||||
if (!is.null(resize)) paste0("resize: ", resize, ";")
|
||||
)
|
||||
@@ -62,6 +63,7 @@ textAreaInput <- function(inputId, label, value = "", width = NULL, height = NUL
|
||||
|
||||
div(class = "form-group shiny-input-container",
|
||||
shinyInputLabel(inputId, label),
|
||||
style = if (!is.null(width)) paste0("width: ", validateCssUnit(width), ";"),
|
||||
tags$textarea(
|
||||
id = inputId,
|
||||
class = "form-control",
|
||||
|
||||
@@ -3,6 +3,8 @@ shinyInputLabel <- function(inputId, label = NULL) {
|
||||
label,
|
||||
class = "control-label",
|
||||
class = if (is.null(label)) "shiny-label-null",
|
||||
# `id` attribute is required for `aria-labelledby` used by screen readers:
|
||||
id = paste0(inputId, "-label"),
|
||||
`for` = inputId
|
||||
)
|
||||
}
|
||||
|
||||
80
R/knitr.R
Normal file
80
R/knitr.R
Normal file
@@ -0,0 +1,80 @@
|
||||
#' Knitr S3 methods
|
||||
#'
|
||||
#' These S3 methods are necessary to help Shiny applications and UI chunks embed
|
||||
#' themselves in knitr/rmarkdown documents.
|
||||
#'
|
||||
#' @name knitr_methods
|
||||
#' @param x Object to knit_print
|
||||
#' @param ... Additional knit_print arguments
|
||||
NULL
|
||||
|
||||
# If there's an R Markdown runtime option set but it isn't set to Shiny, then
|
||||
# return a warning indicating the runtime is inappropriate for this object.
|
||||
# Returns NULL in all other cases.
|
||||
shiny_rmd_warning <- function() {
|
||||
runtime <- knitr::opts_knit$get("rmarkdown.runtime")
|
||||
if (!is.null(runtime) && runtime != "shiny")
|
||||
# note that the RStudio IDE checks for this specific string to detect Shiny
|
||||
# applications in static document
|
||||
list(structure(
|
||||
"Shiny application in a static R Markdown document",
|
||||
class = "rmd_warning"))
|
||||
else
|
||||
NULL
|
||||
}
|
||||
|
||||
#' @rdname knitr_methods
|
||||
knit_print.shiny.appobj <- function(x, ...) {
|
||||
opts <- x$options %OR% list()
|
||||
width <- if (is.null(opts$width)) "100%" else opts$width
|
||||
height <- if (is.null(opts$height)) "400" else opts$height
|
||||
|
||||
runtime <- knitr::opts_knit$get("rmarkdown.runtime")
|
||||
if (!is.null(runtime) && runtime != "shiny") {
|
||||
# If not rendering to a Shiny document, create a box exactly the same
|
||||
# dimensions as the Shiny app would have had (so the document continues to
|
||||
# flow as it would have with the app), and display a diagnostic message
|
||||
width <- validateCssUnit(width)
|
||||
height <- validateCssUnit(height)
|
||||
output <- tags$div(
|
||||
style=paste("width:", width, "; height:", height, "; text-align: center;",
|
||||
"box-sizing: border-box;", "-moz-box-sizing: border-box;",
|
||||
"-webkit-box-sizing: border-box;"),
|
||||
class="muted well",
|
||||
"Shiny applications not supported in static R Markdown documents")
|
||||
}
|
||||
else {
|
||||
path <- addSubApp(x)
|
||||
output <- deferredIFrame(path, width, height)
|
||||
}
|
||||
|
||||
# If embedded Shiny apps ever have JS/CSS dependencies (like pym.js) we'll
|
||||
# need to grab those and put them in meta, like in knit_print.shiny.tag. But
|
||||
# for now it's not an issue, so just return the HTML and warning.
|
||||
|
||||
knitr::asis_output(htmlPreserve(format(output, indent=FALSE)),
|
||||
meta = shiny_rmd_warning(), cacheable = FALSE)
|
||||
}
|
||||
|
||||
# Let us use a nicer syntax in knitr chunks than literally
|
||||
# calling output$value <- renderFoo(...) and fooOutput().
|
||||
#' @rdname knitr_methods
|
||||
#' @param inline Whether the object is printed inline.
|
||||
knit_print.shiny.render.function <- function(x, ..., inline = FALSE) {
|
||||
x <- htmltools::as.tags(x, inline = inline)
|
||||
output <- knitr::knit_print(tagList(x))
|
||||
attr(output, "knit_cacheable") <- FALSE
|
||||
attr(output, "knit_meta") <- append(attr(output, "knit_meta"),
|
||||
shiny_rmd_warning())
|
||||
output
|
||||
}
|
||||
|
||||
# Lets us drop reactive expressions directly into a knitr chunk and have the
|
||||
# value printed out! Nice for teaching if nothing else.
|
||||
#' @rdname knitr_methods
|
||||
knit_print.reactive <- function(x, ..., inline = FALSE) {
|
||||
renderFunc <- if (inline) renderText else renderPrint
|
||||
knitr::knit_print(renderFunc({
|
||||
x()
|
||||
}), inline = inline)
|
||||
}
|
||||
@@ -31,7 +31,6 @@ extract <- function(promise) {
|
||||
#' @noRd
|
||||
#' @export
|
||||
`$.mockclientdata` <- function(x, name) {
|
||||
if (name == "allowDataUriScheme") { return(TRUE) }
|
||||
if (name == "pixelratio") { return(1) }
|
||||
if (name == "url_protocol") { return("http:") }
|
||||
if (name == "url_hostname") { return("mocksession") }
|
||||
@@ -156,6 +155,7 @@ makeExtraMethods <- function() {
|
||||
"sendInsertTab",
|
||||
"sendInsertUI",
|
||||
"sendModal",
|
||||
"setCurrentTheme",
|
||||
"sendNotification",
|
||||
"sendProgress",
|
||||
"sendRemoveTab",
|
||||
@@ -167,12 +167,10 @@ makeExtraMethods <- function() {
|
||||
), makeErrors(
|
||||
`@uploadEnd` = "for internal use only",
|
||||
`@uploadInit` = "for internal use only",
|
||||
`@uploadieFinish` = "for internal use only",
|
||||
createBookmarkObservers = "for internal use only",
|
||||
dispatch = "for internal use only",
|
||||
handleRequest = "for internal use only",
|
||||
requestFlush = "for internal use only",
|
||||
saveFileUrl = "for internal use only",
|
||||
startTiming = "for internal use only",
|
||||
wsClosed = "for internal use only"
|
||||
))
|
||||
@@ -249,6 +247,8 @@ MockShinySession <- R6Class(
|
||||
#' @field user The username of an authenticated user. Always `NULL` for a
|
||||
#' `MockShinySession`.
|
||||
user = NULL,
|
||||
#' @field options A list containing session-level shinyOptions.
|
||||
options = NULL,
|
||||
|
||||
#' @description Create a new MockShinySession.
|
||||
initialize = function() {
|
||||
@@ -273,6 +273,10 @@ MockShinySession <- R6Class(
|
||||
self$input <- .createReactiveValues(private$.input, readonly = TRUE)
|
||||
|
||||
self$token <- createUniqueId(16)
|
||||
|
||||
# Copy app-level options
|
||||
self$options <- getCurrentAppState()$options
|
||||
|
||||
self$cache <- MemoryCache$new()
|
||||
self$appcache <- MemoryCache$new()
|
||||
|
||||
|
||||
21
R/modal.R
21
R/modal.R
@@ -29,10 +29,16 @@ removeModal <- function(session = getDefaultReactiveDomain()) {
|
||||
|
||||
#' Create a modal dialog UI
|
||||
#'
|
||||
#' This creates the UI for a modal dialog, using Bootstrap's modal class. Modals
|
||||
#' are typically used for showing important messages, or for presenting UI that
|
||||
#' requires input from the user, such as a username and password input.
|
||||
#' @description
|
||||
#' `modalDialog()` creates the UI for a modal dialog, using Bootstrap's modal
|
||||
#' class. Modals are typically used for showing important messages, or for
|
||||
#' presenting UI that requires input from the user, such as a user name and
|
||||
#' password input.
|
||||
#'
|
||||
#' `modalButton()` creates a button that will dismiss the dialog when clicked,
|
||||
#' typically used when customising the `footer`.
|
||||
#'
|
||||
#' @inheritParams actionButton
|
||||
#' @param ... UI elements for the body of the modal dialog box.
|
||||
#' @param title An optional title for the dialog.
|
||||
#' @param footer UI for footer. Use `NULL` for no footer.
|
||||
@@ -41,7 +47,7 @@ removeModal <- function(session = getDefaultReactiveDomain()) {
|
||||
#' @param easyClose If `TRUE`, the modal dialog can be dismissed by
|
||||
#' clicking outside the dialog box, or be pressing the Escape key. If
|
||||
#' `FALSE` (the default), the modal dialog can't be dismissed in those
|
||||
#' ways; instead it must be dismissed by clicking on the dismiss button, or
|
||||
#' ways; instead it must be dismissed by clicking on a `modalButton()`, or
|
||||
#' from a call to [removeModal()] on the server.
|
||||
#' @param fade If `FALSE`, the modal dialog will have no fade-in animation
|
||||
#' (it will simply appear rather than fade in to view).
|
||||
@@ -169,13 +175,8 @@ modalDialog <- function(..., title = NULL, footer = modalButton("Dismiss"),
|
||||
)
|
||||
}
|
||||
|
||||
#' Create a button for a modal dialog
|
||||
#'
|
||||
#' When clicked, a `modalButton` will dismiss the modal dialog.
|
||||
#'
|
||||
#' @inheritParams actionButton
|
||||
#' @seealso [modalDialog()] for examples.
|
||||
#' @export
|
||||
#' @rdname modalDialog
|
||||
modalButton <- function(label, icon = NULL) {
|
||||
tags$button(type = "button", class = "btn btn-default",
|
||||
`data-dismiss` = "modal", validateIcon(icon), label
|
||||
|
||||
@@ -204,7 +204,7 @@ Progress <- R6Class(
|
||||
#' the server function. The default is to automatically find the session by
|
||||
#' using the current reactive domain.
|
||||
#' @param expr The work to be done. This expression should contain calls to
|
||||
#' `setProgress`.
|
||||
#' [setProgress()] or [incProgress()].
|
||||
#' @param min The value that represents the starting point of the progress bar.
|
||||
#' Must be less tham `max`. Default is 0.
|
||||
#' @param max The value that represents the end of the progress bar. Must be
|
||||
@@ -227,6 +227,7 @@ Progress <- R6Class(
|
||||
#' @param value Single-element numeric vector; the value at which to set the
|
||||
#' progress bar, relative to `min` and `max`.
|
||||
#'
|
||||
#' @return The result of `expr`.
|
||||
#' @examples
|
||||
#' ## Only run examples in interactive R sessions
|
||||
#' if (interactive()) {
|
||||
|
||||
@@ -231,6 +231,12 @@ reactiveVal <- function(value = NULL, label = NULL) {
|
||||
#' @rdname freezeReactiveValue
|
||||
#' @export
|
||||
freezeReactiveVal <- function(x) {
|
||||
if (getOption("shiny.deprecation.messages", TRUE) && getOption("shiny.deprecation.messages.freeze", TRUE)) {
|
||||
rlang::warn(
|
||||
"freezeReactiveVal() is soft-deprecated, and may be removed in a future version of Shiny. (See https://github.com/rstudio/shiny/issues/3063)",
|
||||
.frequency = "once", .frequency_id = "freezeReactiveVal")
|
||||
}
|
||||
|
||||
domain <- getDefaultReactiveDomain()
|
||||
if (is.null(domain)) {
|
||||
stop("freezeReactiveVal() must be called when a default reactive domain is active.")
|
||||
@@ -357,7 +363,7 @@ ReactiveValues <- R6Class(
|
||||
keyValue
|
||||
},
|
||||
|
||||
set = function(key, value) {
|
||||
set = function(key, value, force = FALSE) {
|
||||
# if key exists
|
||||
# if it is the same value, return
|
||||
#
|
||||
@@ -389,10 +395,8 @@ ReactiveValues <- R6Class(
|
||||
|
||||
key_exists <- .values$containsKey(key)
|
||||
|
||||
if (key_exists) {
|
||||
if (.dedupe && identical(.values$get(key), value)) {
|
||||
return(invisible())
|
||||
}
|
||||
if (key_exists && !isTRUE(force) && .dedupe && identical(.values$get(key), value)) {
|
||||
return(invisible())
|
||||
}
|
||||
|
||||
# set the value for better logging
|
||||
@@ -469,10 +473,15 @@ ReactiveValues <- R6Class(
|
||||
|
||||
# Mark a value as frozen If accessed while frozen, a shiny.silent.error will
|
||||
# be thrown.
|
||||
freeze = function(key) {
|
||||
freeze = function(key, invalidate = FALSE) {
|
||||
domain <- getDefaultReactiveDomain()
|
||||
rLog$freezeReactiveKey(.reactId, key, domain)
|
||||
setMeta(key, "frozen", TRUE)
|
||||
|
||||
if (invalidate) {
|
||||
# Force an invalidation
|
||||
self$set(key, NULL, force = TRUE)
|
||||
}
|
||||
},
|
||||
|
||||
thaw = function(key) {
|
||||
@@ -727,7 +736,10 @@ str.reactivevalues <- function(object, indent.str = " ", ...) {
|
||||
#' thing that happens if `req(FALSE)` is called. The value is thawed
|
||||
#' (un-frozen; accessing it will no longer raise an exception) when the current
|
||||
#' reactive domain is flushed. In a Shiny application, this occurs after all of
|
||||
#' the observers are executed.
|
||||
#' the observers are executed. **NOTE:** We are considering deprecating
|
||||
#' `freezeReactiveVal`, and `freezeReactiveValue` except when `x` is `input`.
|
||||
#' If this affects your app, please let us know by leaving a comment on
|
||||
#' [this GitHub issue](https://github.com/rstudio/shiny/issues/3063).
|
||||
#'
|
||||
#' @param x For `freezeReactiveValue`, a [reactiveValues()]
|
||||
#' object (like `input`); for `freezeReactiveVal`, a
|
||||
@@ -1377,35 +1389,34 @@ observe <- function(x, env=parent.frame(), quoted=FALSE, label=NULL,
|
||||
#' already exist; if so, its value will be used as the initial value of the
|
||||
#' reactive variable (or `NULL` if the variable did not exist).
|
||||
#'
|
||||
#' @param symbol A character string indicating the name of the variable that
|
||||
#' should be made reactive
|
||||
#' @param env The environment that will contain the reactive variable
|
||||
#'
|
||||
#' @param symbol Name of variable to make reactive, as a string.
|
||||
#' @param env Environment in which to create binding. Expert use only.
|
||||
#' @return None.
|
||||
#'
|
||||
#' @keywords internal
|
||||
#' @examples
|
||||
#' \dontrun{
|
||||
#' reactiveConsole(TRUE)
|
||||
#'
|
||||
#' a <- 10
|
||||
#' makeReactiveBinding("a")
|
||||
#'
|
||||
#' b <- reactive(a * -1)
|
||||
#' observe(print(b()))
|
||||
#'
|
||||
#' a <- 20
|
||||
#' }
|
||||
#' a <- 30
|
||||
#'
|
||||
#' reactiveConsole(FALSE)
|
||||
#' @export
|
||||
makeReactiveBinding <- function(symbol, env = parent.frame()) {
|
||||
if (exists(symbol, envir = env, inherits = FALSE)) {
|
||||
initialValue <- env[[symbol]]
|
||||
rm(list = symbol, envir = env, inherits = FALSE)
|
||||
}
|
||||
else
|
||||
} else {
|
||||
initialValue <- NULL
|
||||
values <- reactiveValues(value = initialValue)
|
||||
makeActiveBinding(symbol, env=env, fun=function(v) {
|
||||
if (missing(v))
|
||||
values$value
|
||||
else
|
||||
values$value <- v
|
||||
})
|
||||
}
|
||||
|
||||
val <- reactiveVal(initialValue, label = symbol)
|
||||
makeActiveBinding(symbol, val, env = env)
|
||||
|
||||
invisible()
|
||||
}
|
||||
@@ -1441,6 +1452,29 @@ setAutoflush <- local({
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
#' Activate reactivity in the console
|
||||
#'
|
||||
#' This is an experimental feature that allows you to enable reactivity
|
||||
#' at the console, for the purposes of experimentation and learning.
|
||||
#'
|
||||
#' @keywords internal
|
||||
#' @param enabled Turn console reactivity on or off?
|
||||
#' @export
|
||||
#' @examples
|
||||
#' reactiveConsole(TRUE)
|
||||
#' x <- reactiveVal(10)
|
||||
#' y <- observe({
|
||||
#' message("The value of x is ", x())
|
||||
#' })
|
||||
#' x(20)
|
||||
#' x(30)
|
||||
#' reactiveConsole(FALSE)
|
||||
reactiveConsole <- function(enabled) {
|
||||
options(shiny.suppressMissingContextError = enabled)
|
||||
setAutoflush(enabled)
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
#' Timer
|
||||
|
||||
@@ -150,6 +150,8 @@
|
||||
#' `"app"` (the default), `"session"`, or a cache object like
|
||||
#' a [diskCache()]. See the Cache Scoping section for more
|
||||
#' information.
|
||||
#' @param width,height not used. They are specified via the argument
|
||||
#' `sizePolicy`.
|
||||
#'
|
||||
#' @seealso See [renderPlot()] for the regular, non-cached version of
|
||||
#' this function. For more about configuring caches, see
|
||||
@@ -295,7 +297,10 @@ renderCachedPlot <- function(expr,
|
||||
res = 72,
|
||||
cache = "app",
|
||||
...,
|
||||
outputArgs = list()
|
||||
alt = "Plot object",
|
||||
outputArgs = list(),
|
||||
width = NULL,
|
||||
height = NULL
|
||||
) {
|
||||
|
||||
# This ..stacktraceon is matched by a ..stacktraceoff.. when plotFunc
|
||||
@@ -307,6 +312,11 @@ renderCachedPlot <- function(expr,
|
||||
|
||||
args <- list(...)
|
||||
|
||||
if (!is.null(width) || !is.null(height)) {
|
||||
warning("Unused argument(s) 'width' and/or 'height'. ",
|
||||
"'sizePolicy' is used instead.")
|
||||
}
|
||||
|
||||
cacheKeyExpr <- substitute(cacheKeyExpr)
|
||||
# The real cache key we'll use also includes width, height, res, pixelratio.
|
||||
# This is just the part supplied by the user.
|
||||
@@ -341,6 +351,14 @@ renderCachedPlot <- function(expr,
|
||||
# values get filled by an observer below.
|
||||
fitDims <- reactiveValues(width = NULL, height = NULL)
|
||||
|
||||
# Make sure alt param to be reactive function
|
||||
if (is.reactive(alt))
|
||||
altWrapper <- alt
|
||||
else if (is.function(alt))
|
||||
altWrapper <- reactive({ alt() })
|
||||
else
|
||||
altWrapper <- function() { alt }
|
||||
|
||||
resizeObserver <- NULL
|
||||
ensureResizeObserver <- function() {
|
||||
if (!is.null(resizeObserver))
|
||||
@@ -387,6 +405,8 @@ renderCachedPlot <- function(expr,
|
||||
isolate({
|
||||
width <- fitDims$width
|
||||
height <- fitDims$height
|
||||
# Make sure alt text to be reactive function
|
||||
alt <- altWrapper()
|
||||
})
|
||||
|
||||
pixelratio <- session$clientData$pixelratio %OR% 1
|
||||
@@ -398,6 +418,7 @@ renderCachedPlot <- function(expr,
|
||||
func = isolatedFunc,
|
||||
width = width,
|
||||
height = height,
|
||||
alt = alt,
|
||||
pixelratio = pixelratio,
|
||||
res = res
|
||||
),
|
||||
@@ -434,6 +455,7 @@ renderCachedPlot <- function(expr,
|
||||
function(userCacheKeyResult) {
|
||||
width <- fitDims$width
|
||||
height <- fitDims$height
|
||||
alt <- altWrapper()
|
||||
pixelratio <- session$clientData$pixelratio %OR% 1
|
||||
|
||||
key <- digest::digest(list(outputName, userCacheKeyResult, width, height, res, pixelratio), "xxhash64")
|
||||
@@ -449,6 +471,7 @@ renderCachedPlot <- function(expr,
|
||||
plotObj = plotObj,
|
||||
width = width,
|
||||
height = height,
|
||||
alt = alt,
|
||||
pixelratio = pixelratio
|
||||
))
|
||||
}
|
||||
@@ -471,6 +494,7 @@ renderCachedPlot <- function(expr,
|
||||
plotObj = drawReactiveResult,
|
||||
width = width,
|
||||
height = height,
|
||||
alt = alt,
|
||||
pixelratio = pixelratio
|
||||
)
|
||||
}
|
||||
@@ -480,6 +504,7 @@ renderCachedPlot <- function(expr,
|
||||
hybrid_chain(possiblyAsyncResult, function(result) {
|
||||
width <- result$width
|
||||
height <- result$height
|
||||
alt <- result$alt
|
||||
pixelratio <- result$pixelratio
|
||||
|
||||
# Three possibilities when we get here:
|
||||
@@ -500,6 +525,7 @@ renderCachedPlot <- function(expr,
|
||||
result$plotObj,
|
||||
width,
|
||||
height,
|
||||
alt,
|
||||
pixelratio,
|
||||
res
|
||||
),
|
||||
|
||||
@@ -36,6 +36,12 @@
|
||||
#' @param res Resolution of resulting plot, in pixels per inch. This value is
|
||||
#' passed to [grDevices::png()]. Note that this affects the resolution of PNG
|
||||
#' rendering in R; it won't change the actual ppi of the browser.
|
||||
#' @param alt Alternate text for the HTML `<img>` tag
|
||||
#' if it cannot be displayed or viewed (i.e., the user uses a screen reader).
|
||||
#' In addition to a character string, the value may be a reactive expression
|
||||
#' (or a function referencing reactive values) that returns a character string.
|
||||
#' NULL or "" is not recommended because those should be limited to decorative images
|
||||
#' (the default is "Plot object").
|
||||
#' @param ... Arguments to be passed through to [grDevices::png()].
|
||||
#' These can be used to set the width, height, background color, etc.
|
||||
#' @param env The environment in which to evaluate `expr`.
|
||||
@@ -51,9 +57,10 @@
|
||||
#' call to [plotOutput()] when `renderPlot` is used in an
|
||||
#' interactive R Markdown document.
|
||||
#' @export
|
||||
renderPlot <- function(expr, width='auto', height='auto', res=72, ...,
|
||||
env=parent.frame(), quoted=FALSE,
|
||||
execOnResize=FALSE, outputArgs=list()
|
||||
renderPlot <- function(expr, width = 'auto', height = 'auto', res = 72, ...,
|
||||
alt = "Plot object",
|
||||
env = parent.frame(), quoted = FALSE,
|
||||
execOnResize = FALSE, outputArgs = list()
|
||||
) {
|
||||
# This ..stacktraceon is matched by a ..stacktraceoff.. when plotFunc
|
||||
# is called
|
||||
@@ -75,6 +82,13 @@ renderPlot <- function(expr, width='auto', height='auto', res=72, ...,
|
||||
else
|
||||
heightWrapper <- function() { height }
|
||||
|
||||
if (is.reactive(alt))
|
||||
altWrapper <- alt
|
||||
else if (is.function(alt))
|
||||
altWrapper <- reactive({ alt() })
|
||||
else
|
||||
altWrapper <- function() { alt }
|
||||
|
||||
getDims <- function() {
|
||||
width <- widthWrapper()
|
||||
height <- heightWrapper()
|
||||
@@ -112,6 +126,7 @@ renderPlot <- function(expr, width='auto', height='auto', res=72, ...,
|
||||
func = func,
|
||||
width = dims$width,
|
||||
height = dims$height,
|
||||
alt = altWrapper(),
|
||||
pixelratio = pixelratio,
|
||||
res = res
|
||||
), args))
|
||||
@@ -140,7 +155,7 @@ renderPlot <- function(expr, width='auto', height='auto', res=72, ...,
|
||||
dims <- getDims()
|
||||
pixelratio <- session$clientData$pixelratio %OR% 1
|
||||
result <- do.call("resizeSavedPlot", c(
|
||||
list(name, shinysession, result, dims$width, dims$height, pixelratio, res),
|
||||
list(name, shinysession, result, dims$width, dims$height, altWrapper(), pixelratio, res),
|
||||
args
|
||||
))
|
||||
|
||||
@@ -159,7 +174,7 @@ renderPlot <- function(expr, width='auto', height='auto', res=72, ...,
|
||||
markRenderFunction(outputFunc, renderFunc, outputArgs = outputArgs)
|
||||
}
|
||||
|
||||
resizeSavedPlot <- function(name, session, result, width, height, pixelratio, res, ...) {
|
||||
resizeSavedPlot <- function(name, session, result, width, height, alt, pixelratio, res, ...) {
|
||||
if (result$img$width == width && result$img$height == height &&
|
||||
result$pixelratio == pixelratio && result$res == res) {
|
||||
return(result)
|
||||
@@ -181,6 +196,7 @@ resizeSavedPlot <- function(name, session, result, width, height, pixelratio, re
|
||||
src = session$fileUrl(name, outfile, contentType = "image/png"),
|
||||
width = width,
|
||||
height = height,
|
||||
alt = alt,
|
||||
coordmap = coordmap,
|
||||
error = attr(coordmap, "error", exact = TRUE)
|
||||
)
|
||||
@@ -188,7 +204,7 @@ resizeSavedPlot <- function(name, session, result, width, height, pixelratio, re
|
||||
result
|
||||
}
|
||||
|
||||
drawPlot <- function(name, session, func, width, height, pixelratio, res, ...) {
|
||||
drawPlot <- function(name, session, func, width, height, alt, pixelratio, res, ...) {
|
||||
# 1. Start PNG
|
||||
# 2. Enable displaylist recording
|
||||
# 3. Call user-defined func
|
||||
@@ -272,6 +288,7 @@ drawPlot <- function(name, session, func, width, height, pixelratio, res, ...) {
|
||||
src = session$fileUrl(name, outfile, contentType='image/png'),
|
||||
width = width,
|
||||
height = height,
|
||||
alt = alt,
|
||||
coordmap = result$coordmap,
|
||||
# Get coordmap error message if present
|
||||
error = attr(result$coordmap, "error", exact = TRUE)
|
||||
|
||||
564
R/runapp.R
Normal file
564
R/runapp.R
Normal file
@@ -0,0 +1,564 @@
|
||||
#' Run Shiny Application
|
||||
#'
|
||||
#' Runs a Shiny application. This function normally does not return; interrupt R
|
||||
#' to stop the application (usually by pressing Ctrl+C or Esc).
|
||||
#'
|
||||
#' The host parameter was introduced in Shiny 0.9.0. Its default value of
|
||||
#' `"127.0.0.1"` means that, contrary to previous versions of Shiny, only
|
||||
#' the current machine can access locally hosted Shiny apps. To allow other
|
||||
#' clients to connect, use the value `"0.0.0.0"` instead (which was the
|
||||
#' value that was hard-coded into Shiny in 0.8.0 and earlier).
|
||||
#'
|
||||
#' @param appDir The application to run. Should be one of the following:
|
||||
#' \itemize{
|
||||
#' \item A directory containing `server.R`, plus, either `ui.R` or
|
||||
#' a `www` directory that contains the file `index.html`.
|
||||
#' \item A directory containing `app.R`.
|
||||
#' \item An `.R` file containing a Shiny application, ending with an
|
||||
#' expression that produces a Shiny app object.
|
||||
#' \item A list with `ui` and `server` components.
|
||||
#' \item A Shiny app object created by [shinyApp()].
|
||||
#' }
|
||||
#' @param port The TCP port that the application should listen on. If the
|
||||
#' `port` is not specified, and the `shiny.port` option is set (with
|
||||
#' `options(shiny.port = XX)`), then that port will be used. Otherwise,
|
||||
#' use a random port.
|
||||
#' @param launch.browser If true, the system's default web browser will be
|
||||
#' launched automatically after the app is started. Defaults to true in
|
||||
#' interactive sessions only. This value of this parameter can also be a
|
||||
#' function to call with the application's URL.
|
||||
#' @param host The IPv4 address that the application should listen on. Defaults
|
||||
#' to the `shiny.host` option, if set, or `"127.0.0.1"` if not. See
|
||||
#' Details.
|
||||
#' @param workerId Can generally be ignored. Exists to help some editions of
|
||||
#' Shiny Server Pro route requests to the correct process.
|
||||
#' @param quiet Should Shiny status messages be shown? Defaults to FALSE.
|
||||
#' @param display.mode The mode in which to display the application. If set to
|
||||
#' the value `"showcase"`, shows application code and metadata from a
|
||||
#' `DESCRIPTION` file in the application directory alongside the
|
||||
#' application. If set to `"normal"`, displays the application normally.
|
||||
#' Defaults to `"auto"`, which displays the application in the mode given
|
||||
#' in its `DESCRIPTION` file, if any.
|
||||
#' @param test.mode Should the application be launched in test mode? This is
|
||||
#' only used for recording or running automated tests. Defaults to the
|
||||
#' `shiny.testmode` option, or FALSE if the option is not set.
|
||||
#'
|
||||
#' @examples
|
||||
#' \dontrun{
|
||||
#' # Start app in the current working directory
|
||||
#' runApp()
|
||||
#'
|
||||
#' # Start app in a subdirectory called myapp
|
||||
#' runApp("myapp")
|
||||
#' }
|
||||
#'
|
||||
#' ## Only run this example in interactive R sessions
|
||||
#' if (interactive()) {
|
||||
#' options(device.ask.default = FALSE)
|
||||
#'
|
||||
#' # Apps can be run without a server.r and ui.r file
|
||||
#' runApp(list(
|
||||
#' ui = bootstrapPage(
|
||||
#' numericInput('n', 'Number of obs', 100),
|
||||
#' plotOutput('plot')
|
||||
#' ),
|
||||
#' server = function(input, output) {
|
||||
#' output$plot <- renderPlot({ hist(runif(input$n)) })
|
||||
#' }
|
||||
#' ))
|
||||
#'
|
||||
#'
|
||||
#' # Running a Shiny app object
|
||||
#' app <- shinyApp(
|
||||
#' ui = bootstrapPage(
|
||||
#' numericInput('n', 'Number of obs', 100),
|
||||
#' plotOutput('plot')
|
||||
#' ),
|
||||
#' server = function(input, output) {
|
||||
#' output$plot <- renderPlot({ hist(runif(input$n)) })
|
||||
#' }
|
||||
#' )
|
||||
#' runApp(app)
|
||||
#' }
|
||||
#' @export
|
||||
runApp <- function(appDir=getwd(),
|
||||
port=getOption('shiny.port'),
|
||||
launch.browser=getOption('shiny.launch.browser',
|
||||
interactive()),
|
||||
host=getOption('shiny.host', '127.0.0.1'),
|
||||
workerId="", quiet=FALSE,
|
||||
display.mode=c("auto", "normal", "showcase"),
|
||||
test.mode=getOption('shiny.testmode', FALSE)) {
|
||||
on.exit({
|
||||
handlerManager$clear()
|
||||
}, add = TRUE)
|
||||
|
||||
if (isRunning()) {
|
||||
stop("Can't call `runApp()` from within `runApp()`. If your ",
|
||||
"application code contains `runApp()`, please remove it.")
|
||||
}
|
||||
|
||||
# Make warnings print immediately
|
||||
# Set pool.scheduler to support pool package
|
||||
ops <- options(
|
||||
# Raise warn level to 1, but don't lower it
|
||||
warn = max(1, getOption("warn", default = 1)),
|
||||
pool.scheduler = scheduleTask
|
||||
)
|
||||
on.exit(options(ops), add = TRUE)
|
||||
|
||||
# ============================================================================
|
||||
# Global onStart/onStop callbacks
|
||||
# ============================================================================
|
||||
# Invoke user-defined onStop callbacks, before the application's internal
|
||||
# onStop callbacks.
|
||||
on.exit({
|
||||
.globals$onStopCallbacks$invoke()
|
||||
.globals$onStopCallbacks <- Callbacks$new()
|
||||
}, add = TRUE)
|
||||
|
||||
require(shiny)
|
||||
|
||||
# ============================================================================
|
||||
# Convert to Shiny app object
|
||||
# ============================================================================
|
||||
appParts <- as.shiny.appobj(appDir)
|
||||
|
||||
# ============================================================================
|
||||
# Initialize app state object
|
||||
# ============================================================================
|
||||
# This is so calls to getCurrentAppState() can be used to find (A) whether an
|
||||
# app is running and (B), get options and data associated with the app.
|
||||
initCurrentAppState(appParts)
|
||||
on.exit(clearCurrentAppState(), add = TRUE)
|
||||
# Any shinyOptions set after this point will apply to the current app only
|
||||
# (and will not persist after the app stops).
|
||||
|
||||
# ============================================================================
|
||||
# shinyOptions
|
||||
# ============================================================================
|
||||
# A unique identifier associated with this run of this application. It is
|
||||
# shared across sessions.
|
||||
shinyOptions(appToken = createUniqueId(8))
|
||||
|
||||
# Set up default cache for app.
|
||||
if (is.null(getShinyOption("cache"))) {
|
||||
shinyOptions(cache = MemoryCache$new())
|
||||
}
|
||||
|
||||
# Extract appOptions (which is a list) and store them as shinyOptions, for
|
||||
# this app. (This is the only place we have to store settings that are
|
||||
# accessible both the UI and server portion of the app.)
|
||||
applyCapturedAppOptions(appParts$appOptions)
|
||||
|
||||
# ============================================================================
|
||||
# runApp options set via shinyApp(options = list(...))
|
||||
# ============================================================================
|
||||
# The lines below set some of the app's running options, which
|
||||
# can be:
|
||||
# - left unspecified (in which case the arguments' default
|
||||
# values from `runApp` kick in);
|
||||
# - passed through `shinyApp`
|
||||
# - passed through `runApp` (this function)
|
||||
# - passed through both `shinyApp` and `runApp` (the latter
|
||||
# takes precedence)
|
||||
#
|
||||
# Matrix of possibilities:
|
||||
# | IN shinyApp | IN runApp | result | check |
|
||||
# |-------------|-----------|--------------|----------------------------------------------------------------------------------------------------------------------------------------|
|
||||
# | no | no | use defaults | exhaust all possibilities: if it's missing (runApp does not specify); THEN if it's not in shinyApp appParts$options; THEN use defaults |
|
||||
# | yes | no | use shinyApp | if it's missing (runApp does not specify); THEN if it's in shinyApp appParts$options; THEN use shinyApp |
|
||||
# | no | yes | use runApp | if it's not missing (runApp specifies), use those |
|
||||
# | yes | yes | use runApp | if it's not missing (runApp specifies), use those |
|
||||
#
|
||||
# I tried to make this as compact and intuitive as possible,
|
||||
# given that there are four distinct possibilities to check
|
||||
appOps <- appParts$options
|
||||
findVal <- function(arg, default) {
|
||||
if (arg %in% names(appOps)) appOps[[arg]] else default
|
||||
}
|
||||
|
||||
if (missing(port))
|
||||
port <- findVal("port", port)
|
||||
if (missing(launch.browser))
|
||||
launch.browser <- findVal("launch.browser", launch.browser)
|
||||
if (missing(host))
|
||||
host <- findVal("host", host)
|
||||
if (missing(quiet))
|
||||
quiet <- findVal("quiet", quiet)
|
||||
if (missing(display.mode))
|
||||
display.mode <- findVal("display.mode", display.mode)
|
||||
if (missing(test.mode))
|
||||
test.mode <- findVal("test.mode", test.mode)
|
||||
|
||||
if (is.null(host) || is.na(host)) host <- '0.0.0.0'
|
||||
|
||||
# ============================================================================
|
||||
# Hosted environment
|
||||
# ============================================================================
|
||||
workerId(workerId)
|
||||
|
||||
if (inShinyServer()) {
|
||||
# If SHINY_PORT is set, we're running under Shiny Server. Check the version
|
||||
# to make sure it is compatible. Older versions of Shiny Server don't set
|
||||
# SHINY_SERVER_VERSION, those will return "" which is considered less than
|
||||
# any valid version.
|
||||
ver <- Sys.getenv('SHINY_SERVER_VERSION')
|
||||
if (utils::compareVersion(ver, .shinyServerMinVersion) < 0) {
|
||||
warning('Shiny Server v', .shinyServerMinVersion,
|
||||
' or later is required; please upgrade!')
|
||||
}
|
||||
}
|
||||
|
||||
# ============================================================================
|
||||
# Shinytest
|
||||
# ============================================================================
|
||||
# Set the testmode shinyoption so that this can be read by both the
|
||||
# ShinySession and the UI code (which executes separately from the
|
||||
# ShinySession code).
|
||||
shinyOptions(testmode = test.mode)
|
||||
if (test.mode) {
|
||||
message("Running application in test mode.")
|
||||
}
|
||||
|
||||
# ============================================================================
|
||||
# Showcase mode
|
||||
# ============================================================================
|
||||
# Showcase mode is disabled by default; it must be explicitly enabled in
|
||||
# either the DESCRIPTION file for directory-based apps, or via
|
||||
# the display.mode parameter. The latter takes precedence.
|
||||
setShowcaseDefault(0)
|
||||
|
||||
# If appDir specifies a path, and display mode is specified in the
|
||||
# DESCRIPTION file at that path, apply it here.
|
||||
if (is.character(appDir)) {
|
||||
# if appDir specifies a .R file (single-file Shiny app), look for the
|
||||
# DESCRIPTION in the parent directory
|
||||
desc <- file.path.ci(
|
||||
if (tolower(tools::file_ext(appDir)) == "r")
|
||||
dirname(appDir)
|
||||
else
|
||||
appDir, "DESCRIPTION")
|
||||
if (file.exists(desc)) {
|
||||
con <- file(desc, encoding = checkEncoding(desc))
|
||||
on.exit(close(con), add = TRUE)
|
||||
settings <- read.dcf(con)
|
||||
if ("DisplayMode" %in% colnames(settings)) {
|
||||
mode <- settings[1, "DisplayMode"]
|
||||
if (mode == "Showcase") {
|
||||
setShowcaseDefault(1)
|
||||
if ("IncludeWWW" %in% colnames(settings)) {
|
||||
.globals$IncludeWWW <- as.logical(settings[1, "IncludeWWW"])
|
||||
if (is.na(.globals$IncludeWWW)) {
|
||||
stop("In your Description file, `IncludeWWW` ",
|
||||
"must be set to `True` (default) or `False`")
|
||||
}
|
||||
} else {
|
||||
.globals$IncludeWWW <- TRUE
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
## default is to show the .js, .css and .html files in the www directory
|
||||
## (if not in showcase mode, this variable will simply be ignored)
|
||||
if (is.null(.globals$IncludeWWW) || is.na(.globals$IncludeWWW)) {
|
||||
.globals$IncludeWWW <- TRUE
|
||||
}
|
||||
|
||||
# If display mode is specified as an argument, apply it (overriding the
|
||||
# value specified in DESCRIPTION, if any).
|
||||
display.mode <- match.arg(display.mode)
|
||||
if (display.mode == "normal") {
|
||||
setShowcaseDefault(0)
|
||||
}
|
||||
else if (display.mode == "showcase") {
|
||||
setShowcaseDefault(1)
|
||||
}
|
||||
|
||||
# ============================================================================
|
||||
# Server port
|
||||
# ============================================================================
|
||||
# determine port if we need to
|
||||
if (is.null(port)) {
|
||||
|
||||
# Try up to 20 random ports. If we don't succeed just plow ahead
|
||||
# with the final value we tried, and let the "real" startServer
|
||||
# somewhere down the line fail and throw the error to the user.
|
||||
#
|
||||
# If we (think we) succeed, save the value as .globals$lastPort,
|
||||
# and try that first next time the user wants a random port.
|
||||
|
||||
for (i in 1:20) {
|
||||
if (!is.null(.globals$lastPort)) {
|
||||
port <- .globals$lastPort
|
||||
.globals$lastPort <- NULL
|
||||
}
|
||||
else {
|
||||
# Try up to 20 random ports
|
||||
while (TRUE) {
|
||||
port <- p_randomInt(3000, 8000)
|
||||
# Reject ports in this range that are considered unsafe by Chrome
|
||||
# http://superuser.com/questions/188058/which-ports-are-considered-unsafe-on-chrome
|
||||
# https://github.com/rstudio/shiny/issues/1784
|
||||
if (!port %in% c(3659, 4045, 6000, 6665:6669, 6697)) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Test port to see if we can use it
|
||||
tmp <- try(startServer(host, port, list()), silent=TRUE)
|
||||
if (!inherits(tmp, 'try-error')) {
|
||||
stopServer(tmp)
|
||||
.globals$lastPort <- port
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ============================================================================
|
||||
# onStart/onStop callbacks
|
||||
# ============================================================================
|
||||
# Set up the onStop before we call onStart, so that it gets called even if an
|
||||
# error happens in onStart.
|
||||
if (!is.null(appParts$onStop))
|
||||
on.exit(appParts$onStop(), add = TRUE)
|
||||
if (!is.null(appParts$onStart))
|
||||
appParts$onStart()
|
||||
|
||||
# ============================================================================
|
||||
# Start/stop httpuv app
|
||||
# ============================================================================
|
||||
server <- startApp(appParts, port, host, quiet)
|
||||
|
||||
# Make the httpuv server object accessible. Needed for calling
|
||||
# addResourcePath while app is running.
|
||||
shinyOptions(server = server)
|
||||
|
||||
on.exit({
|
||||
stopServer(server)
|
||||
}, add = TRUE)
|
||||
|
||||
# ============================================================================
|
||||
# Launch web browser
|
||||
# ============================================================================
|
||||
if (!is.character(port)) {
|
||||
browseHost <- host
|
||||
if (identical(host, "0.0.0.0")) {
|
||||
# http://0.0.0.0/ doesn't work on QtWebKit (i.e. RStudio viewer)
|
||||
browseHost <- "127.0.0.1"
|
||||
} else if (identical(host, "::")) {
|
||||
browseHost <- "::1"
|
||||
}
|
||||
|
||||
if (httpuv::ipFamily(browseHost) == 6L) {
|
||||
browseHost <- paste0("[", browseHost, "]")
|
||||
}
|
||||
|
||||
appUrl <- paste("http://", browseHost, ":", port, sep="")
|
||||
if (is.function(launch.browser))
|
||||
launch.browser(appUrl)
|
||||
else if (launch.browser)
|
||||
utils::browseURL(appUrl)
|
||||
} else {
|
||||
appUrl <- NULL
|
||||
}
|
||||
|
||||
# ============================================================================
|
||||
# Application hooks
|
||||
# ============================================================================
|
||||
callAppHook("onAppStart", appUrl)
|
||||
on.exit({
|
||||
callAppHook("onAppStop", appUrl)
|
||||
}, add = TRUE)
|
||||
|
||||
# ============================================================================
|
||||
# Run event loop via httpuv
|
||||
# ============================================================================
|
||||
.globals$reterror <- NULL
|
||||
.globals$retval <- NULL
|
||||
.globals$stopped <- FALSE
|
||||
# Top-level ..stacktraceoff..; matches with ..stacktraceon in observe(),
|
||||
# reactive(), Callbacks$invoke(), and others
|
||||
..stacktraceoff..(
|
||||
captureStackTraces({
|
||||
while (!.globals$stopped) {
|
||||
..stacktracefloor..(serviceApp())
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
if (isTRUE(.globals$reterror)) {
|
||||
stop(.globals$retval)
|
||||
}
|
||||
else if (.globals$retval$visible)
|
||||
.globals$retval$value
|
||||
else
|
||||
invisible(.globals$retval$value)
|
||||
}
|
||||
|
||||
#' Stop the currently running Shiny app
|
||||
#'
|
||||
#' Stops the currently running Shiny app, returning control to the caller of
|
||||
#' [runApp()].
|
||||
#'
|
||||
#' @param returnValue The value that should be returned from
|
||||
#' [runApp()].
|
||||
#' @export
|
||||
stopApp <- function(returnValue = invisible()) {
|
||||
# reterror will indicate whether retval is an error (i.e. it should be passed
|
||||
# to stop() when the serviceApp loop stops) or a regular value (in which case
|
||||
# it should simply be returned with the appropriate visibility).
|
||||
.globals$reterror <- FALSE
|
||||
..stacktraceoff..(
|
||||
tryCatch(
|
||||
{
|
||||
captureStackTraces(
|
||||
.globals$retval <- withVisible(..stacktraceon..(force(returnValue)))
|
||||
)
|
||||
},
|
||||
error = function(e) {
|
||||
.globals$retval <- e
|
||||
.globals$reterror <- TRUE
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
.globals$stopped <- TRUE
|
||||
httpuv::interrupt()
|
||||
}
|
||||
|
||||
#' Run Shiny Example Applications
|
||||
#'
|
||||
#' Launch Shiny example applications, and optionally, your system's web browser.
|
||||
#'
|
||||
#' @param example The name of the example to run, or `NA` (the default) to
|
||||
#' list the available examples.
|
||||
#' @param launch.browser If true, the system's default web browser will be
|
||||
#' launched automatically after the app is started. Defaults to true in
|
||||
#' interactive sessions only.
|
||||
#' @param host The IPv4 address that the application should listen on. Defaults
|
||||
#' to the `shiny.host` option, if set, or `"127.0.0.1"` if not.
|
||||
#' @param display.mode The mode in which to display the example. Defaults to
|
||||
#' `showcase`, but may be set to `normal` to see the example without
|
||||
#' code or commentary.
|
||||
#' @inheritParams runApp
|
||||
#'
|
||||
#' @examples
|
||||
#' ## Only run this example in interactive R sessions
|
||||
#' if (interactive()) {
|
||||
#' # List all available examples
|
||||
#' runExample()
|
||||
#'
|
||||
#' # Run one of the examples
|
||||
#' runExample("01_hello")
|
||||
#'
|
||||
#' # Print the directory containing the code for all examples
|
||||
#' system.file("examples", package="shiny")
|
||||
#' }
|
||||
#' @export
|
||||
runExample <- function(example=NA,
|
||||
port=getOption("shiny.port"),
|
||||
launch.browser=getOption('shiny.launch.browser',
|
||||
interactive()),
|
||||
host=getOption('shiny.host', '127.0.0.1'),
|
||||
display.mode=c("auto", "normal", "showcase")) {
|
||||
examplesDir <- system.file('examples', package='shiny')
|
||||
dir <- resolve(examplesDir, example)
|
||||
if (is.null(dir)) {
|
||||
if (is.na(example)) {
|
||||
errFun <- message
|
||||
errMsg <- ''
|
||||
}
|
||||
else {
|
||||
errFun <- stop
|
||||
errMsg <- paste('Example', example, 'does not exist. ')
|
||||
}
|
||||
|
||||
errFun(errMsg,
|
||||
'Valid examples are "',
|
||||
paste(list.files(examplesDir), collapse='", "'),
|
||||
'"')
|
||||
}
|
||||
else {
|
||||
runApp(dir, port = port, host = host, launch.browser = launch.browser,
|
||||
display.mode = display.mode)
|
||||
}
|
||||
}
|
||||
|
||||
#' Run a gadget
|
||||
#'
|
||||
#' Similar to `runApp`, but handles `input$cancel` automatically, and
|
||||
#' if running in RStudio, defaults to viewing the app in the Viewer pane.
|
||||
#'
|
||||
#' @param app Either a Shiny app object as created by
|
||||
#' [`shinyApp()`][shiny] et al, or, a UI object.
|
||||
#' @param server Ignored if `app` is a Shiny app object; otherwise, passed
|
||||
#' along to `shinyApp` (i.e. `shinyApp(ui = app, server = server)`).
|
||||
#' @param port See [`runApp()`][shiny].
|
||||
#' @param viewer Specify where the gadget should be displayed--viewer pane,
|
||||
#' dialog window, or external browser--by passing in a call to one of the
|
||||
#' [viewer()] functions.
|
||||
#' @param stopOnCancel If `TRUE` (the default), then an `observeEvent`
|
||||
#' is automatically created that handles `input$cancel` by calling
|
||||
#' `stopApp()` with an error. Pass `FALSE` if you want to handle
|
||||
#' `input$cancel` yourself.
|
||||
#' @return The value returned by the gadget.
|
||||
#'
|
||||
#' @examples
|
||||
#' \dontrun{
|
||||
#' library(shiny)
|
||||
#'
|
||||
#' ui <- fillPage(...)
|
||||
#'
|
||||
#' server <- function(input, output, session) {
|
||||
#' ...
|
||||
#' }
|
||||
#'
|
||||
#' # Either pass ui/server as separate arguments...
|
||||
#' runGadget(ui, server)
|
||||
#'
|
||||
#' # ...or as a single app object
|
||||
#' runGadget(shinyApp(ui, server))
|
||||
#' }
|
||||
#' @export
|
||||
runGadget <- function(app, server = NULL, port = getOption("shiny.port"),
|
||||
viewer = paneViewer(), stopOnCancel = TRUE) {
|
||||
|
||||
if (!is.shiny.appobj(app)) {
|
||||
app <- shinyApp(app, server)
|
||||
}
|
||||
|
||||
if (isTRUE(stopOnCancel)) {
|
||||
app <- decorateServerFunc(app, function(input, output, session) {
|
||||
observeEvent(input$cancel, {
|
||||
stopApp(stop("User cancel", call. = FALSE))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
if (is.null(viewer)) {
|
||||
viewer <- utils::browseURL
|
||||
}
|
||||
|
||||
shiny::runApp(app, port = port, launch.browser = viewer)
|
||||
}
|
||||
|
||||
# Add custom functionality to a Shiny app object's server func
|
||||
decorateServerFunc <- function(appobj, serverFunc) {
|
||||
origServerFuncSource <- appobj$serverFuncSource
|
||||
appobj$serverFuncSource <- function() {
|
||||
origServerFunc <- origServerFuncSource()
|
||||
function(input, output, session) {
|
||||
serverFunc(input, output, session)
|
||||
|
||||
# The clientData and session arguments are optional; check if
|
||||
# each exists
|
||||
args <- argsForServerFunc(origServerFunc, session)
|
||||
do.call(origServerFunc, args)
|
||||
}
|
||||
}
|
||||
appobj
|
||||
}
|
||||
@@ -5,14 +5,15 @@ inputHandlers <- Map$new()
|
||||
#'
|
||||
#' Adds an input handler for data of this type. When called, Shiny will use the
|
||||
#' function provided to refine the data passed back from the client (after being
|
||||
#' deserialized by jsonlite) before making it available in the `input`
|
||||
#' variable of the `server.R` file.
|
||||
#' deserialized by jsonlite) before making it available in the `input` variable
|
||||
#' of the `server.R` file.
|
||||
#'
|
||||
#' This function will register the handler for the duration of the R process
|
||||
#' (unless Shiny is explicitly reloaded). For that reason, the `type` used
|
||||
#' should be very specific to this package to minimize the risk of colliding
|
||||
#' with another Shiny package which might use this data type name. We recommend
|
||||
#' the format of "packageName.widgetName".
|
||||
#' the format of "packageName.widgetName". It should be called from the
|
||||
#' package's `.onLoad()` function.
|
||||
#'
|
||||
#' Currently Shiny registers the following handlers: `shiny.matrix`,
|
||||
#' `shiny.number`, and `shiny.date`.
|
||||
@@ -20,23 +21,20 @@ inputHandlers <- Map$new()
|
||||
#' The `type` of a custom Shiny Input widget will be deduced using the
|
||||
#' `getType()` JavaScript function on the registered Shiny inputBinding.
|
||||
#' @param type The type for which the handler should be added --- should be a
|
||||
#' single-element character vector.
|
||||
#' single-element character vector.
|
||||
#' @param fun The handler function. This is the function that will be used to
|
||||
#' parse the data delivered from the client before it is available in the
|
||||
#' `input` variable. The function will be called with the following three
|
||||
#' parameters:
|
||||
#' \enumerate{
|
||||
#' \item{The value of this input as provided by the client, deserialized
|
||||
#' using jsonlite.}
|
||||
#' \item{The `shinysession` in which the input exists.}
|
||||
#' \item{The name of the input.}
|
||||
#' }
|
||||
#' @param force If `TRUE`, will overwrite any existing handler without
|
||||
#' warning. If `FALSE`, will throw an error if this class already has
|
||||
#' a handler defined.
|
||||
#' parameters: \enumerate{ \item{The value of this input as provided by the
|
||||
#' client, deserialized using jsonlite.} \item{The `shinysession` in which the
|
||||
#' input exists.} \item{The name of the input.} }
|
||||
#' @param force If `TRUE`, will overwrite any existing handler without warning.
|
||||
#' If `FALSE`, will throw an error if this class already has a handler
|
||||
#' defined.
|
||||
#' @examples
|
||||
#' \dontrun{
|
||||
#' # Register an input handler which rounds a input number to the nearest integer
|
||||
#' # In a package, this should be called from the .onLoad function.
|
||||
#' registerInputHandler("mypackage.validint", function(x, shinysession, name) {
|
||||
#' if (is.null(x)) return(NA)
|
||||
#' round(x)
|
||||
|
||||
169
R/server-resource-paths.R
Normal file
169
R/server-resource-paths.R
Normal file
@@ -0,0 +1,169 @@
|
||||
.globals$resourcePaths <- list()
|
||||
.globals$resources <- list()
|
||||
|
||||
#' Resource Publishing
|
||||
#'
|
||||
#' Add, remove, or list directory of static resources to Shiny's web server,
|
||||
#' with the given path prefix. Primarily intended for package authors to make
|
||||
#' supporting JavaScript/CSS files available to their components.
|
||||
#'
|
||||
#' Shiny provides two ways of serving static files (i.e., resources):
|
||||
#'
|
||||
#' 1. Static files under the `www/` directory are automatically made available
|
||||
#' under a request path that begins with `/`.
|
||||
#' 2. `addResourcePath()` makes static files in a `directoryPath` available
|
||||
#' under a request path that begins with `prefix`.
|
||||
#'
|
||||
#' The second approach is primarily intended for package authors to make
|
||||
#' supporting JavaScript/CSS files available to their components.
|
||||
#'
|
||||
#' Tools for managing static resources published by Shiny's web server:
|
||||
#' * `addResourcePath()` adds a directory of static resources.
|
||||
#' * `resourcePaths()` lists the currently active resource mappings.
|
||||
#' * `removeResourcePath()` removes a directory of static resources.
|
||||
#'
|
||||
#' @param prefix The URL prefix (without slashes). Valid characters are a-z,
|
||||
#' A-Z, 0-9, hyphen, period, and underscore. For example, a value of 'foo'
|
||||
#' means that any request paths that begin with '/foo' will be mapped to the
|
||||
#' given directory.
|
||||
#' @param directoryPath The directory that contains the static resources to be
|
||||
#' served.
|
||||
#'
|
||||
#' @rdname resourcePaths
|
||||
#' @seealso [singleton()]
|
||||
#'
|
||||
#' @examples
|
||||
#' addResourcePath('datasets', system.file('data', package='datasets'))
|
||||
#' resourcePaths()
|
||||
#' removeResourcePath('datasets')
|
||||
#' resourcePaths()
|
||||
#'
|
||||
#' # make sure all resources are removed
|
||||
#' lapply(names(resourcePaths()), removeResourcePath)
|
||||
#' @export
|
||||
addResourcePath <- function(prefix, directoryPath) {
|
||||
if (length(prefix) != 1) stop("prefix must be of length 1")
|
||||
if (grepl("^\\.+$", prefix)) stop("prefix can't be composed of dots only")
|
||||
if (!grepl('[a-z0-9\\-_.]+$', prefix, ignore.case = TRUE, perl = TRUE)) {
|
||||
stop("addResourcePath called with invalid prefix; please see documentation")
|
||||
}
|
||||
if (prefix %in% c('shared')) {
|
||||
stop("addResourcePath called with the reserved prefix '", prefix, "'; ",
|
||||
"please use a different prefix")
|
||||
}
|
||||
normalizedPath <- tryCatch(normalizePath(directoryPath, mustWork = TRUE),
|
||||
error = function(e) {
|
||||
stop("Couldn't normalize path in `addResourcePath`, with arguments: ",
|
||||
"`prefix` = '", prefix, "'; `directoryPath` = '" , directoryPath, "'")
|
||||
}
|
||||
)
|
||||
|
||||
# # Often times overwriting a resource path is "what you want",
|
||||
# # but sometimes it can lead to difficult to diagnose issues
|
||||
# # (e.g. an implict dependency might set a resource path that
|
||||
# # conflicts with what you, the app author, are trying to register)
|
||||
# # Note that previous versions of shiny used to warn about this case,
|
||||
# # but it was eventually removed since it caused confusion (#567).
|
||||
# # It seems a good compromise is to throw a more information message.
|
||||
# if (getOption("shiny.resourcePathChanges", FALSE) &&
|
||||
# prefix %in% names(.globals$resourcePaths)) {
|
||||
# existingPath <- .globals$resourcePaths[[prefix]]$path
|
||||
# if (normalizedPath != existingPath) {
|
||||
# message(
|
||||
# "The resource path '", prefix, "' used to point to ",
|
||||
# existingPath, ", but it now points to ", normalizedPath, ". ",
|
||||
# "If your app doesn't work as expected, you may want to ",
|
||||
# "choose a different prefix name."
|
||||
# )
|
||||
# }
|
||||
# }
|
||||
|
||||
# If a shiny app is currently running, dynamically register this path with
|
||||
# the corresponding httpuv server object.
|
||||
if (!is.null(getShinyOption("server")))
|
||||
{
|
||||
getShinyOption("server")$setStaticPath(.list = stats::setNames(normalizedPath, prefix))
|
||||
}
|
||||
|
||||
# .globals$resourcePaths and .globals$resources persist across runs of applications.
|
||||
.globals$resourcePaths[[prefix]] <- staticPath(normalizedPath)
|
||||
# This is necessary because resourcePaths is only for serving assets out of C++;
|
||||
# to support subapps, we also need assets to be served out of R, because those
|
||||
# URLs are rewritten by R code (i.e. routeHandler) before they can be matched to
|
||||
# a resource path.
|
||||
.globals$resources[[prefix]] <- list(
|
||||
directoryPath = normalizedPath,
|
||||
func = staticHandler(normalizedPath)
|
||||
)
|
||||
}
|
||||
|
||||
#' @rdname resourcePaths
|
||||
#' @export
|
||||
resourcePaths <- function() {
|
||||
urls <- names(.globals$resourcePaths)
|
||||
paths <- vapply(.globals$resourcePaths, function(x) x$path, character(1))
|
||||
stats::setNames(paths, urls)
|
||||
}
|
||||
|
||||
hasResourcePath <- function(prefix) {
|
||||
prefix %in% names(resourcePaths())
|
||||
}
|
||||
|
||||
#' @rdname resourcePaths
|
||||
#' @export
|
||||
removeResourcePath <- function(prefix) {
|
||||
if (length(prefix) > 1) stop("`prefix` must be of length 1.")
|
||||
if (!hasResourcePath(prefix)) {
|
||||
warning("Resource ", prefix, " not found.")
|
||||
return(invisible(FALSE))
|
||||
}
|
||||
.globals$resourcePaths[[prefix]] <- NULL
|
||||
.globals$resources[[prefix]] <- NULL
|
||||
invisible(TRUE)
|
||||
}
|
||||
|
||||
# This function handles any GET request with two or more path elements where the
|
||||
# first path element matches a prefix that was previously added using
|
||||
# addResourcePath().
|
||||
#
|
||||
# For example, if `addResourcePath("foo", "~/bar")` was called, then a GET
|
||||
# request for /foo/one/two.html would rewrite the PATH_INFO as /one/two.html and
|
||||
# send it to the resource path function for "foo". As of this writing, that
|
||||
# function will always be a staticHandler, which serves up a file if it exists
|
||||
# and NULL if it does not.
|
||||
#
|
||||
# Since Shiny 1.3.x, assets registered via addResourcePath should mostly be
|
||||
# served out of httpuv's native static file serving features. However, in the
|
||||
# specific case of subapps, the R code path must be used, because subapps insert
|
||||
# a giant random ID into the beginning of the URL that must be stripped off by
|
||||
# an R route handler (see addSubApp()).
|
||||
resourcePathHandler <- function(req) {
|
||||
if (!identical(req$REQUEST_METHOD, 'GET'))
|
||||
return(NULL)
|
||||
|
||||
# e.g. "/foo/one/two.html"
|
||||
path <- req$PATH_INFO
|
||||
|
||||
match <- regexpr('^/([^/]+)/', path, perl=TRUE)
|
||||
if (match == -1)
|
||||
return(NULL)
|
||||
len <- attr(match, 'capture.length')
|
||||
# e.g. "foo"
|
||||
prefix <- substr(path, 2, 2 + len - 1)
|
||||
|
||||
resInfo <- .globals$resources[[prefix]]
|
||||
if (is.null(resInfo))
|
||||
return(NULL)
|
||||
|
||||
# e.g. "/one/two.html"
|
||||
suffix <- substr(path, 2 + len, nchar(path))
|
||||
|
||||
# Create a new request that's a clone of the current request, but adjust
|
||||
# PATH_INFO and SCRIPT_NAME to reflect that we have already matched the first
|
||||
# path element (e.g. "/foo"). See routeHandler() for more info.
|
||||
subreq <- as.environment(as.list(req, all.names=TRUE))
|
||||
subreq$PATH_INFO <- suffix
|
||||
subreq$SCRIPT_NAME <- paste(subreq$SCRIPT_NAME, substr(path, 1, 2 + len), sep='')
|
||||
|
||||
return(resInfo$func(subreq))
|
||||
}
|
||||
755
R/server.R
755
R/server.R
@@ -22,180 +22,10 @@ registerClient <- function(client) {
|
||||
}
|
||||
|
||||
|
||||
.globals$resourcePaths <- list()
|
||||
.globals$resources <- list()
|
||||
|
||||
.globals$showcaseDefault <- 0
|
||||
|
||||
.globals$showcaseOverride <- FALSE
|
||||
|
||||
#' Resource Publishing
|
||||
#'
|
||||
#' Add, remove, or list directory of static resources to Shiny's web server,
|
||||
#' with the given path prefix. Primarily intended for package authors to make
|
||||
#' supporting JavaScript/CSS files available to their components.
|
||||
#'
|
||||
#' Shiny provides two ways of serving static files (i.e., resources):
|
||||
#'
|
||||
#' 1. Static files under the `www/` directory are automatically made available
|
||||
#' under a request path that begins with `/`.
|
||||
#' 2. `addResourcePath()` makes static files in a `directoryPath` available
|
||||
#' under a request path that begins with `prefix`.
|
||||
#'
|
||||
#' The second approach is primarily intended for package authors to make
|
||||
#' supporting JavaScript/CSS files available to their components.
|
||||
#'
|
||||
#' Tools for managing static resources published by Shiny's web server:
|
||||
#' * `addResourcePath()` adds a directory of static resources.
|
||||
#' * `resourcePaths()` lists the currently active resource mappings.
|
||||
#' * `removeResourcePath()` removes a directory of static resources.
|
||||
#'
|
||||
#' @param prefix The URL prefix (without slashes). Valid characters are a-z,
|
||||
#' A-Z, 0-9, hyphen, period, and underscore. For example, a value of 'foo'
|
||||
#' means that any request paths that begin with '/foo' will be mapped to the
|
||||
#' given directory.
|
||||
#' @param directoryPath The directory that contains the static resources to be
|
||||
#' served.
|
||||
#'
|
||||
#' @rdname resourcePaths
|
||||
#' @seealso [singleton()]
|
||||
#'
|
||||
#' @examples
|
||||
#' addResourcePath('datasets', system.file('data', package='datasets'))
|
||||
#' resourcePaths()
|
||||
#' removeResourcePath('datasets')
|
||||
#' resourcePaths()
|
||||
#'
|
||||
#' # make sure all resources are removed
|
||||
#' lapply(names(resourcePaths()), removeResourcePath)
|
||||
#' @export
|
||||
addResourcePath <- function(prefix, directoryPath) {
|
||||
if (length(prefix) != 1) stop("prefix must be of length 1")
|
||||
if (!grepl('^[a-z0-9\\-_][a-z0-9\\-_.]*$', prefix, ignore.case = TRUE, perl = TRUE)) {
|
||||
stop("addResourcePath called with invalid prefix; please see documentation")
|
||||
}
|
||||
if (prefix %in% c('shared')) {
|
||||
stop("addResourcePath called with the reserved prefix '", prefix, "'; ",
|
||||
"please use a different prefix")
|
||||
}
|
||||
normalizedPath <- tryCatch(normalizePath(directoryPath, mustWork = TRUE),
|
||||
error = function(e) {
|
||||
stop("Couldn't normalize path in `addResourcePath`, with arguments: ",
|
||||
"`prefix` = '", prefix, "'; `directoryPath` = '" , directoryPath, "'")
|
||||
}
|
||||
)
|
||||
|
||||
# # Often times overwriting a resource path is "what you want",
|
||||
# # but sometimes it can lead to difficult to diagnose issues
|
||||
# # (e.g. an implict dependency might set a resource path that
|
||||
# # conflicts with what you, the app author, are trying to register)
|
||||
# # Note that previous versions of shiny used to warn about this case,
|
||||
# # but it was eventually removed since it caused confusion (#567).
|
||||
# # It seems a good compromise is to throw a more information message.
|
||||
# if (getOption("shiny.resourcePathChanges", FALSE) &&
|
||||
# prefix %in% names(.globals$resourcePaths)) {
|
||||
# existingPath <- .globals$resourcePaths[[prefix]]$path
|
||||
# if (normalizedPath != existingPath) {
|
||||
# message(
|
||||
# "The resource path '", prefix, "' used to point to ",
|
||||
# existingPath, ", but it now points to ", normalizedPath, ". ",
|
||||
# "If your app doesn't work as expected, you may want to ",
|
||||
# "choose a different prefix name."
|
||||
# )
|
||||
# }
|
||||
# }
|
||||
|
||||
# If a shiny app is currently running, dynamically register this path with
|
||||
# the corresponding httpuv server object.
|
||||
if (!is.null(getShinyOption("server")))
|
||||
{
|
||||
getShinyOption("server")$setStaticPath(.list = stats::setNames(normalizedPath, prefix))
|
||||
}
|
||||
|
||||
# .globals$resourcePaths and .globals$resources persist across runs of applications.
|
||||
.globals$resourcePaths[[prefix]] <- staticPath(normalizedPath)
|
||||
# This is necessary because resourcePaths is only for serving assets out of C++;
|
||||
# to support subapps, we also need assets to be served out of R, because those
|
||||
# URLs are rewritten by R code (i.e. routeHandler) before they can be matched to
|
||||
# a resource path.
|
||||
.globals$resources[[prefix]] <- list(
|
||||
directoryPath = normalizedPath,
|
||||
func = staticHandler(normalizedPath)
|
||||
)
|
||||
}
|
||||
|
||||
#' @rdname resourcePaths
|
||||
#' @export
|
||||
resourcePaths <- function() {
|
||||
urls <- names(.globals$resourcePaths)
|
||||
paths <- vapply(.globals$resourcePaths, function(x) x$path, character(1))
|
||||
stats::setNames(paths, urls)
|
||||
}
|
||||
|
||||
hasResourcePath <- function(prefix) {
|
||||
prefix %in% names(resourcePaths())
|
||||
}
|
||||
|
||||
#' @rdname resourcePaths
|
||||
#' @export
|
||||
removeResourcePath <- function(prefix) {
|
||||
if (length(prefix) > 1) stop("`prefix` must be of length 1.")
|
||||
if (!hasResourcePath(prefix)) {
|
||||
warning("Resource ", prefix, " not found.")
|
||||
return(invisible(FALSE))
|
||||
}
|
||||
.globals$resourcePaths[[prefix]] <- NULL
|
||||
.globals$resources[[prefix]] <- NULL
|
||||
invisible(TRUE)
|
||||
}
|
||||
|
||||
|
||||
|
||||
# This function handles any GET request with two or more path elements where the
|
||||
# first path element matches a prefix that was previously added using
|
||||
# addResourcePath().
|
||||
#
|
||||
# For example, if `addResourcePath("foo", "~/bar")` was called, then a GET
|
||||
# request for /foo/one/two.html would rewrite the PATH_INFO as /one/two.html and
|
||||
# send it to the resource path function for "foo". As of this writing, that
|
||||
# function will always be a staticHandler, which serves up a file if it exists
|
||||
# and NULL if it does not.
|
||||
#
|
||||
# Since Shiny 1.3.x, assets registered via addResourcePath should mostly be
|
||||
# served out of httpuv's native static file serving features. However, in the
|
||||
# specific case of subapps, the R code path must be used, because subapps insert
|
||||
# a giant random ID into the beginning of the URL that must be stripped off by
|
||||
# an R route handler (see addSubApp()).
|
||||
resourcePathHandler <- function(req) {
|
||||
if (!identical(req$REQUEST_METHOD, 'GET'))
|
||||
return(NULL)
|
||||
|
||||
# e.g. "/foo/one/two.html"
|
||||
path <- req$PATH_INFO
|
||||
|
||||
match <- regexpr('^/([^/]+)/', path, perl=TRUE)
|
||||
if (match == -1)
|
||||
return(NULL)
|
||||
len <- attr(match, 'capture.length')
|
||||
# e.g. "foo"
|
||||
prefix <- substr(path, 2, 2 + len - 1)
|
||||
|
||||
resInfo <- .globals$resources[[prefix]]
|
||||
if (is.null(resInfo))
|
||||
return(NULL)
|
||||
|
||||
# e.g. "/one/two.html"
|
||||
suffix <- substr(path, 2 + len, nchar(path))
|
||||
|
||||
# Create a new request that's a clone of the current request, but adjust
|
||||
# PATH_INFO and SCRIPT_NAME to reflect that we have already matched the first
|
||||
# path element (e.g. "/foo"). See routeHandler() for more info.
|
||||
subreq <- as.environment(as.list(req, all.names=TRUE))
|
||||
subreq$PATH_INFO <- suffix
|
||||
subreq$SCRIPT_NAME <- paste(subreq$SCRIPT_NAME, substr(path, 1, 2 + len), sep='')
|
||||
|
||||
return(resInfo$func(subreq))
|
||||
}
|
||||
|
||||
#' Define Server Functionality
|
||||
#'
|
||||
@@ -644,9 +474,6 @@ 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
|
||||
|
||||
#' Check whether a Shiny application is running
|
||||
#'
|
||||
#' This function tests whether a Shiny application is currently running.
|
||||
@@ -655,589 +482,9 @@ serviceApp <- function() {
|
||||
#' `FALSE`.
|
||||
#' @export
|
||||
isRunning <- function() {
|
||||
.globals$running
|
||||
!is.null(getCurrentAppState())
|
||||
}
|
||||
|
||||
#' Run Shiny Application
|
||||
#'
|
||||
#' Runs a Shiny application. This function normally does not return; interrupt R
|
||||
#' to stop the application (usually by pressing Ctrl+C or Esc).
|
||||
#'
|
||||
#' The host parameter was introduced in Shiny 0.9.0. Its default value of
|
||||
#' `"127.0.0.1"` means that, contrary to previous versions of Shiny, only
|
||||
#' the current machine can access locally hosted Shiny apps. To allow other
|
||||
#' clients to connect, use the value `"0.0.0.0"` instead (which was the
|
||||
#' value that was hard-coded into Shiny in 0.8.0 and earlier).
|
||||
#'
|
||||
#' @param appDir The application to run. Should be one of the following:
|
||||
#' \itemize{
|
||||
#' \item A directory containing `server.R`, plus, either `ui.R` or
|
||||
#' a `www` directory that contains the file `index.html`.
|
||||
#' \item A directory containing `app.R`.
|
||||
#' \item An `.R` file containing a Shiny application, ending with an
|
||||
#' expression that produces a Shiny app object.
|
||||
#' \item A list with `ui` and `server` components.
|
||||
#' \item A Shiny app object created by [shinyApp()].
|
||||
#' }
|
||||
#' @param port The TCP port that the application should listen on. If the
|
||||
#' `port` is not specified, and the `shiny.port` option is set (with
|
||||
#' `options(shiny.port = XX)`), then that port will be used. Otherwise,
|
||||
#' use a random port.
|
||||
#' @param launch.browser If true, the system's default web browser will be
|
||||
#' launched automatically after the app is started. Defaults to true in
|
||||
#' interactive sessions only. This value of this parameter can also be a
|
||||
#' function to call with the application's URL.
|
||||
#' @param host The IPv4 address that the application should listen on. Defaults
|
||||
#' to the `shiny.host` option, if set, or `"127.0.0.1"` if not. See
|
||||
#' Details.
|
||||
#' @param workerId Can generally be ignored. Exists to help some editions of
|
||||
#' Shiny Server Pro route requests to the correct process.
|
||||
#' @param quiet Should Shiny status messages be shown? Defaults to FALSE.
|
||||
#' @param display.mode The mode in which to display the application. If set to
|
||||
#' the value `"showcase"`, shows application code and metadata from a
|
||||
#' `DESCRIPTION` file in the application directory alongside the
|
||||
#' application. If set to `"normal"`, displays the application normally.
|
||||
#' Defaults to `"auto"`, which displays the application in the mode given
|
||||
#' in its `DESCRIPTION` file, if any.
|
||||
#' @param test.mode Should the application be launched in test mode? This is
|
||||
#' only used for recording or running automated tests. Defaults to the
|
||||
#' `shiny.testmode` option, or FALSE if the option is not set.
|
||||
#'
|
||||
#' @examples
|
||||
#' \dontrun{
|
||||
#' # Start app in the current working directory
|
||||
#' runApp()
|
||||
#'
|
||||
#' # Start app in a subdirectory called myapp
|
||||
#' runApp("myapp")
|
||||
#' }
|
||||
#'
|
||||
#' ## Only run this example in interactive R sessions
|
||||
#' if (interactive()) {
|
||||
#' options(device.ask.default = FALSE)
|
||||
#'
|
||||
#' # Apps can be run without a server.r and ui.r file
|
||||
#' runApp(list(
|
||||
#' ui = bootstrapPage(
|
||||
#' numericInput('n', 'Number of obs', 100),
|
||||
#' plotOutput('plot')
|
||||
#' ),
|
||||
#' server = function(input, output) {
|
||||
#' output$plot <- renderPlot({ hist(runif(input$n)) })
|
||||
#' }
|
||||
#' ))
|
||||
#'
|
||||
#'
|
||||
#' # Running a Shiny app object
|
||||
#' app <- shinyApp(
|
||||
#' ui = bootstrapPage(
|
||||
#' numericInput('n', 'Number of obs', 100),
|
||||
#' plotOutput('plot')
|
||||
#' ),
|
||||
#' server = function(input, output) {
|
||||
#' output$plot <- renderPlot({ hist(runif(input$n)) })
|
||||
#' }
|
||||
#' )
|
||||
#' runApp(app)
|
||||
#' }
|
||||
#' @export
|
||||
runApp <- function(appDir=getwd(),
|
||||
port=getOption('shiny.port'),
|
||||
launch.browser=getOption('shiny.launch.browser',
|
||||
interactive()),
|
||||
host=getOption('shiny.host', '127.0.0.1'),
|
||||
workerId="", quiet=FALSE,
|
||||
display.mode=c("auto", "normal", "showcase"),
|
||||
test.mode=getOption('shiny.testmode', FALSE)) {
|
||||
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, for shinyOptions() and getShinyOption().
|
||||
oldOptionSet <- .globals$options
|
||||
on.exit({
|
||||
.globals$options <- oldOptionSet
|
||||
},add = TRUE)
|
||||
|
||||
# A unique identifier associated with this run of this application. It is
|
||||
# shared across sessions.
|
||||
shinyOptions(appToken = createUniqueId(8))
|
||||
|
||||
# Make warnings print immediately
|
||||
# Set pool.scheduler to support pool package
|
||||
ops <- options(
|
||||
# Raise warn level to 1, but don't lower it
|
||||
warn = max(1, getOption("warn", default = 1)),
|
||||
pool.scheduler = scheduleTask
|
||||
)
|
||||
on.exit(options(ops), add = TRUE)
|
||||
|
||||
# Set up default cache for app.
|
||||
if (is.null(getShinyOption("cache"))) {
|
||||
shinyOptions(cache = MemoryCache$new())
|
||||
}
|
||||
|
||||
# Invoke user-defined onStop callbacks, before the application's internal
|
||||
# onStop callbacks.
|
||||
on.exit({
|
||||
.globals$onStopCallbacks$invoke()
|
||||
.globals$onStopCallbacks <- Callbacks$new()
|
||||
}, add = TRUE)
|
||||
|
||||
require(shiny)
|
||||
|
||||
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()) {
|
||||
# If SHINY_PORT is set, we're running under Shiny Server. Check the version
|
||||
# to make sure it is compatible. Older versions of Shiny Server don't set
|
||||
# SHINY_SERVER_VERSION, those will return "" which is considered less than
|
||||
# any valid version.
|
||||
ver <- Sys.getenv('SHINY_SERVER_VERSION')
|
||||
if (utils::compareVersion(ver, .shinyServerMinVersion) < 0) {
|
||||
warning('Shiny Server v', .shinyServerMinVersion,
|
||||
' or later is required; please upgrade!')
|
||||
}
|
||||
}
|
||||
|
||||
# Showcase mode is disabled by default; it must be explicitly enabled in
|
||||
# either the DESCRIPTION file for directory-based apps, or via
|
||||
# the display.mode parameter. The latter takes precedence.
|
||||
setShowcaseDefault(0)
|
||||
|
||||
.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)) {
|
||||
# if appDir specifies a .R file (single-file Shiny app), look for the
|
||||
# DESCRIPTION in the parent directory
|
||||
desc <- file.path.ci(
|
||||
if (tolower(tools::file_ext(appDir)) == "r")
|
||||
dirname(appDir)
|
||||
else
|
||||
appDir, "DESCRIPTION")
|
||||
if (file.exists(desc)) {
|
||||
con <- file(desc, encoding = checkEncoding(desc))
|
||||
on.exit(close(con), add = TRUE)
|
||||
settings <- read.dcf(con)
|
||||
if ("DisplayMode" %in% colnames(settings)) {
|
||||
mode <- settings[1, "DisplayMode"]
|
||||
if (mode == "Showcase") {
|
||||
setShowcaseDefault(1)
|
||||
if ("IncludeWWW" %in% colnames(settings)) {
|
||||
.globals$IncludeWWW <- as.logical(settings[1, "IncludeWWW"])
|
||||
if (is.na(.globals$IncludeWWW)) {
|
||||
stop("In your Description file, `IncludeWWW` ",
|
||||
"must be set to `True` (default) or `False`")
|
||||
}
|
||||
} else {
|
||||
.globals$IncludeWWW <- TRUE
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
## default is to show the .js, .css and .html files in the www directory
|
||||
## (if not in showcase mode, this variable will simply be ignored)
|
||||
if (is.null(.globals$IncludeWWW) || is.na(.globals$IncludeWWW)) {
|
||||
.globals$IncludeWWW <- TRUE
|
||||
}
|
||||
|
||||
# If display mode is specified as an argument, apply it (overriding the
|
||||
# value specified in DESCRIPTION, if any).
|
||||
display.mode <- match.arg(display.mode)
|
||||
if (display.mode == "normal") {
|
||||
setShowcaseDefault(0)
|
||||
}
|
||||
else if (display.mode == "showcase") {
|
||||
setShowcaseDefault(1)
|
||||
}
|
||||
|
||||
# determine port if we need to
|
||||
if (is.null(port)) {
|
||||
|
||||
# Try up to 20 random ports. If we don't succeed just plow ahead
|
||||
# with the final value we tried, and let the "real" startServer
|
||||
# somewhere down the line fail and throw the error to the user.
|
||||
#
|
||||
# If we (think we) succeed, save the value as .globals$lastPort,
|
||||
# and try that first next time the user wants a random port.
|
||||
|
||||
for (i in 1:20) {
|
||||
if (!is.null(.globals$lastPort)) {
|
||||
port <- .globals$lastPort
|
||||
.globals$lastPort <- NULL
|
||||
}
|
||||
else {
|
||||
# Try up to 20 random ports
|
||||
while (TRUE) {
|
||||
port <- p_randomInt(3000, 8000)
|
||||
# Reject ports in this range that are considered unsafe by Chrome
|
||||
# http://superuser.com/questions/188058/which-ports-are-considered-unsafe-on-chrome
|
||||
# https://github.com/rstudio/shiny/issues/1784
|
||||
if (!port %in% c(3659, 4045, 6000, 6665:6669, 6697)) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Test port to see if we can use it
|
||||
tmp <- try(startServer(host, port, list()), silent=TRUE)
|
||||
if (!inherits(tmp, 'try-error')) {
|
||||
stopServer(tmp)
|
||||
.globals$lastPort <- port
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# 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.)
|
||||
unconsumeAppOptions(appParts$appOptions)
|
||||
|
||||
# Set up the onStop before we call onStart, so that it gets called even if an
|
||||
# error happens in onStart.
|
||||
if (!is.null(appParts$onStop))
|
||||
on.exit(appParts$onStop(), add = TRUE)
|
||||
if (!is.null(appParts$onStart))
|
||||
appParts$onStart()
|
||||
|
||||
server <- startApp(appParts, port, host, quiet)
|
||||
|
||||
# Make the httpuv server object accessible. Needed for calling
|
||||
# addResourcePath while app is running.
|
||||
shinyOptions(server = server)
|
||||
|
||||
on.exit({
|
||||
stopServer(server)
|
||||
}, add = TRUE)
|
||||
|
||||
if (!is.character(port)) {
|
||||
browseHost <- host
|
||||
if (identical(host, "0.0.0.0")) {
|
||||
# http://0.0.0.0/ doesn't work on QtWebKit (i.e. RStudio viewer)
|
||||
browseHost <- "127.0.0.1"
|
||||
} else if (identical(host, "::")) {
|
||||
browseHost <- "::1"
|
||||
}
|
||||
|
||||
if (httpuv::ipFamily(browseHost) == 6L) {
|
||||
browseHost <- paste0("[", browseHost, "]")
|
||||
}
|
||||
|
||||
appUrl <- paste("http://", browseHost, ":", port, sep="")
|
||||
if (is.function(launch.browser))
|
||||
launch.browser(appUrl)
|
||||
else if (launch.browser)
|
||||
utils::browseURL(appUrl)
|
||||
} else {
|
||||
appUrl <- NULL
|
||||
}
|
||||
|
||||
# call application hooks
|
||||
callAppHook("onAppStart", appUrl)
|
||||
on.exit({
|
||||
callAppHook("onAppStop", appUrl)
|
||||
}, add = TRUE)
|
||||
|
||||
.globals$reterror <- NULL
|
||||
.globals$retval <- NULL
|
||||
.globals$stopped <- FALSE
|
||||
# Top-level ..stacktraceoff..; matches with ..stacktraceon in observe(),
|
||||
# reactive(), Callbacks$invoke(), and others
|
||||
..stacktraceoff..(
|
||||
captureStackTraces({
|
||||
while (!.globals$stopped) {
|
||||
..stacktracefloor..(serviceApp())
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
if (isTRUE(.globals$reterror)) {
|
||||
stop(.globals$retval)
|
||||
}
|
||||
else if (.globals$retval$visible)
|
||||
.globals$retval$value
|
||||
else
|
||||
invisible(.globals$retval$value)
|
||||
}
|
||||
|
||||
#' Stop the currently running Shiny app
|
||||
#'
|
||||
#' Stops the currently running Shiny app, returning control to the caller of
|
||||
#' [runApp()].
|
||||
#'
|
||||
#' @param returnValue The value that should be returned from
|
||||
#' [runApp()].
|
||||
#' @export
|
||||
stopApp <- function(returnValue = invisible()) {
|
||||
# reterror will indicate whether retval is an error (i.e. it should be passed
|
||||
# to stop() when the serviceApp loop stops) or a regular value (in which case
|
||||
# it should simply be returned with the appropriate visibility).
|
||||
.globals$reterror <- FALSE
|
||||
..stacktraceoff..(
|
||||
tryCatch(
|
||||
{
|
||||
captureStackTraces(
|
||||
.globals$retval <- withVisible(..stacktraceon..(force(returnValue)))
|
||||
)
|
||||
},
|
||||
error = function(e) {
|
||||
.globals$retval <- e
|
||||
.globals$reterror <- TRUE
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
.globals$stopped <- TRUE
|
||||
httpuv::interrupt()
|
||||
}
|
||||
|
||||
#' Run Shiny Example Applications
|
||||
#'
|
||||
#' Launch Shiny example applications, and optionally, your system's web browser.
|
||||
#'
|
||||
#' @param example The name of the example to run, or `NA` (the default) to
|
||||
#' list the available examples.
|
||||
#' @param port The TCP port that the application should listen on. Defaults to
|
||||
#' choosing a random port.
|
||||
#' @param launch.browser If true, the system's default web browser will be
|
||||
#' launched automatically after the app is started. Defaults to true in
|
||||
#' interactive sessions only.
|
||||
#' @param host The IPv4 address that the application should listen on. Defaults
|
||||
#' to the `shiny.host` option, if set, or `"127.0.0.1"` if not.
|
||||
#' @param display.mode The mode in which to display the example. Defaults to
|
||||
#' `showcase`, but may be set to `normal` to see the example without
|
||||
#' code or commentary.
|
||||
#'
|
||||
#' @examples
|
||||
#' ## Only run this example in interactive R sessions
|
||||
#' if (interactive()) {
|
||||
#' # List all available examples
|
||||
#' runExample()
|
||||
#'
|
||||
#' # Run one of the examples
|
||||
#' runExample("01_hello")
|
||||
#'
|
||||
#' # Print the directory containing the code for all examples
|
||||
#' system.file("examples", package="shiny")
|
||||
#' }
|
||||
#' @export
|
||||
runExample <- function(example=NA,
|
||||
port=NULL,
|
||||
launch.browser=getOption('shiny.launch.browser',
|
||||
interactive()),
|
||||
host=getOption('shiny.host', '127.0.0.1'),
|
||||
display.mode=c("auto", "normal", "showcase")) {
|
||||
examplesDir <- system.file('examples', package='shiny')
|
||||
dir <- resolve(examplesDir, example)
|
||||
if (is.null(dir)) {
|
||||
if (is.na(example)) {
|
||||
errFun <- message
|
||||
errMsg <- ''
|
||||
}
|
||||
else {
|
||||
errFun <- stop
|
||||
errMsg <- paste('Example', example, 'does not exist. ')
|
||||
}
|
||||
|
||||
errFun(errMsg,
|
||||
'Valid examples are "',
|
||||
paste(list.files(examplesDir), collapse='", "'),
|
||||
'"')
|
||||
}
|
||||
else {
|
||||
runApp(dir, port = port, host = host, launch.browser = launch.browser,
|
||||
display.mode = display.mode)
|
||||
}
|
||||
}
|
||||
|
||||
#' Run a gadget
|
||||
#'
|
||||
#' Similar to `runApp`, but handles `input$cancel` automatically, and
|
||||
#' if running in RStudio, defaults to viewing the app in the Viewer pane.
|
||||
#'
|
||||
#' @param app Either a Shiny app object as created by
|
||||
#' [`shinyApp()`][shiny] et al, or, a UI object.
|
||||
#' @param server Ignored if `app` is a Shiny app object; otherwise, passed
|
||||
#' along to `shinyApp` (i.e. `shinyApp(ui = app, server = server)`).
|
||||
#' @param port See [`runApp()`][shiny].
|
||||
#' @param viewer Specify where the gadget should be displayed--viewer pane,
|
||||
#' dialog window, or external browser--by passing in a call to one of the
|
||||
#' [viewer()] functions.
|
||||
#' @param stopOnCancel If `TRUE` (the default), then an `observeEvent`
|
||||
#' is automatically created that handles `input$cancel` by calling
|
||||
#' `stopApp()` with an error. Pass `FALSE` if you want to handle
|
||||
#' `input$cancel` yourself.
|
||||
#' @return The value returned by the gadget.
|
||||
#'
|
||||
#' @examples
|
||||
#' \dontrun{
|
||||
#' library(shiny)
|
||||
#'
|
||||
#' ui <- fillPage(...)
|
||||
#'
|
||||
#' server <- function(input, output, session) {
|
||||
#' ...
|
||||
#' }
|
||||
#'
|
||||
#' # Either pass ui/server as separate arguments...
|
||||
#' runGadget(ui, server)
|
||||
#'
|
||||
#' # ...or as a single app object
|
||||
#' runGadget(shinyApp(ui, server))
|
||||
#' }
|
||||
#' @export
|
||||
runGadget <- function(app, server = NULL, port = getOption("shiny.port"),
|
||||
viewer = paneViewer(), stopOnCancel = TRUE) {
|
||||
|
||||
if (!is.shiny.appobj(app)) {
|
||||
app <- shinyApp(app, server)
|
||||
}
|
||||
|
||||
if (isTRUE(stopOnCancel)) {
|
||||
app <- decorateServerFunc(app, function(input, output, session) {
|
||||
observeEvent(input$cancel, {
|
||||
stopApp(stop("User cancel", call. = FALSE))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
if (is.null(viewer)) {
|
||||
viewer <- utils::browseURL
|
||||
}
|
||||
|
||||
shiny::runApp(app, port = port, launch.browser = viewer)
|
||||
}
|
||||
|
||||
# Add custom functionality to a Shiny app object's server func
|
||||
decorateServerFunc <- function(appobj, serverFunc) {
|
||||
origServerFuncSource <- appobj$serverFuncSource
|
||||
appobj$serverFuncSource <- function() {
|
||||
origServerFunc <- origServerFuncSource()
|
||||
function(input, output, session) {
|
||||
serverFunc(input, output, session)
|
||||
|
||||
# The clientData and session arguments are optional; check if
|
||||
# each exists
|
||||
args <- argsForServerFunc(origServerFunc, session)
|
||||
do.call(origServerFunc, args)
|
||||
}
|
||||
}
|
||||
appobj
|
||||
}
|
||||
|
||||
#' Viewer options
|
||||
#'
|
||||
#' Use these functions to control where the gadget is displayed in RStudio (or
|
||||
#' other R environments that emulate RStudio's viewer pane/dialog APIs). If
|
||||
#' viewer APIs are not available in the current R environment, then the gadget
|
||||
#' will be displayed in the system's default web browser (see
|
||||
#' [utils::browseURL()]).
|
||||
#'
|
||||
#' @return A function that takes a single `url` parameter, suitable for
|
||||
#' passing as the `viewer` argument of [runGadget()].
|
||||
#'
|
||||
#' @rdname viewer
|
||||
#' @name viewer
|
||||
NULL
|
||||
|
||||
#' @param minHeight The minimum height (in pixels) desired to show the gadget in
|
||||
#' the viewer pane. If a positive number, resize the pane if necessary to show
|
||||
#' at least that many pixels. If `NULL`, use the existing viewer pane
|
||||
#' size. If `"maximize"`, use the maximum available vertical space.
|
||||
#' @rdname viewer
|
||||
#' @export
|
||||
paneViewer <- function(minHeight = NULL) {
|
||||
viewer <- getOption("viewer")
|
||||
if (is.null(viewer)) {
|
||||
utils::browseURL
|
||||
} else {
|
||||
function(url) {
|
||||
viewer(url, minHeight)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#' @param dialogName The window title to display for the dialog.
|
||||
#' @param width,height The desired dialog width/height, in pixels.
|
||||
#' @rdname viewer
|
||||
#' @export
|
||||
dialogViewer <- function(dialogName, width = 600, height = 600) {
|
||||
viewer <- getOption("shinygadgets.showdialog")
|
||||
if (is.null(viewer)) {
|
||||
utils::browseURL
|
||||
} else {
|
||||
function(url) {
|
||||
viewer(dialogName, url, width = width, height = height)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#' @param browser See [utils::browseURL()].
|
||||
#' @rdname viewer
|
||||
#' @export
|
||||
browserViewer <- function(browser = getOption("browser")) {
|
||||
function(url) {
|
||||
utils::browseURL(url, browser = browser)
|
||||
}
|
||||
}
|
||||
|
||||
# Returns TRUE if we're running in Shiny Server or other hosting environment,
|
||||
# otherwise returns FALSE.
|
||||
|
||||
@@ -8,31 +8,55 @@ getShinyOption <- function(name, default = NULL) {
|
||||
# Make sure to use named (not numeric) indexing
|
||||
name <- as.character(name)
|
||||
|
||||
if (name %in% names(.globals$options))
|
||||
.globals$options[[name]]
|
||||
else
|
||||
default
|
||||
# Check if there's a current session
|
||||
session <- getDefaultReactiveDomain()
|
||||
if (!is.null(session)) {
|
||||
if (name %in% names(session$options)) {
|
||||
return(session$options[[name]])
|
||||
} else {
|
||||
return(default)
|
||||
}
|
||||
}
|
||||
|
||||
# Check if there's a current app
|
||||
app_state <- getCurrentAppState()
|
||||
if (!is.null(app_state)) {
|
||||
if (name %in% names(app_state$options)) {
|
||||
return(app_state$options[[name]])
|
||||
} else {
|
||||
return(default)
|
||||
}
|
||||
}
|
||||
|
||||
# If we got here, look in global options
|
||||
if (name %in% names(.globals$options)) {
|
||||
return(.globals$options[[name]])
|
||||
} else {
|
||||
return(default)
|
||||
}
|
||||
}
|
||||
|
||||
#' Get or set Shiny options
|
||||
#'
|
||||
#' `getShinyOption()` retrieves the value of a Shiny option. `shinyOptions()`
|
||||
#' sets the value of Shiny options; it can also be used to return a list of all
|
||||
#' currently-set Shiny options.
|
||||
#' @description
|
||||
#'
|
||||
#' @section Scope:
|
||||
#' There is a global option set which is available by default. When a Shiny
|
||||
#' application is run with [runApp()], that option set is duplicated and the
|
||||
#' new option set is available for getting or setting values. If options
|
||||
#' are set from `global.R`, `app.R`, `ui.R`, or `server.R`, or if they are set
|
||||
#' from inside the server function, then the options will be scoped to the
|
||||
#' application. When the application exits, the new option set is discarded and
|
||||
#' the global option set is restored.
|
||||
#' There are two mechanisms for working with options for Shiny. One is the
|
||||
#' [options()] function, which is part of base R, and the other is the
|
||||
#' `shinyOptions()` function, which is in the Shiny package. The reason for
|
||||
#' these two mechanisms is has to do with legacy code and scoping.
|
||||
#'
|
||||
#' @section Options:
|
||||
#' There are a number of global options that affect Shiny's behavior. These can
|
||||
#' be set globally with `options()` or locally (for a single app) with
|
||||
#' `shinyOptions()`.
|
||||
#' The [options()] function sets options globally, for the duration of the R
|
||||
#' process. The [getOption()] function retrieves the value of an option. All
|
||||
#' shiny related options of this type are prefixed with `"shiny."`.
|
||||
#'
|
||||
#' The `shinyOptions()` function sets the value of a shiny option, but unlike
|
||||
#' `options()`, it is not always global in scope; the options may be scoped
|
||||
#' globally, to an application, or to a user session in an application,
|
||||
#' depending on the context. The `getShinyOption()` function retrieves a value
|
||||
#' of a shiny option. Currently, the options set via `shinyOptions` are for
|
||||
#' internal use only.
|
||||
#'
|
||||
#' @section Options with `options()`:
|
||||
#'
|
||||
#' \describe{
|
||||
#' \item{shiny.autoreload (defaults to `FALSE`)}{If `TRUE` when a Shiny app is launched, the
|
||||
@@ -107,46 +131,119 @@ getShinyOption <- function(name, default = NULL) {
|
||||
#' `"recv"` (only print messages received by the server), `TRUE`
|
||||
#' (print all messages), or `FALSE` (default; don't print any of these
|
||||
#' messages).}
|
||||
#' \item{shiny.autoload.r (defaults to `TRUE`)}{If `TRUE`, then the R/
|
||||
#' of a shiny app will automatically be sourced.}
|
||||
#' \item{shiny.usecairo (defaults to `TRUE`)}{This is used to disable graphical rendering by the
|
||||
#' Cairo package, if it is installed. See [plotPNG()] for more
|
||||
#' information.}
|
||||
#' }
|
||||
#'
|
||||
#'
|
||||
#' @section Scoping for `shinyOptions()`:
|
||||
#'
|
||||
#' There are three levels of scoping for `shinyOptions()`: global,
|
||||
#' application, and session.
|
||||
#'
|
||||
#' The global option set is available by default. Any calls to
|
||||
#' `shinyOptions()` and `getShinyOption()` outside of an app will access the
|
||||
#' global option set.
|
||||
#'
|
||||
#' When a Shiny application is run with [runApp()], the global option set is
|
||||
#' duplicated and the new option set is available at the application level. If
|
||||
#' options are set from `global.R`, `app.R`, `ui.R`, or `server.R` (but
|
||||
#' outside of the server function), then the application-level options will be
|
||||
#' modified.
|
||||
#'
|
||||
#' Each time a user session is started, the application-level option set is
|
||||
#' duplicated, for that session. If the options are set from inside the server
|
||||
#' function, then they will be scoped to the session.
|
||||
#'
|
||||
#' @section Options with `shinyOptions()`:
|
||||
#'
|
||||
#' There are a number of global options that affect Shiny's behavior. These
|
||||
#' can be set globally with `options()` or locally (for a single app) with
|
||||
#' `shinyOptions()`.
|
||||
#'
|
||||
#' \describe{ \item{cache}{A caching object that will be used by
|
||||
#' [renderCachedPlot()]. If not specified, a [memoryCache()] will be used.} }
|
||||
#'
|
||||
#' @param ... Options to set, with the form `name = value`.
|
||||
#' @aliases shiny-options
|
||||
#' @examples
|
||||
#' \dontrun{
|
||||
#' shinyOptions(myOption = 10)
|
||||
#' getShinyOption("myOption")
|
||||
#' }
|
||||
#' @export
|
||||
shinyOptions <- function(...) {
|
||||
newOpts <- list(...)
|
||||
|
||||
if (length(newOpts) > 0) {
|
||||
# If we're within a session, modify at the session level.
|
||||
session <- getDefaultReactiveDomain()
|
||||
if (!is.null(session)) {
|
||||
# Modify session-level-options
|
||||
session$options <- dropNulls(mergeVectors(session$options, newOpts))
|
||||
return(invisible(session$options))
|
||||
}
|
||||
|
||||
# If not in a session, but we have a currently running app, modify options
|
||||
# at the app level.
|
||||
app_state <- getCurrentAppState()
|
||||
if (!is.null(app_state)) {
|
||||
# Modify app-level options
|
||||
app_state$options <- dropNulls(mergeVectors(app_state$options, newOpts))
|
||||
return(invisible(app_state$options))
|
||||
}
|
||||
|
||||
# If no currently running app, modify global options and return them.
|
||||
.globals$options <- dropNulls(mergeVectors(.globals$options, newOpts))
|
||||
invisible(.globals$options)
|
||||
} else {
|
||||
.globals$options
|
||||
return(invisible(.globals$options))
|
||||
}
|
||||
}
|
||||
|
||||
# If not setting any options, just return current option set, visibly.
|
||||
|
||||
# Eval an expression with a new option set
|
||||
withLocalOptions <- function(expr) {
|
||||
oldOptionSet <- .globals$options
|
||||
on.exit(.globals$options <- oldOptionSet)
|
||||
session <- getDefaultReactiveDomain()
|
||||
if (!is.null(session)) {
|
||||
return(session$options)
|
||||
}
|
||||
|
||||
expr
|
||||
app_state <- getCurrentAppState()
|
||||
if (!is.null(app_state)) {
|
||||
return(app_state$options)
|
||||
}
|
||||
|
||||
return(.globals$options)
|
||||
}
|
||||
|
||||
|
||||
# Get specific shiny options and put them in a list, reset those shiny options,
|
||||
# and then return the options list. This should be during the creation of a
|
||||
# shiny app object, which happens before another option frame is added to the
|
||||
# options stack (the new option frame is added when the app is run). This
|
||||
# function "consumes" the options when the shinyApp object is created, so the
|
||||
# options won't affect another app that is created later.
|
||||
consumeAppOptions <- function() {
|
||||
# shiny app object. This function "consumes" the options when the shinyApp
|
||||
# object is created, so the options won't affect another app that is created
|
||||
# later.
|
||||
#
|
||||
# ==== Example ====
|
||||
# shinyOptions(bookmarkStore = 1234)
|
||||
# # This now returns 1234.
|
||||
# getShinyOption("bookmarkStore")
|
||||
#
|
||||
# # Creating the app captures the bookmarkStore option and clears it.
|
||||
# s <- shinyApp(
|
||||
# fluidPage(verbatimTextOutput("txt")),
|
||||
# function(input, output) {
|
||||
# output$txt <- renderText(getShinyOption("bookmarkStore"))
|
||||
# }
|
||||
# )
|
||||
#
|
||||
# # This now returns NULL.
|
||||
# getShinyOption("bookmarkStore")
|
||||
#
|
||||
# When running the app, the app will display "1234"
|
||||
# runApp(s)
|
||||
#
|
||||
# # After quitting the app, this still returns NULL.
|
||||
# getShinyOption("bookmarkStore")
|
||||
# ==================
|
||||
#
|
||||
# If another app had been created after s was created, but before s was run,
|
||||
# then it would capture the value of "bookmarkStore" at the time of creation.
|
||||
captureAppOptions <- function() {
|
||||
options <- list(
|
||||
appDir = getwd(),
|
||||
bookmarkStore = getShinyOption("bookmarkStore")
|
||||
@@ -157,9 +254,9 @@ consumeAppOptions <- function() {
|
||||
options
|
||||
}
|
||||
|
||||
# Do the inverse of consumeAppOptions. This should be called once the app is
|
||||
# Do the inverse of captureAppOptions. This should be called once the app is
|
||||
# started.
|
||||
unconsumeAppOptions <- function(options) {
|
||||
applyCapturedAppOptions <- function(options) {
|
||||
if (!is.null(options)) {
|
||||
do.call(shinyOptions, options)
|
||||
}
|
||||
|
||||
144
R/shiny.R
144
R/shiny.R
@@ -117,9 +117,6 @@ workerId <- local({
|
||||
#' \item{clientData}{
|
||||
#' A [reactiveValues()] object that contains information about the client.
|
||||
#' \itemize{
|
||||
#' \item{`allowDataUriScheme` is a logical value that indicates whether
|
||||
#' the browser is able to handle URIs that use the `data:` scheme.
|
||||
#' }
|
||||
#' \item{`pixelratio` reports the "device pixel ratio" from the web browser,
|
||||
#' or 1 if none is reported. The value is 2 for Apple Retina displays.
|
||||
#' }
|
||||
@@ -474,8 +471,22 @@ ShinySession <- R6Class(
|
||||
|
||||
if (!is.null(params$input)) {
|
||||
|
||||
allInputs <- isolate(
|
||||
reactiveValuesToList(self$input, all.names = TRUE)
|
||||
# The isolate and reactiveValuesToList calls are being executed
|
||||
# in a non-reactive context, but will produce output in the reactlog
|
||||
# Seeing new, unlabelled reactives ONLY when calling shinytest is
|
||||
# jarring / frustrating to debug.
|
||||
# Since labeling these values is not currently supported in reactlog,
|
||||
# it is better to hide them.
|
||||
# Hopefully we can replace this with something like
|
||||
# `with_reactlog_group("shinytest", {})`, which would visibily explain
|
||||
# why the new reactives are added when calling shinytest
|
||||
withr::with_options(
|
||||
list(shiny.reactlog = FALSE),
|
||||
{
|
||||
allInputs <- isolate(
|
||||
reactiveValuesToList(self$input, all.names = TRUE)
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
# If params$input is "1", return all; otherwise return just the
|
||||
@@ -651,6 +662,7 @@ ShinySession <- R6Class(
|
||||
cache = NULL, # A cache object used in the session
|
||||
user = NULL,
|
||||
groups = NULL,
|
||||
options = NULL, # For session-specific shinyOptions()
|
||||
|
||||
initialize = function(websocket) {
|
||||
private$websocket <- websocket
|
||||
@@ -681,6 +693,9 @@ ShinySession <- R6Class(
|
||||
private$.outputs <- list()
|
||||
private$.outputOptions <- list()
|
||||
|
||||
# Copy app-level options
|
||||
self$options <- getCurrentAppState()$options
|
||||
|
||||
self$cache <- MemoryCache$new()
|
||||
|
||||
private$bookmarkCallbacks <- Callbacks$new()
|
||||
@@ -688,7 +703,7 @@ ShinySession <- R6Class(
|
||||
private$restoreCallbacks <- Callbacks$new()
|
||||
private$restoredCallbacks <- Callbacks$new()
|
||||
|
||||
private$testMode <- .globals$testMode
|
||||
private$testMode <- getShinyOption("testmode", default = FALSE)
|
||||
private$enableTestSnapshot()
|
||||
|
||||
private$registerSessionEndCallbacks()
|
||||
@@ -928,7 +943,33 @@ ShinySession <- R6Class(
|
||||
|
||||
impl <- .subset2(x, 'impl')
|
||||
key <- .subset2(x, 'ns')(name)
|
||||
impl$freeze(key)
|
||||
|
||||
is_input <- identical(impl, private$.input)
|
||||
|
||||
# There's no good reason for us not to just do force=TRUE, except that we
|
||||
# know this fixes problems for freezeReactiveValue(input) but we don't
|
||||
# currently even know what you would use freezeReactiveValue(rv) for. In
|
||||
# the spirit of not breaking things we don't understand, we're making as
|
||||
# targeted a fix as possible, while emitting a deprecation warning (below)
|
||||
# that should help us gather more data about the other case.
|
||||
impl$freeze(key, invalidate = is_input)
|
||||
|
||||
if (is_input) {
|
||||
# Notify the client that this input was frozen. The client will ensure
|
||||
# that the next time it sees a value for that input, even if the value
|
||||
# has not changed from the last known value of that input, it will be
|
||||
# sent to the server anyway.
|
||||
private$sendMessage(frozen = list(
|
||||
ids = list(key)
|
||||
))
|
||||
} else {
|
||||
if (getOption("shiny.deprecation.messages", TRUE) && getOption("shiny.deprecation.messages.freeze", TRUE)) {
|
||||
rlang::warn(
|
||||
"Support for calling freezeReactiveValue() with non-`input` reactiveValues objects is soft-deprecated, and may be removed in a future version of Shiny. (See https://github.com/rstudio/shiny/issues/3063)",
|
||||
.frequency = "once", .frequency_id = "freezeReactiveValue")
|
||||
}
|
||||
}
|
||||
|
||||
self$onFlushed(function() impl$thaw(key))
|
||||
},
|
||||
|
||||
@@ -1238,6 +1279,41 @@ ShinySession <- R6Class(
|
||||
modal = list(type = type, message = message)
|
||||
)
|
||||
},
|
||||
|
||||
setCurrentTheme = function(theme) {
|
||||
# This function does three things: (1) sets theme as the current
|
||||
# bootstrapTheme, (2) re-executes any registered theme dependencies, and
|
||||
# (3) sends the resulting dependencies to the client.
|
||||
|
||||
# Note that this will automatically scope to the session.
|
||||
shinyOptions(bootstrapTheme = theme)
|
||||
|
||||
# Call any theme dependency functions and make sure we get a list of deps back
|
||||
funcs <- getShinyOption("themeDependencyFuncs")
|
||||
deps <- lapply(funcs, function(func) {
|
||||
deps <- func(theme)
|
||||
if (length(deps) == 0) return(NULL)
|
||||
if (inherits(deps, "html_dependency")) return(list(deps))
|
||||
is_dep <- vapply(deps, inherits, logical(1), "html_dependency")
|
||||
if (all(is_dep)) return(deps)
|
||||
stop("All registerThemeDependency() functions must yield htmlDependency() object(s)", call. = FALSE)
|
||||
})
|
||||
# Work with a flat list of dependencies
|
||||
deps <- unlist(dropNulls(deps), recursive = FALSE)
|
||||
# Add a special flag to let Shiny.renderDependencies() know that, even
|
||||
# though we've already rendered the dependency, that we need to re-render
|
||||
# the stylesheets
|
||||
deps <- lapply(deps, function(dep) {
|
||||
dep$restyle <- TRUE
|
||||
dep
|
||||
})
|
||||
|
||||
# Send any dependencies to be re-rendered
|
||||
if (length(deps)) {
|
||||
insertUI(selector = "body", where = "afterEnd", ui = tagList(deps))
|
||||
}
|
||||
},
|
||||
|
||||
dispatch = function(msg) {
|
||||
method <- paste('@', msg$method, sep='')
|
||||
func <- try(self[[method]], silent = TRUE)
|
||||
@@ -1671,10 +1747,6 @@ ShinySession <- R6Class(
|
||||
)
|
||||
},
|
||||
|
||||
# Public RPC methods
|
||||
`@uploadieFinish` = function() {
|
||||
# Do nothing; just want the side effect of flushReact, output flush, etc.
|
||||
},
|
||||
`@uploadInit` = function(fileInfos) {
|
||||
maxSize <- getOption('shiny.maxRequestSize', 5 * 1024 * 1024)
|
||||
fileInfos <- lapply(fileInfos, function(fi) {
|
||||
@@ -1741,33 +1813,6 @@ ShinySession <- R6Class(
|
||||
}
|
||||
}
|
||||
|
||||
# @description Only applicable to files uploaded via IE. When possible,
|
||||
# adds the appropriate extension to temporary files created by
|
||||
# \code{mime::parse_multipart}.
|
||||
# @param multipart A named list as returned by
|
||||
# \code{mime::parse_multipart}
|
||||
# @return A named list with datapath updated to point to the new location
|
||||
# of the file, if an extension was added.
|
||||
maybeMoveIEUpload <- function(multipart) {
|
||||
if (is.null(multipart)) return(NULL)
|
||||
|
||||
lapply(multipart, function(input) {
|
||||
oldPath <- input$datapath
|
||||
newPath <- paste0(oldPath, maybeGetExtension(input$name))
|
||||
if (oldPath != newPath) {
|
||||
file.rename(oldPath, newPath)
|
||||
input$datapath <- newPath
|
||||
}
|
||||
input
|
||||
})
|
||||
}
|
||||
|
||||
if (matches[2] == 'uploadie' && identical(req$REQUEST_METHOD, "POST")) {
|
||||
id <- URLdecode(matches[3])
|
||||
res <- maybeMoveIEUpload(mime::parse_multipart(req))
|
||||
private$.input$set(id, res[[id]])
|
||||
return(httpResponse(200, 'text/plain', 'OK'))
|
||||
}
|
||||
|
||||
if (matches[2] == 'download') {
|
||||
|
||||
@@ -1876,33 +1921,18 @@ ShinySession <- R6Class(
|
||||
|
||||
return(httpResponse(404, 'text/html', '<h1>Not Found</h1>'))
|
||||
},
|
||||
saveFileUrl = function(name, data, contentType, extra=list()) {
|
||||
"Creates an entry in the file map for the data, and returns a URL pointing
|
||||
to the file."
|
||||
self$files$set(name, list(data=data, contentType=contentType))
|
||||
return(sprintf('session/%s/file/%s?w=%s&r=%s',
|
||||
URLencode(self$token, TRUE),
|
||||
URLencode(name, TRUE),
|
||||
workerId(),
|
||||
createUniqueId(8)))
|
||||
},
|
||||
# Send a file to the client
|
||||
fileUrl = function(name, file, contentType='application/octet-stream') {
|
||||
"Return a URL for a file to be sent to the client. If allowDataUriScheme
|
||||
is TRUE, then the file will be base64 encoded and embedded in the URL.
|
||||
Otherwise, a URL pointing to the file will be returned."
|
||||
"Return a URL for a file to be sent to the client. The file will be base64
|
||||
encoded and embedded in the URL."
|
||||
bytes <- file.info(file)$size
|
||||
if (is.na(bytes))
|
||||
return(NULL)
|
||||
|
||||
fileData <- readBin(file, 'raw', n=bytes)
|
||||
|
||||
if (isTRUE(private$.clientData$.values$get("allowDataUriScheme"))) {
|
||||
b64 <- rawToBase64(fileData)
|
||||
return(paste('data:', contentType, ';base64,', b64, sep=''))
|
||||
} else {
|
||||
return(self$saveFileUrl(name, fileData, contentType))
|
||||
}
|
||||
b64 <- rawToBase64(fileData)
|
||||
return(paste('data:', contentType, ';base64,', b64, sep=''))
|
||||
},
|
||||
registerDownload = function(name, filename, contentType, func) {
|
||||
|
||||
|
||||
@@ -93,8 +93,7 @@ shinyApp <- function(ui, server, onStart=NULL, options=list(),
|
||||
|
||||
# Store the appDir and bookmarking-related options, so that we can read them
|
||||
# from within the app.
|
||||
shinyOptions(appDir = getwd())
|
||||
appOptions <- consumeAppOptions()
|
||||
appOptions <- captureAppOptions()
|
||||
|
||||
structure(
|
||||
list(
|
||||
@@ -408,7 +407,7 @@ shinyAppDir_appR <- function(fileName, appDir, options=list())
|
||||
if (!is.shiny.appobj(result))
|
||||
stop("app.R did not return a shiny.appobj object.")
|
||||
|
||||
unconsumeAppOptions(result$appOptions)
|
||||
applyCapturedAppOptions(result$appOptions)
|
||||
|
||||
return(result)
|
||||
}
|
||||
@@ -579,84 +578,3 @@ deferredIFrame <- function(path, width, height) {
|
||||
class = "shiny-frame shiny-frame-deferred"
|
||||
)
|
||||
}
|
||||
|
||||
#' Knitr S3 methods
|
||||
#'
|
||||
#' These S3 methods are necessary to help Shiny applications and UI chunks embed
|
||||
#' themselves in knitr/rmarkdown documents.
|
||||
#'
|
||||
#' @name knitr_methods
|
||||
#' @param x Object to knit_print
|
||||
#' @param ... Additional knit_print arguments
|
||||
NULL
|
||||
|
||||
# If there's an R Markdown runtime option set but it isn't set to Shiny, then
|
||||
# return a warning indicating the runtime is inappropriate for this object.
|
||||
# Returns NULL in all other cases.
|
||||
shiny_rmd_warning <- function() {
|
||||
runtime <- knitr::opts_knit$get("rmarkdown.runtime")
|
||||
if (!is.null(runtime) && runtime != "shiny")
|
||||
# note that the RStudio IDE checks for this specific string to detect Shiny
|
||||
# applications in static document
|
||||
list(structure(
|
||||
"Shiny application in a static R Markdown document",
|
||||
class = "rmd_warning"))
|
||||
else
|
||||
NULL
|
||||
}
|
||||
|
||||
#' @rdname knitr_methods
|
||||
knit_print.shiny.appobj <- function(x, ...) {
|
||||
opts <- x$options %OR% list()
|
||||
width <- if (is.null(opts$width)) "100%" else opts$width
|
||||
height <- if (is.null(opts$height)) "400" else opts$height
|
||||
|
||||
runtime <- knitr::opts_knit$get("rmarkdown.runtime")
|
||||
if (!is.null(runtime) && runtime != "shiny") {
|
||||
# If not rendering to a Shiny document, create a box exactly the same
|
||||
# dimensions as the Shiny app would have had (so the document continues to
|
||||
# flow as it would have with the app), and display a diagnostic message
|
||||
width <- validateCssUnit(width)
|
||||
height <- validateCssUnit(height)
|
||||
output <- tags$div(
|
||||
style=paste("width:", width, "; height:", height, "; text-align: center;",
|
||||
"box-sizing: border-box;", "-moz-box-sizing: border-box;",
|
||||
"-webkit-box-sizing: border-box;"),
|
||||
class="muted well",
|
||||
"Shiny applications not supported in static R Markdown documents")
|
||||
}
|
||||
else {
|
||||
path <- addSubApp(x)
|
||||
output <- deferredIFrame(path, width, height)
|
||||
}
|
||||
|
||||
# If embedded Shiny apps ever have JS/CSS dependencies (like pym.js) we'll
|
||||
# need to grab those and put them in meta, like in knit_print.shiny.tag. But
|
||||
# for now it's not an issue, so just return the HTML and warning.
|
||||
|
||||
knitr::asis_output(htmlPreserve(format(output, indent=FALSE)),
|
||||
meta = shiny_rmd_warning(), cacheable = FALSE)
|
||||
}
|
||||
|
||||
# Let us use a nicer syntax in knitr chunks than literally
|
||||
# calling output$value <- renderFoo(...) and fooOutput().
|
||||
#' @rdname knitr_methods
|
||||
#' @param inline Whether the object is printed inline.
|
||||
knit_print.shiny.render.function <- function(x, ..., inline = FALSE) {
|
||||
x <- htmltools::as.tags(x, inline = inline)
|
||||
output <- knitr::knit_print(tagList(x))
|
||||
attr(output, "knit_cacheable") <- FALSE
|
||||
attr(output, "knit_meta") <- append(attr(output, "knit_meta"),
|
||||
shiny_rmd_warning())
|
||||
output
|
||||
}
|
||||
|
||||
# Lets us drop reactive expressions directly into a knitr chunk and have the
|
||||
# value printed out! Nice for teaching if nothing else.
|
||||
#' @rdname knitr_methods
|
||||
knit_print.reactive <- function(x, ..., inline = FALSE) {
|
||||
renderFunc <- if (inline) renderText else renderPrint
|
||||
knitr::knit_print(renderFunc({
|
||||
x()
|
||||
}), inline = inline)
|
||||
}
|
||||
58
R/shinyui.R
58
R/shinyui.R
@@ -25,6 +25,8 @@ withMathJax <- function(...) {
|
||||
}
|
||||
|
||||
renderPage <- function(ui, showcase=0, testMode=FALSE) {
|
||||
lang <- getLang(ui)
|
||||
|
||||
# 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")) {
|
||||
@@ -38,7 +40,10 @@ renderPage <- function(ui, showcase=0, testMode=FALSE) {
|
||||
# Put the body into the default template
|
||||
ui <- htmlTemplate(
|
||||
system.file("template", "default.html", package = "shiny"),
|
||||
body = ui
|
||||
lang = lang,
|
||||
body = ui,
|
||||
# this template is a complete HTML document
|
||||
document_ = TRUE
|
||||
)
|
||||
}
|
||||
|
||||
@@ -61,25 +66,60 @@ renderPage <- function(ui, showcase=0, testMode=FALSE) {
|
||||
stop("Unsupported version of jQuery: ", version)
|
||||
}
|
||||
|
||||
shiny_deps <- list(
|
||||
htmlDependency("json2", "2014.02.04", c(href="shared"), script = "json2-min.js"),
|
||||
jquery(),
|
||||
htmlDependency("shiny", utils::packageVersion("shiny"), c(href="shared"),
|
||||
script = if (getOption("shiny.minified", TRUE)) "shiny.min.js" else "shiny.js",
|
||||
stylesheet = "shiny.css")
|
||||
shiny_deps <- c(
|
||||
list(jquery()),
|
||||
shinyDependencies()
|
||||
)
|
||||
|
||||
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")
|
||||
c(href="shared"), script = "shiny-testmode.js")
|
||||
}
|
||||
|
||||
html <- renderDocument(ui, shiny_deps, processDep = createWebDependency)
|
||||
enc2utf8(paste(collapse = "\n", html))
|
||||
}
|
||||
|
||||
shinyDependencies <- function() {
|
||||
version <- utils::packageVersion("shiny")
|
||||
list(
|
||||
bootstraplib::bs_dependency_defer(shinyDependencyCSS),
|
||||
htmlDependency(
|
||||
name = "shiny-javascript",
|
||||
version = version,
|
||||
src = c(href = "shared"),
|
||||
script = if (getOption("shiny.minified", TRUE)) "shiny.min.js" else "shiny.js"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
shinyDependencyCSS <- function(theme) {
|
||||
version <- utils::packageVersion("shiny")
|
||||
|
||||
if (!is_bs_theme(theme)) {
|
||||
return(htmlDependency(
|
||||
name = "shiny-css",
|
||||
version = version,
|
||||
src = c(href = "shared"),
|
||||
stylesheet = "shiny.min.css"
|
||||
))
|
||||
}
|
||||
|
||||
scss_home <- system.file("www/shared/shiny_scss", package = "shiny")
|
||||
scss_files <- file.path(scss_home, c("bootstrap.scss", "shiny.scss"))
|
||||
scss_files <- lapply(scss_files, sass::sass_file)
|
||||
|
||||
bootstraplib::bs_dependency(
|
||||
input = scss_files,
|
||||
theme = theme,
|
||||
name = "shiny-sass",
|
||||
version = version,
|
||||
cache_key_extra = version
|
||||
)
|
||||
}
|
||||
|
||||
#' Create a Shiny UI handler
|
||||
#'
|
||||
#' Historically this function was used in ui.R files to register a user
|
||||
@@ -120,7 +160,7 @@ uiHttpHandler <- function(ui, uiPattern = "^/$") {
|
||||
showcaseMode <- mode
|
||||
}
|
||||
|
||||
testMode <- .globals$testMode %OR% FALSE
|
||||
testMode <- getShinyOption("testmode", default = FALSE)
|
||||
|
||||
# Create a restore context using query string
|
||||
bookmarkStore <- getShinyOption("bookmarkStore", default = "disable")
|
||||
|
||||
@@ -372,35 +372,35 @@ isTemp <- function(path, tempDir = tempdir(), mustExist) {
|
||||
return(substr(path, 1, nchar(tempDir)) == tempDir)
|
||||
}
|
||||
|
||||
#' Printable Output
|
||||
#' Text Output
|
||||
#'
|
||||
#' Makes a reactive version of the given function that captures any printed
|
||||
#' output, and also captures its printable result (unless
|
||||
#' [base::invisible()]), into a string. The resulting function is suitable
|
||||
#' for assigning to an `output` slot.
|
||||
#' @description
|
||||
#' `renderPrint()` prints the result of `expr`, while `renderText()` pastes it
|
||||
#' together into a single string. `renderPrint()` is equivalent to [print()];
|
||||
#' `renderText()` is equivalent to [cat()]. Both functions capture all other
|
||||
#' printed output generated while evaluating `expr`.
|
||||
#'
|
||||
#' `renderPrint()` is usually paired with [verbatimTextOutput()];
|
||||
#' `renderText()` is usually paired with [textOutput()].
|
||||
#'
|
||||
#' @details
|
||||
#' The corresponding HTML output tag can be anything (though `pre` is
|
||||
#' recommended if you need a monospace font and whitespace preserved) and should
|
||||
#' have the CSS class name `shiny-text-output`.
|
||||
#'
|
||||
#' The result of executing `func` will be printed inside a
|
||||
#' [utils::capture.output()] call.
|
||||
#' @return
|
||||
#' For `renderPrint()`, note the given expression returns `NULL` then `NULL`
|
||||
#' will actually be visible in the output. To display nothing, make your
|
||||
#' function return [invisible()].
|
||||
#'
|
||||
#' Note that unlike most other Shiny output functions, if the given function
|
||||
#' returns `NULL` then `NULL` will actually be visible in the output.
|
||||
#' To display nothing, make your function return [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 `expr`.
|
||||
#' @param expr An expression to evaluate.
|
||||
#' @param env The environment in which to evaluate `expr`. For expert use only.
|
||||
#' @param quoted Is `expr` a quoted expression (with `quote()`)? This
|
||||
#' is useful if you want to save an expression in a variable.
|
||||
#' @param width The value for `[options][base::options]('width')`.
|
||||
#' @param width Width of printed output.
|
||||
#' @param outputArgs A list of arguments to be passed through to the implicit
|
||||
#' call to [verbatimTextOutput()] when `renderPrint` is used
|
||||
#' in an interactive R Markdown document.
|
||||
#' @seealso [renderText()] for displaying the value returned from a
|
||||
#' function, instead of the printed output.
|
||||
#' call to [verbatimTextOutput()] or [textOutput()] when the functions are
|
||||
#' used in an interactive RMarkdown document.
|
||||
#'
|
||||
#' @example res/text-example.R
|
||||
#' @export
|
||||
@@ -476,35 +476,10 @@ createRenderPrintPromiseDomain <- function(width) {
|
||||
)
|
||||
}
|
||||
|
||||
#' Text Output
|
||||
#'
|
||||
#' Makes a reactive version of the given function that also uses
|
||||
#' [base::cat()] to turn its result into a single-element character
|
||||
#' vector.
|
||||
#'
|
||||
#' The corresponding HTML output tag can be anything (though `pre` is
|
||||
#' recommended if you need a monospace font and whitespace preserved) and should
|
||||
#' have the CSS class name `shiny-text-output`.
|
||||
#'
|
||||
#' The result of executing `func` will passed to `cat`, inside a
|
||||
#' [utils::capture.output()] call.
|
||||
#'
|
||||
#' @param expr An expression that returns an R object that can be used as an
|
||||
#' argument to `cat`.
|
||||
#' @param env The environment in which to evaluate `expr`.
|
||||
#' @param quoted Is `expr` a quoted expression (with `quote()`)? This
|
||||
#' is useful if you want to save an expression in a variable.
|
||||
#' @param outputArgs A list of arguments to be passed through to the implicit
|
||||
#' call to [textOutput()] when `renderText` is used in an
|
||||
#' interactive R Markdown document.
|
||||
#' @param sep A separator passed to `cat` to be appended after each
|
||||
#' element.
|
||||
#'
|
||||
#' @seealso [renderPrint()] for capturing the print output of a
|
||||
#' function, rather than the returned text value.
|
||||
#'
|
||||
#' @example res/text-example.R
|
||||
#' @export
|
||||
#' @rdname renderPrint
|
||||
renderText <- function(expr, env=parent.frame(), quoted=FALSE,
|
||||
outputArgs=list(), sep=" ") {
|
||||
installExprFunction(expr, "func", env, quoted)
|
||||
|
||||
@@ -220,4 +220,3 @@ showcaseUI <- function(ui) {
|
||||
showcaseBody(ui)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
151
R/test-server.R
151
R/test-server.R
@@ -1,19 +1,14 @@
|
||||
#' @noRd
|
||||
isModuleServer <- function(x) {
|
||||
is.function(x) && names(formals(x))[1] == "id"
|
||||
}
|
||||
|
||||
#' Reactive testing for Shiny server functions and modules
|
||||
#'
|
||||
#' A way to test the reactive interactions in Shiny applications. Reactive
|
||||
#' interactions are defined in the server function of applications and in
|
||||
#' modules.
|
||||
#' @param app The path to an application or module to test. In addition to
|
||||
#' paths, applications may be represented by any object suitable for coercion
|
||||
#' to an `appObj` by [`as.shiny.appobj`]. Application server functions must
|
||||
#' include a `session` argument in order to be tested. If `app` is `NULL` or
|
||||
#' not supplied, the nearest enclosing directory that is a Shiny app, starting
|
||||
#' with the current directory, is used.
|
||||
#' @param app A server function (i.e. a function with `input`, `output`,
|
||||
#' and `session`), or a module function (i.e. a function with first
|
||||
#' argument `id` that calls [moduleServer()].
|
||||
#'
|
||||
#' You can also provide an app, a path an app, or anything that
|
||||
#' [`as.shiny.appobj()`] can handle.
|
||||
#' @param expr Test code containing expectations. The objects from inside the
|
||||
#' server function environment will be made available in the environment of
|
||||
#' the test expression (this is done using a data mask with
|
||||
@@ -30,7 +25,19 @@ isModuleServer <- function(x) {
|
||||
#' @include mock-session.R
|
||||
#' @rdname testServer
|
||||
#' @examples
|
||||
#' server <- function(id, multiplier = 2, prefix = "I am ") {
|
||||
#' # Testing a server function ----------------------------------------------
|
||||
#' server <- function(input, output, session) {
|
||||
#' x <- reactive(input$a * input$b)
|
||||
#' }
|
||||
#'
|
||||
#' testServer(server, {
|
||||
#' session$setInputs(a = 2, b = 3)
|
||||
#' stopifnot(x() == 6)
|
||||
#' })
|
||||
#'
|
||||
#'
|
||||
#' # Testing a module --------------------------------------------------------
|
||||
#' myModuleServer <- function(id, multiplier = 2, prefix = "I am ") {
|
||||
#' moduleServer(id, function(input, output, session) {
|
||||
#' myreactive <- reactive({
|
||||
#' input$x * multiplier
|
||||
@@ -41,7 +48,7 @@ isModuleServer <- function(x) {
|
||||
#' })
|
||||
#' }
|
||||
#'
|
||||
#' testServer(server, args = list(multiplier = 2), {
|
||||
#' testServer(myModuleServer, args = list(multiplier = 2), {
|
||||
#' session$setInputs(x = 1)
|
||||
#' # You're also free to use third-party
|
||||
#' # testing packages like testthat:
|
||||
@@ -56,74 +63,94 @@ isModuleServer <- function(x) {
|
||||
#' })
|
||||
#' @export
|
||||
testServer <- function(app = NULL, expr, args = list(), session = MockShinySession$new()) {
|
||||
|
||||
require(shiny)
|
||||
|
||||
if (!is.null(getDefaultReactiveDomain()))
|
||||
stop("testServer() is for use only within tests and may not indirectly call itself.")
|
||||
|
||||
on.exit(if (!session$isClosed()) session$close(), add = TRUE)
|
||||
quosure <- rlang::enquo(expr)
|
||||
|
||||
on.exit(if (!session$isClosed()) session$close())
|
||||
|
||||
withMockContext <- function(expr) {
|
||||
isolate(
|
||||
withReactiveDomain(session, {
|
||||
withr::with_options(list(`shiny.allowoutputreads` = TRUE), {
|
||||
withLocalOptions({
|
||||
# Sets a cache for renderCachedPlot() with cache = "app" to use.
|
||||
shinyOptions("cache" = session$appcache)
|
||||
expr
|
||||
})
|
||||
})
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
if (isModuleServer(app)) {
|
||||
if (!("id" %in% names(args)))
|
||||
args[["id"]] <- session$genId()
|
||||
# app is presumed to be a module, and modules may take additional arguments,
|
||||
# so splice in any args.
|
||||
withMockContext(rlang::exec(app, !!!args))
|
||||
withMockContext(session, rlang::exec(app, !!!args))
|
||||
|
||||
# If app is a module, then we must use both the module function's immediate
|
||||
# environment and also its enclosing environment to construct the mask.
|
||||
parent_clone <- rlang::env_clone(parent.env(session$env))
|
||||
clone <- rlang::env_clone(session$env, parent_clone)
|
||||
mask <- rlang::new_data_mask(clone, parent_clone)
|
||||
withMockContext(rlang::eval_tidy(quosure, mask, rlang::caller_env()))
|
||||
} else {
|
||||
if (is.null(app)) {
|
||||
app <- findEnclosingApp(".")
|
||||
}
|
||||
|
||||
appobj <- as.shiny.appobj(app)
|
||||
if (!is.null(appobj$onStart))
|
||||
appobj$onStart()
|
||||
# Ensure appobj$onStop() is called, and the current directory is restored,
|
||||
# regardless of whether invoking the server function is successful.
|
||||
tryCatch({
|
||||
server <- appobj$serverFuncSource()
|
||||
if (! "session" %in% names(formals(server)))
|
||||
stop("Tested application server functions must declare input, output, and session arguments.")
|
||||
body(server) <- rlang::expr({
|
||||
session$setEnv(base::environment())
|
||||
!!body(server)
|
||||
})
|
||||
if (length(args))
|
||||
stop("Arguments were provided to a server function.")
|
||||
withMockContext(server(input = session$input, output = session$output, session = session))
|
||||
}, finally = {
|
||||
if (!is.null(appobj$onStop))
|
||||
appobj$onStop()
|
||||
})
|
||||
|
||||
# If app is a server, we use only the server function's immediate
|
||||
# environment to construct the mask.
|
||||
mask <- rlang::new_data_mask(rlang::env_clone(session$env))
|
||||
withMockContext(rlang::eval_tidy(quosure, mask, rlang::caller_env()))
|
||||
withMockContext(session, rlang::eval_tidy(quosure, mask, rlang::caller_env()))
|
||||
return(invisible())
|
||||
}
|
||||
|
||||
if (is.null(app)) {
|
||||
path <- findEnclosingApp(".")
|
||||
app <- shinyAppDir(path)
|
||||
} else if (isServer(app)) {
|
||||
app <- shinyApp(fluidPage(), app)
|
||||
} else {
|
||||
app <- as.shiny.appobj(app)
|
||||
}
|
||||
|
||||
if (!is.null(app$onStart))
|
||||
app$onStart()
|
||||
if (!is.null(app$onStop))
|
||||
on.exit(app$onStop(), add = TRUE)
|
||||
|
||||
server <- app$serverFuncSource()
|
||||
if (!"session" %in% names(formals(server)))
|
||||
stop("Tested application server functions must declare input, output, and session arguments.")
|
||||
if (length(args))
|
||||
stop("Arguments were provided to a server function.")
|
||||
|
||||
body(server) <- rlang::expr({
|
||||
session$setEnv(base::environment())
|
||||
!!body(server)
|
||||
})
|
||||
withMockContext(session,
|
||||
server(input = session$input, output = session$output, session = session)
|
||||
)
|
||||
|
||||
# # If app is a server, we use only the server function's immediate
|
||||
# # environment to construct the mask.
|
||||
mask <- rlang::new_data_mask(rlang::env_clone(session$env))
|
||||
withMockContext(session, {
|
||||
rlang::eval_tidy(quosure, mask, rlang::caller_env())
|
||||
})
|
||||
invisible()
|
||||
}
|
||||
|
||||
withMockContext <- function(session, expr) {
|
||||
isolate(
|
||||
withReactiveDomain(session, {
|
||||
withr::with_options(list(`shiny.allowoutputreads` = TRUE), {
|
||||
# Sets a cache for renderCachedPlot() with cache = "app" to use.
|
||||
shinyOptions("cache" = session$appcache)
|
||||
expr
|
||||
})
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
# Helpers -----------------------------------------------------------------
|
||||
|
||||
isModuleServer <- function(x) {
|
||||
is.function(x) && names(formals(x))[[1]] == "id"
|
||||
}
|
||||
|
||||
isServer <- function(x) {
|
||||
if (!is.function(x)) {
|
||||
return(FALSE)
|
||||
}
|
||||
|
||||
if (length(formals(x)) < 3) {
|
||||
return(FALSE)
|
||||
}
|
||||
|
||||
identical(names(formals(x))[1:3], c("input", "output", "session"))
|
||||
}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
#' Change the value of a text input on the client
|
||||
#'
|
||||
#' @template update-input
|
||||
#' @param value The value to set for the input object.
|
||||
#' @param placeholder The placeholder to set for the input object.
|
||||
#' @inheritParams textInput
|
||||
#'
|
||||
#' @seealso [textInput()]
|
||||
#'
|
||||
@@ -82,7 +81,7 @@ updateTextAreaInput <- updateTextInput
|
||||
#' Change the value of a checkbox input on the client
|
||||
#'
|
||||
#' @template update-input
|
||||
#' @param value The value to set for the input object.
|
||||
#' @inheritParams checkboxInput
|
||||
#'
|
||||
#' @seealso [checkboxInput()]
|
||||
#'
|
||||
@@ -116,8 +115,7 @@ updateCheckboxInput <- function(session, inputId, label = NULL, value = NULL) {
|
||||
#' Change the label or icon of an action button on the client
|
||||
#'
|
||||
#' @template update-input
|
||||
#' @param icon The icon to set for the input object. To remove the
|
||||
#' current icon, use `icon=character(0)`.
|
||||
#' @inheritParams actionButton
|
||||
#'
|
||||
#' @seealso [actionButton()]
|
||||
#'
|
||||
@@ -180,12 +178,7 @@ updateActionLink <- updateActionButton
|
||||
#' Change the value of a date input on the client
|
||||
#'
|
||||
#' @template update-input
|
||||
#' @param value The desired date value. Either a Date object, or a string in
|
||||
#' `yyyy-mm-dd` format. Supply `NA` to clear the date.
|
||||
#' @param min The minimum allowed date. Either a Date object, or a string in
|
||||
#' `yyyy-mm-dd` format.
|
||||
#' @param max The maximum allowed date. Either a Date object, or a string in
|
||||
#' `yyyy-mm-dd` format.
|
||||
#' @inheritParams dateInput
|
||||
#'
|
||||
#' @seealso [dateInput()]
|
||||
#'
|
||||
@@ -228,14 +221,7 @@ updateDateInput <- function(session, inputId, label = NULL, value = NULL,
|
||||
#' Change the start and end values of a date range input on the client
|
||||
#'
|
||||
#' @template update-input
|
||||
#' @param start The start date. Either a Date object, or a string in
|
||||
#' `yyyy-mm-dd` format. Supplying `NA` clears the start date.
|
||||
#' @param end The end date. Either a Date object, or a string in
|
||||
#' `yyyy-mm-dd` format. Supplying `NA` clears the end date.
|
||||
#' @param min The minimum allowed date. Either a Date object, or a string in
|
||||
#' `yyyy-mm-dd` format.
|
||||
#' @param max The maximum allowed date. Either a Date object, or a string in
|
||||
#' `yyyy-mm-dd` format.
|
||||
#' @inheritParams dateRangeInput
|
||||
#'
|
||||
#' @seealso [dateRangeInput()]
|
||||
#'
|
||||
@@ -290,7 +276,7 @@ updateDateRangeInput <- function(session, inputId, label = NULL,
|
||||
#' `shinyServer`.
|
||||
#' @param inputId The id of the `tabsetPanel`, `navlistPanel`,
|
||||
#' or `navbarPage` object.
|
||||
#' @param selected The name of the tab to make active.
|
||||
#' @inheritParams tabsetPanel
|
||||
#'
|
||||
#' @seealso [tabsetPanel()], [navlistPanel()],
|
||||
#' [navbarPage()]
|
||||
@@ -339,10 +325,7 @@ updateNavlistPanel <- updateTabsetPanel
|
||||
#' Change the value of a number input on the client
|
||||
#'
|
||||
#' @template update-input
|
||||
#' @param value The value to set for the input object.
|
||||
#' @param min Minimum value.
|
||||
#' @param max Maximum value.
|
||||
#' @param step Step size.
|
||||
#' @inheritParams numericInput
|
||||
#'
|
||||
#' @seealso [numericInput()]
|
||||
#'
|
||||
@@ -389,12 +372,7 @@ updateNumericInput <- function(session, inputId, label = NULL, value = NULL,
|
||||
#' Change the value of a slider input on the client.
|
||||
#'
|
||||
#' @template update-input
|
||||
#' @param value The value to set for the input object.
|
||||
#' @param min Minimum value.
|
||||
#' @param max Maximum value.
|
||||
#' @param step Step size.
|
||||
#' @param timeFormat Date and POSIXt formatting.
|
||||
#' @param timezone The timezone offset for POSIXt objects.
|
||||
#' @inheritParams sliderInput
|
||||
#'
|
||||
#' @seealso [sliderInput()]
|
||||
#'
|
||||
@@ -617,7 +595,7 @@ updateSelectInput <- function(session, inputId, label = NULL, choices = NULL,
|
||||
selected = NULL) {
|
||||
choices <- if (!is.null(choices)) choicesWithNames(choices)
|
||||
if (!is.null(selected)) selected <- as.character(selected)
|
||||
options <- if (!is.null(choices)) selectOptions(choices, selected)
|
||||
options <- if (!is.null(choices)) selectOptions(choices, selected, inputId, FALSE)
|
||||
message <- dropNulls(list(label = label, options = options, value = selected))
|
||||
session$sendInputMessage(inputId, message)
|
||||
}
|
||||
|
||||
@@ -1594,7 +1594,6 @@ URLencode <- function(value, reserved = FALSE) {
|
||||
# so that strings like "2016-08-9" are expanded to "2016-08-09"
|
||||
dateYMD <- function(date = NULL, argName = "value") {
|
||||
if (!length(date)) return(NULL)
|
||||
if (length(date) > 1) warning("Expected `", argName, "` to be of length 1.")
|
||||
tryCatch(date <- format(as.Date(date), "%Y-%m-%d"),
|
||||
error = function(e) {
|
||||
warning(
|
||||
|
||||
56
R/viewer.R
Normal file
56
R/viewer.R
Normal file
@@ -0,0 +1,56 @@
|
||||
|
||||
#' Viewer options
|
||||
#'
|
||||
#' Use these functions to control where the gadget is displayed in RStudio (or
|
||||
#' other R environments that emulate RStudio's viewer pane/dialog APIs). If
|
||||
#' viewer APIs are not available in the current R environment, then the gadget
|
||||
#' will be displayed in the system's default web browser (see
|
||||
#' [utils::browseURL()]).
|
||||
#'
|
||||
#' @return A function that takes a single `url` parameter, suitable for
|
||||
#' passing as the `viewer` argument of [runGadget()].
|
||||
#'
|
||||
#' @rdname viewer
|
||||
#' @name viewer
|
||||
NULL
|
||||
|
||||
#' @param minHeight The minimum height (in pixels) desired to show the gadget in
|
||||
#' the viewer pane. If a positive number, resize the pane if necessary to show
|
||||
#' at least that many pixels. If `NULL`, use the existing viewer pane
|
||||
#' size. If `"maximize"`, use the maximum available vertical space.
|
||||
#' @rdname viewer
|
||||
#' @export
|
||||
paneViewer <- function(minHeight = NULL) {
|
||||
viewer <- getOption("viewer")
|
||||
if (is.null(viewer)) {
|
||||
utils::browseURL
|
||||
} else {
|
||||
function(url) {
|
||||
viewer(url, minHeight)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#' @param dialogName The window title to display for the dialog.
|
||||
#' @param width,height The desired dialog width/height, in pixels.
|
||||
#' @rdname viewer
|
||||
#' @export
|
||||
dialogViewer <- function(dialogName, width = 600, height = 600) {
|
||||
viewer <- getOption("shinygadgets.showdialog")
|
||||
if (is.null(viewer)) {
|
||||
utils::browseURL
|
||||
} else {
|
||||
function(url) {
|
||||
viewer(dialogName, url, width = width, height = height)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#' @param browser See [utils::browseURL()].
|
||||
#' @rdname viewer
|
||||
#' @export
|
||||
browserViewer <- function(browser = getOption("browser")) {
|
||||
function(url) {
|
||||
utils::browseURL(url, browser = browser)
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<html{{ if (isTRUE(nzchar(lang))) paste0(" lang=\"", lang, "\"") }}>
|
||||
<head>
|
||||
{{ headContent() }}
|
||||
</head>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<head lang = "en">
|
||||
<title>An error has occurred</title>
|
||||
</head>
|
||||
|
||||
|
||||
@@ -1,28 +1,30 @@
|
||||
/*!
|
||||
* Datepicker for Bootstrap v1.6.4 (https://github.com/eternicode/bootstrap-datepicker)
|
||||
*
|
||||
* Copyright 2012 Stefan Petre
|
||||
* Improvements by Andrew Rowls
|
||||
* Licensed under the Apache License v2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
||||
*/
|
||||
.datepicker {
|
||||
border-radius: 4px;
|
||||
border-radius: 0.25rem;
|
||||
direction: ltr;
|
||||
}
|
||||
|
||||
.datepicker-inline {
|
||||
width: 220px;
|
||||
}
|
||||
.datepicker.datepicker-rtl {
|
||||
|
||||
.datepicker-rtl {
|
||||
direction: rtl;
|
||||
}
|
||||
.datepicker.datepicker-rtl table tr td span {
|
||||
|
||||
.datepicker-rtl.dropdown-menu {
|
||||
left: auto;
|
||||
}
|
||||
|
||||
.datepicker-rtl table tr td span {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.datepicker-dropdown {
|
||||
top: 0;
|
||||
left: 0;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.datepicker-dropdown:before {
|
||||
content: '';
|
||||
display: inline-block;
|
||||
@@ -33,6 +35,7 @@
|
||||
border-bottom-color: rgba(0, 0, 0, 0.2);
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.datepicker-dropdown:after {
|
||||
content: '';
|
||||
display: inline-block;
|
||||
@@ -42,34 +45,43 @@
|
||||
border-top: 0;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.datepicker-dropdown.datepicker-orient-left:before {
|
||||
left: 6px;
|
||||
}
|
||||
|
||||
.datepicker-dropdown.datepicker-orient-left:after {
|
||||
left: 7px;
|
||||
}
|
||||
|
||||
.datepicker-dropdown.datepicker-orient-right:before {
|
||||
right: 6px;
|
||||
}
|
||||
|
||||
.datepicker-dropdown.datepicker-orient-right:after {
|
||||
right: 7px;
|
||||
}
|
||||
|
||||
.datepicker-dropdown.datepicker-orient-bottom:before {
|
||||
top: -7px;
|
||||
}
|
||||
|
||||
.datepicker-dropdown.datepicker-orient-bottom:after {
|
||||
top: -6px;
|
||||
}
|
||||
|
||||
.datepicker-dropdown.datepicker-orient-top:before {
|
||||
bottom: -7px;
|
||||
border-bottom: 0;
|
||||
border-top: 7px solid rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.datepicker-dropdown.datepicker-orient-top:after {
|
||||
bottom: -6px;
|
||||
border-bottom: 0;
|
||||
border-top: 6px solid #fff;
|
||||
}
|
||||
|
||||
.datepicker table {
|
||||
margin: 0;
|
||||
-webkit-touch-callout: none;
|
||||
@@ -79,424 +91,352 @@
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
.datepicker table tr td,
|
||||
.datepicker table tr th {
|
||||
|
||||
.datepicker table tr td, .datepicker table tr th {
|
||||
text-align: center;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
border-radius: 4px;
|
||||
border: none;
|
||||
}
|
||||
.table-striped .datepicker table tr td,
|
||||
.table-striped .datepicker table tr th {
|
||||
|
||||
.table-striped .datepicker table tr td, .table-striped .datepicker table tr th {
|
||||
background-color: transparent;
|
||||
}
|
||||
.datepicker table tr td.old,
|
||||
.datepicker table tr td.new {
|
||||
color: #777777;
|
||||
|
||||
.datepicker table tr td.old, .datepicker table tr td.new {
|
||||
color: #6c757d;
|
||||
}
|
||||
.datepicker table tr td.day:hover,
|
||||
.datepicker table tr td.focused {
|
||||
background: #eeeeee;
|
||||
|
||||
.datepicker table tr td.day:hover, .datepicker table tr td.focused {
|
||||
color: #212529;
|
||||
background: #e9e9ea;
|
||||
cursor: pointer;
|
||||
}
|
||||
.datepicker table tr td.disabled,
|
||||
.datepicker table tr td.disabled:hover {
|
||||
|
||||
.datepicker table tr td.disabled, .datepicker table tr td.disabled:hover {
|
||||
background: none;
|
||||
color: #777777;
|
||||
color: #6c757d;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.datepicker table tr td.highlighted {
|
||||
color: #000;
|
||||
background-color: #d9edf7;
|
||||
border-color: #85c5e5;
|
||||
color: #212529;
|
||||
background-color: #d1ecf1;
|
||||
border-color: #83ccd9;
|
||||
border-radius: 0;
|
||||
}
|
||||
.datepicker table tr td.highlighted:focus,
|
||||
.datepicker table tr td.highlighted.focus {
|
||||
color: #000;
|
||||
background-color: #afd9ee;
|
||||
border-color: #298fc2;
|
||||
|
||||
.datepicker table tr td.highlighted:focus, .datepicker table tr td.highlighted.focus {
|
||||
color: #212529;
|
||||
background-color: #bfd8dd;
|
||||
border-color: #6aa2ad;
|
||||
}
|
||||
|
||||
.datepicker table tr td.highlighted:hover {
|
||||
color: #000;
|
||||
background-color: #afd9ee;
|
||||
border-color: #52addb;
|
||||
color: #212529;
|
||||
background-color: #79898d;
|
||||
border-color: #77b8c4;
|
||||
}
|
||||
.datepicker table tr td.highlighted:active,
|
||||
.datepicker table tr td.highlighted.active {
|
||||
color: #000;
|
||||
background-color: #afd9ee;
|
||||
border-color: #52addb;
|
||||
|
||||
.datepicker table tr td.highlighted:active, .datepicker table tr td.highlighted.active {
|
||||
color: #212529;
|
||||
background-color: #bfd8dd;
|
||||
border-color: #77b8c4;
|
||||
}
|
||||
.datepicker table tr td.highlighted:active:hover,
|
||||
.datepicker table tr td.highlighted.active:hover,
|
||||
.datepicker table tr td.highlighted:active:focus,
|
||||
.datepicker table tr td.highlighted.active:focus,
|
||||
.datepicker table tr td.highlighted:active.focus,
|
||||
.datepicker table tr td.highlighted.active.focus {
|
||||
color: #000;
|
||||
background-color: #91cbe8;
|
||||
border-color: #298fc2;
|
||||
|
||||
.datepicker table tr td.highlighted:active:hover, .datepicker table tr td.highlighted:active:focus, .datepicker table tr td.highlighted:active.focus, .datepicker table tr td.highlighted.active:hover, .datepicker table tr td.highlighted.active:focus, .datepicker table tr td.highlighted.active.focus {
|
||||
color: #212529;
|
||||
background-color: #b3cacf;
|
||||
border-color: #6aa2ad;
|
||||
}
|
||||
.datepicker table tr td.highlighted.disabled:hover,
|
||||
.datepicker table tr td.highlighted[disabled]:hover,
|
||||
|
||||
.datepicker table tr td.highlighted.disabled:hover, .datepicker table tr td.highlighted.disabled:focus, .datepicker table tr td.highlighted.disabled.focus, .datepicker table tr td.highlighted[disabled]:hover, .datepicker table tr td.highlighted[disabled]:focus, .datepicker table tr td.highlighted[disabled].focus,
|
||||
fieldset[disabled] .datepicker table tr td.highlighted:hover,
|
||||
.datepicker table tr td.highlighted.disabled:focus,
|
||||
.datepicker table tr td.highlighted[disabled]:focus,
|
||||
fieldset[disabled] .datepicker table tr td.highlighted:focus,
|
||||
.datepicker table tr td.highlighted.disabled.focus,
|
||||
.datepicker table tr td.highlighted[disabled].focus,
|
||||
fieldset[disabled] .datepicker table tr td.highlighted.focus {
|
||||
background-color: #d9edf7;
|
||||
border-color: #85c5e5;
|
||||
background-color: #d1ecf1;
|
||||
border-color: #83ccd9;
|
||||
}
|
||||
|
||||
.datepicker table tr td.highlighted.focused {
|
||||
background: #afd9ee;
|
||||
background: #aadce5;
|
||||
}
|
||||
.datepicker table tr td.highlighted.disabled,
|
||||
.datepicker table tr td.highlighted.disabled:active {
|
||||
background: #d9edf7;
|
||||
color: #777777;
|
||||
|
||||
.datepicker table tr td.highlighted.disabled, .datepicker table tr td.highlighted.disabled:active {
|
||||
background: #d1ecf1;
|
||||
color: #6c757d;
|
||||
}
|
||||
|
||||
.datepicker table tr td.today {
|
||||
color: #000;
|
||||
color: #212529;
|
||||
background-color: #ffdb99;
|
||||
border-color: #ffb733;
|
||||
}
|
||||
.datepicker table tr td.today:focus,
|
||||
.datepicker table tr td.today.focus {
|
||||
color: #000;
|
||||
background-color: #ffc966;
|
||||
border-color: #b37400;
|
||||
|
||||
.datepicker table tr td.today:focus, .datepicker table tr td.today.focus {
|
||||
color: #212529;
|
||||
background-color: #e9c98e;
|
||||
border-color: #c89331;
|
||||
}
|
||||
|
||||
.datepicker table tr td.today:hover {
|
||||
color: #000;
|
||||
background-color: #ffc966;
|
||||
border-color: #f59e00;
|
||||
color: #212529;
|
||||
background-color: #908061;
|
||||
border-color: #e4a532;
|
||||
}
|
||||
.datepicker table tr td.today:active,
|
||||
.datepicker table tr td.today.active {
|
||||
color: #000;
|
||||
background-color: #ffc966;
|
||||
border-color: #f59e00;
|
||||
|
||||
.datepicker table tr td.today:active, .datepicker table tr td.today.active {
|
||||
color: #212529;
|
||||
background-color: #e9c98e;
|
||||
border-color: #e4a532;
|
||||
}
|
||||
.datepicker table tr td.today:active:hover,
|
||||
.datepicker table tr td.today.active:hover,
|
||||
.datepicker table tr td.today:active:focus,
|
||||
.datepicker table tr td.today.active:focus,
|
||||
.datepicker table tr td.today:active.focus,
|
||||
.datepicker table tr td.today.active.focus {
|
||||
color: #000;
|
||||
background-color: #ffbc42;
|
||||
border-color: #b37400;
|
||||
|
||||
.datepicker table tr td.today:active:hover, .datepicker table tr td.today:active:focus, .datepicker table tr td.today:active.focus, .datepicker table tr td.today.active:hover, .datepicker table tr td.today.active:focus, .datepicker table tr td.today.active.focus {
|
||||
color: #212529;
|
||||
background-color: #d9bc86;
|
||||
border-color: #c89331;
|
||||
}
|
||||
.datepicker table tr td.today.disabled:hover,
|
||||
.datepicker table tr td.today[disabled]:hover,
|
||||
|
||||
.datepicker table tr td.today.disabled:hover, .datepicker table tr td.today.disabled:focus, .datepicker table tr td.today.disabled.focus, .datepicker table tr td.today[disabled]:hover, .datepicker table tr td.today[disabled]:focus, .datepicker table tr td.today[disabled].focus,
|
||||
fieldset[disabled] .datepicker table tr td.today:hover,
|
||||
.datepicker table tr td.today.disabled:focus,
|
||||
.datepicker table tr td.today[disabled]:focus,
|
||||
fieldset[disabled] .datepicker table tr td.today:focus,
|
||||
.datepicker table tr td.today.disabled.focus,
|
||||
.datepicker table tr td.today[disabled].focus,
|
||||
fieldset[disabled] .datepicker table tr td.today.focus {
|
||||
background-color: #ffdb99;
|
||||
border-color: #ffb733;
|
||||
}
|
||||
|
||||
.datepicker table tr td.today.focused {
|
||||
background: #ffc966;
|
||||
}
|
||||
.datepicker table tr td.today.disabled,
|
||||
.datepicker table tr td.today.disabled:active {
|
||||
|
||||
.datepicker table tr td.today.disabled, .datepicker table tr td.today.disabled:active {
|
||||
background: #ffdb99;
|
||||
color: #777777;
|
||||
color: #6c757d;
|
||||
}
|
||||
|
||||
.datepicker table tr td.range {
|
||||
color: #000;
|
||||
background-color: #eeeeee;
|
||||
border-color: #bbbbbb;
|
||||
color: #212529;
|
||||
background-color: #e9e9ea;
|
||||
border-color: #b5b5b8;
|
||||
border-radius: 0;
|
||||
}
|
||||
.datepicker table tr td.range:focus,
|
||||
.datepicker table tr td.range.focus {
|
||||
color: #000;
|
||||
background-color: #d5d5d5;
|
||||
border-color: #7c7c7c;
|
||||
|
||||
.datepicker table tr td.range:focus, .datepicker table tr td.range.focus {
|
||||
color: #212529;
|
||||
background-color: #d5d5d7;
|
||||
border-color: #909194;
|
||||
}
|
||||
|
||||
.datepicker table tr td.range:hover {
|
||||
color: #000;
|
||||
background-color: #d5d5d5;
|
||||
border-color: #9d9d9d;
|
||||
color: #212529;
|
||||
background-color: #85878a;
|
||||
border-color: #a3a4a7;
|
||||
}
|
||||
.datepicker table tr td.range:active,
|
||||
.datepicker table tr td.range.active {
|
||||
color: #000;
|
||||
background-color: #d5d5d5;
|
||||
border-color: #9d9d9d;
|
||||
|
||||
.datepicker table tr td.range:active, .datepicker table tr td.range.active {
|
||||
color: #212529;
|
||||
background-color: #d5d5d7;
|
||||
border-color: #a3a4a7;
|
||||
}
|
||||
.datepicker table tr td.range:active:hover,
|
||||
.datepicker table tr td.range.active:hover,
|
||||
.datepicker table tr td.range:active:focus,
|
||||
.datepicker table tr td.range.active:focus,
|
||||
.datepicker table tr td.range:active.focus,
|
||||
.datepicker table tr td.range.active.focus {
|
||||
color: #000;
|
||||
background-color: #c3c3c3;
|
||||
border-color: #7c7c7c;
|
||||
|
||||
.datepicker table tr td.range:active:hover, .datepicker table tr td.range:active:focus, .datepicker table tr td.range:active.focus, .datepicker table tr td.range.active:hover, .datepicker table tr td.range.active:focus, .datepicker table tr td.range.active.focus {
|
||||
color: #212529;
|
||||
background-color: #c7c8c9;
|
||||
border-color: #909194;
|
||||
}
|
||||
.datepicker table tr td.range.disabled:hover,
|
||||
.datepicker table tr td.range[disabled]:hover,
|
||||
|
||||
.datepicker table tr td.range.disabled:hover, .datepicker table tr td.range.disabled:focus, .datepicker table tr td.range.disabled.focus, .datepicker table tr td.range[disabled]:hover, .datepicker table tr td.range[disabled]:focus, .datepicker table tr td.range[disabled].focus,
|
||||
fieldset[disabled] .datepicker table tr td.range:hover,
|
||||
.datepicker table tr td.range.disabled:focus,
|
||||
.datepicker table tr td.range[disabled]:focus,
|
||||
fieldset[disabled] .datepicker table tr td.range:focus,
|
||||
.datepicker table tr td.range.disabled.focus,
|
||||
.datepicker table tr td.range[disabled].focus,
|
||||
fieldset[disabled] .datepicker table tr td.range.focus {
|
||||
background-color: #eeeeee;
|
||||
border-color: #bbbbbb;
|
||||
background-color: #e9e9ea;
|
||||
border-color: #b5b5b8;
|
||||
}
|
||||
|
||||
.datepicker table tr td.range.focused {
|
||||
background: #d5d5d5;
|
||||
background: #cfcfd1;
|
||||
}
|
||||
.datepicker table tr td.range.disabled,
|
||||
.datepicker table tr td.range.disabled:active {
|
||||
background: #eeeeee;
|
||||
color: #777777;
|
||||
|
||||
.datepicker table tr td.range.disabled, .datepicker table tr td.range.disabled:active {
|
||||
background: #e9e9ea;
|
||||
color: #6c757d;
|
||||
}
|
||||
|
||||
.datepicker table tr td.range.highlighted {
|
||||
color: #000;
|
||||
background-color: #e4eef3;
|
||||
border-color: #9dc1d3;
|
||||
color: #212529;
|
||||
background-color: #ddebee;
|
||||
border-color: #99c3cc;
|
||||
}
|
||||
.datepicker table tr td.range.highlighted:focus,
|
||||
.datepicker table tr td.range.highlighted.focus {
|
||||
color: #000;
|
||||
background-color: #c1d7e3;
|
||||
border-color: #4b88a6;
|
||||
|
||||
.datepicker table tr td.range.highlighted:focus, .datepicker table tr td.range.highlighted.focus {
|
||||
color: #212529;
|
||||
background-color: #cad7da;
|
||||
border-color: #7b9ca3;
|
||||
}
|
||||
|
||||
.datepicker table tr td.range.highlighted:hover {
|
||||
color: #000;
|
||||
background-color: #c1d7e3;
|
||||
border-color: #73a6c0;
|
||||
color: #212529;
|
||||
background-color: #7f888c;
|
||||
border-color: #8bb0b8;
|
||||
}
|
||||
.datepicker table tr td.range.highlighted:active,
|
||||
.datepicker table tr td.range.highlighted.active {
|
||||
color: #000;
|
||||
background-color: #c1d7e3;
|
||||
border-color: #73a6c0;
|
||||
|
||||
.datepicker table tr td.range.highlighted:active, .datepicker table tr td.range.highlighted.active {
|
||||
color: #212529;
|
||||
background-color: #cad7da;
|
||||
border-color: #8bb0b8;
|
||||
}
|
||||
.datepicker table tr td.range.highlighted:active:hover,
|
||||
.datepicker table tr td.range.highlighted.active:hover,
|
||||
.datepicker table tr td.range.highlighted:active:focus,
|
||||
.datepicker table tr td.range.highlighted.active:focus,
|
||||
.datepicker table tr td.range.highlighted:active.focus,
|
||||
.datepicker table tr td.range.highlighted.active.focus {
|
||||
color: #000;
|
||||
background-color: #a8c8d8;
|
||||
border-color: #4b88a6;
|
||||
|
||||
.datepicker table tr td.range.highlighted:active:hover, .datepicker table tr td.range.highlighted:active:focus, .datepicker table tr td.range.highlighted:active.focus, .datepicker table tr td.range.highlighted.active:hover, .datepicker table tr td.range.highlighted.active:focus, .datepicker table tr td.range.highlighted.active.focus {
|
||||
color: #212529;
|
||||
background-color: #bdc9cd;
|
||||
border-color: #7b9ca3;
|
||||
}
|
||||
.datepicker table tr td.range.highlighted.disabled:hover,
|
||||
.datepicker table tr td.range.highlighted[disabled]:hover,
|
||||
|
||||
.datepicker table tr td.range.highlighted.disabled:hover, .datepicker table tr td.range.highlighted.disabled:focus, .datepicker table tr td.range.highlighted.disabled.focus, .datepicker table tr td.range.highlighted[disabled]:hover, .datepicker table tr td.range.highlighted[disabled]:focus, .datepicker table tr td.range.highlighted[disabled].focus,
|
||||
fieldset[disabled] .datepicker table tr td.range.highlighted:hover,
|
||||
.datepicker table tr td.range.highlighted.disabled:focus,
|
||||
.datepicker table tr td.range.highlighted[disabled]:focus,
|
||||
fieldset[disabled] .datepicker table tr td.range.highlighted:focus,
|
||||
.datepicker table tr td.range.highlighted.disabled.focus,
|
||||
.datepicker table tr td.range.highlighted[disabled].focus,
|
||||
fieldset[disabled] .datepicker table tr td.range.highlighted.focus {
|
||||
background-color: #e4eef3;
|
||||
border-color: #9dc1d3;
|
||||
background-color: #ddebee;
|
||||
border-color: #99c3cc;
|
||||
}
|
||||
|
||||
.datepicker table tr td.range.highlighted.focused {
|
||||
background: #c1d7e3;
|
||||
background: #bbd7dd;
|
||||
}
|
||||
.datepicker table tr td.range.highlighted.disabled,
|
||||
.datepicker table tr td.range.highlighted.disabled:active {
|
||||
background: #e4eef3;
|
||||
color: #777777;
|
||||
|
||||
.datepicker table tr td.range.highlighted.disabled, .datepicker table tr td.range.highlighted.disabled:active {
|
||||
background: #ddebee;
|
||||
color: #6c757d;
|
||||
}
|
||||
|
||||
.datepicker table tr td.range.today {
|
||||
color: #000;
|
||||
background-color: #f7ca77;
|
||||
border-color: #f1a417;
|
||||
color: #212529;
|
||||
background-color: #f4c775;
|
||||
border-color: #eca117;
|
||||
}
|
||||
.datepicker table tr td.range.today:focus,
|
||||
.datepicker table tr td.range.today.focus {
|
||||
color: #000;
|
||||
background-color: #f4b747;
|
||||
border-color: #815608;
|
||||
|
||||
.datepicker table tr td.range.today:focus, .datepicker table tr td.range.today.focus {
|
||||
color: #212529;
|
||||
background-color: #dfb76d;
|
||||
border-color: #ba821b;
|
||||
}
|
||||
|
||||
.datepicker table tr td.range.today:hover {
|
||||
color: #000;
|
||||
background-color: #f4b747;
|
||||
border-color: #bf800c;
|
||||
color: #212529;
|
||||
background-color: #8b764f;
|
||||
border-color: #d49219;
|
||||
}
|
||||
.datepicker table tr td.range.today:active,
|
||||
.datepicker table tr td.range.today.active {
|
||||
color: #000;
|
||||
background-color: #f4b747;
|
||||
border-color: #bf800c;
|
||||
|
||||
.datepicker table tr td.range.today:active, .datepicker table tr td.range.today.active {
|
||||
color: #212529;
|
||||
background-color: #dfb76d;
|
||||
border-color: #d49219;
|
||||
}
|
||||
.datepicker table tr td.range.today:active:hover,
|
||||
.datepicker table tr td.range.today.active:hover,
|
||||
.datepicker table tr td.range.today:active:focus,
|
||||
.datepicker table tr td.range.today.active:focus,
|
||||
.datepicker table tr td.range.today:active.focus,
|
||||
.datepicker table tr td.range.today.active.focus {
|
||||
color: #000;
|
||||
background-color: #f2aa25;
|
||||
border-color: #815608;
|
||||
|
||||
.datepicker table tr td.range.today:active:hover, .datepicker table tr td.range.today:active:focus, .datepicker table tr td.range.today:active.focus, .datepicker table tr td.range.today.active:hover, .datepicker table tr td.range.today.active:focus, .datepicker table tr td.range.today.active.focus {
|
||||
color: #212529;
|
||||
background-color: #d0ab68;
|
||||
border-color: #ba821b;
|
||||
}
|
||||
.datepicker table tr td.range.today.disabled:hover,
|
||||
.datepicker table tr td.range.today[disabled]:hover,
|
||||
|
||||
.datepicker table tr td.range.today.disabled:hover, .datepicker table tr td.range.today.disabled:focus, .datepicker table tr td.range.today.disabled.focus, .datepicker table tr td.range.today[disabled]:hover, .datepicker table tr td.range.today[disabled]:focus, .datepicker table tr td.range.today[disabled].focus,
|
||||
fieldset[disabled] .datepicker table tr td.range.today:hover,
|
||||
.datepicker table tr td.range.today.disabled:focus,
|
||||
.datepicker table tr td.range.today[disabled]:focus,
|
||||
fieldset[disabled] .datepicker table tr td.range.today:focus,
|
||||
.datepicker table tr td.range.today.disabled.focus,
|
||||
.datepicker table tr td.range.today[disabled].focus,
|
||||
fieldset[disabled] .datepicker table tr td.range.today.focus {
|
||||
background-color: #f7ca77;
|
||||
border-color: #f1a417;
|
||||
background-color: #f4c775;
|
||||
border-color: #eca117;
|
||||
}
|
||||
.datepicker table tr td.range.today.disabled,
|
||||
.datepicker table tr td.range.today.disabled:active {
|
||||
background: #f7ca77;
|
||||
color: #777777;
|
||||
|
||||
.datepicker table tr td.range.today.disabled, .datepicker table tr td.range.today.disabled:active {
|
||||
background: #f4c775;
|
||||
color: #6c757d;
|
||||
}
|
||||
.datepicker table tr td.selected,
|
||||
.datepicker table tr td.selected.highlighted {
|
||||
|
||||
.datepicker table tr td.selected, .datepicker table tr td.selected.highlighted {
|
||||
color: #fff;
|
||||
background-color: #777777;
|
||||
border-color: #555555;
|
||||
background-color: #898b8d;
|
||||
border-color: #6b6e71;
|
||||
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
.datepicker table tr td.selected:focus,
|
||||
.datepicker table tr td.selected.highlighted:focus,
|
||||
.datepicker table tr td.selected.focus,
|
||||
.datepicker table tr td.selected.highlighted.focus {
|
||||
|
||||
.datepicker table tr td.selected:focus, .datepicker table tr td.selected.focus, .datepicker table tr td.selected.highlighted:focus, .datepicker table tr td.selected.highlighted.focus {
|
||||
color: #fff;
|
||||
background-color: #5e5e5e;
|
||||
border-color: #161616;
|
||||
background-color: #959798;
|
||||
border-color: #909295;
|
||||
}
|
||||
.datepicker table tr td.selected:hover,
|
||||
.datepicker table tr td.selected.highlighted:hover {
|
||||
|
||||
.datepicker table tr td.selected:hover, .datepicker table tr td.selected.highlighted:hover {
|
||||
color: #fff;
|
||||
background-color: #5e5e5e;
|
||||
border-color: #373737;
|
||||
background-color: #c4c5c6;
|
||||
border-color: #7d7f82;
|
||||
}
|
||||
.datepicker table tr td.selected:active,
|
||||
.datepicker table tr td.selected.highlighted:active,
|
||||
.datepicker table tr td.selected.active,
|
||||
.datepicker table tr td.selected.highlighted.active {
|
||||
|
||||
.datepicker table tr td.selected:active, .datepicker table tr td.selected.active, .datepicker table tr td.selected.highlighted:active, .datepicker table tr td.selected.highlighted.active {
|
||||
color: #fff;
|
||||
background-color: #5e5e5e;
|
||||
border-color: #373737;
|
||||
background-color: #959798;
|
||||
border-color: #7d7f82;
|
||||
}
|
||||
.datepicker table tr td.selected:active:hover,
|
||||
.datepicker table tr td.selected.highlighted:active:hover,
|
||||
.datepicker table tr td.selected.active:hover,
|
||||
.datepicker table tr td.selected.highlighted.active:hover,
|
||||
.datepicker table tr td.selected:active:focus,
|
||||
.datepicker table tr td.selected.highlighted:active:focus,
|
||||
.datepicker table tr td.selected.active:focus,
|
||||
.datepicker table tr td.selected.highlighted.active:focus,
|
||||
.datepicker table tr td.selected:active.focus,
|
||||
.datepicker table tr td.selected.highlighted:active.focus,
|
||||
.datepicker table tr td.selected.active.focus,
|
||||
.datepicker table tr td.selected.highlighted.active.focus {
|
||||
|
||||
.datepicker table tr td.selected:active:hover, .datepicker table tr td.selected:active:focus, .datepicker table tr td.selected:active.focus, .datepicker table tr td.selected.active:hover, .datepicker table tr td.selected.active:focus, .datepicker table tr td.selected.active.focus, .datepicker table tr td.selected.highlighted:active:hover, .datepicker table tr td.selected.highlighted:active:focus, .datepicker table tr td.selected.highlighted:active.focus, .datepicker table tr td.selected.highlighted.active:hover, .datepicker table tr td.selected.highlighted.active:focus, .datepicker table tr td.selected.highlighted.active.focus {
|
||||
color: #fff;
|
||||
background-color: #4c4c4c;
|
||||
border-color: #161616;
|
||||
background-color: #9d9fa0;
|
||||
border-color: #909295;
|
||||
}
|
||||
.datepicker table tr td.selected.disabled:hover,
|
||||
.datepicker table tr td.selected.highlighted.disabled:hover,
|
||||
.datepicker table tr td.selected[disabled]:hover,
|
||||
.datepicker table tr td.selected.highlighted[disabled]:hover,
|
||||
|
||||
.datepicker table tr td.selected.disabled:hover, .datepicker table tr td.selected.disabled:focus, .datepicker table tr td.selected.disabled.focus, .datepicker table tr td.selected[disabled]:hover, .datepicker table tr td.selected[disabled]:focus, .datepicker table tr td.selected[disabled].focus,
|
||||
fieldset[disabled] .datepicker table tr td.selected:hover,
|
||||
fieldset[disabled] .datepicker table tr td.selected.highlighted:hover,
|
||||
.datepicker table tr td.selected.disabled:focus,
|
||||
.datepicker table tr td.selected.highlighted.disabled:focus,
|
||||
.datepicker table tr td.selected[disabled]:focus,
|
||||
.datepicker table tr td.selected.highlighted[disabled]:focus,
|
||||
fieldset[disabled] .datepicker table tr td.selected:focus,
|
||||
fieldset[disabled] .datepicker table tr td.selected.focus, .datepicker table tr td.selected.highlighted.disabled:hover, .datepicker table tr td.selected.highlighted.disabled:focus, .datepicker table tr td.selected.highlighted.disabled.focus, .datepicker table tr td.selected.highlighted[disabled]:hover, .datepicker table tr td.selected.highlighted[disabled]:focus, .datepicker table tr td.selected.highlighted[disabled].focus,
|
||||
fieldset[disabled] .datepicker table tr td.selected.highlighted:hover,
|
||||
fieldset[disabled] .datepicker table tr td.selected.highlighted:focus,
|
||||
.datepicker table tr td.selected.disabled.focus,
|
||||
.datepicker table tr td.selected.highlighted.disabled.focus,
|
||||
.datepicker table tr td.selected[disabled].focus,
|
||||
.datepicker table tr td.selected.highlighted[disabled].focus,
|
||||
fieldset[disabled] .datepicker table tr td.selected.focus,
|
||||
fieldset[disabled] .datepicker table tr td.selected.highlighted.focus {
|
||||
background-color: #777777;
|
||||
border-color: #555555;
|
||||
background-color: #898b8d;
|
||||
border-color: #6b6e71;
|
||||
}
|
||||
.datepicker table tr td.active,
|
||||
.datepicker table tr td.active.highlighted {
|
||||
|
||||
.datepicker table tr td.active, .datepicker table tr td.active.highlighted {
|
||||
color: #fff;
|
||||
background-color: #337ab7;
|
||||
border-color: #2e6da4;
|
||||
background-color: #007bff;
|
||||
border-color: #0277f4;
|
||||
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
.datepicker table tr td.active:focus,
|
||||
.datepicker table tr td.active.highlighted:focus,
|
||||
.datepicker table tr td.active.focus,
|
||||
.datepicker table tr td.active.highlighted.focus {
|
||||
|
||||
.datepicker table tr td.active:focus, .datepicker table tr td.active.focus, .datepicker table tr td.active.highlighted:focus, .datepicker table tr td.active.highlighted.focus {
|
||||
color: #fff;
|
||||
background-color: #286090;
|
||||
border-color: #122b40;
|
||||
background-color: #1a88ff;
|
||||
border-color: #4199f7;
|
||||
}
|
||||
.datepicker table tr td.active:hover,
|
||||
.datepicker table tr td.active.highlighted:hover {
|
||||
|
||||
.datepicker table tr td.active:hover, .datepicker table tr td.active.highlighted:hover {
|
||||
color: #fff;
|
||||
background-color: #286090;
|
||||
border-color: #204d74;
|
||||
background-color: #80bdff;
|
||||
border-color: #2087f5;
|
||||
}
|
||||
.datepicker table tr td.active:active,
|
||||
.datepicker table tr td.active.highlighted:active,
|
||||
.datepicker table tr td.active.active,
|
||||
.datepicker table tr td.active.highlighted.active {
|
||||
|
||||
.datepicker table tr td.active:active, .datepicker table tr td.active.active, .datepicker table tr td.active.highlighted:active, .datepicker table tr td.active.highlighted.active {
|
||||
color: #fff;
|
||||
background-color: #286090;
|
||||
border-color: #204d74;
|
||||
background-color: #1a88ff;
|
||||
border-color: #2087f5;
|
||||
}
|
||||
.datepicker table tr td.active:active:hover,
|
||||
.datepicker table tr td.active.highlighted:active:hover,
|
||||
.datepicker table tr td.active.active:hover,
|
||||
.datepicker table tr td.active.highlighted.active:hover,
|
||||
.datepicker table tr td.active:active:focus,
|
||||
.datepicker table tr td.active.highlighted:active:focus,
|
||||
.datepicker table tr td.active.active:focus,
|
||||
.datepicker table tr td.active.highlighted.active:focus,
|
||||
.datepicker table tr td.active:active.focus,
|
||||
.datepicker table tr td.active.highlighted:active.focus,
|
||||
.datepicker table tr td.active.active.focus,
|
||||
.datepicker table tr td.active.highlighted.active.focus {
|
||||
|
||||
.datepicker table tr td.active:active:hover, .datepicker table tr td.active:active:focus, .datepicker table tr td.active:active.focus, .datepicker table tr td.active.active:hover, .datepicker table tr td.active.active:focus, .datepicker table tr td.active.active.focus, .datepicker table tr td.active.highlighted:active:hover, .datepicker table tr td.active.highlighted:active:focus, .datepicker table tr td.active.highlighted:active.focus, .datepicker table tr td.active.highlighted.active:hover, .datepicker table tr td.active.highlighted.active:focus, .datepicker table tr td.active.highlighted.active.focus {
|
||||
color: #fff;
|
||||
background-color: #204d74;
|
||||
border-color: #122b40;
|
||||
background-color: #2b91ff;
|
||||
border-color: #4199f7;
|
||||
}
|
||||
.datepicker table tr td.active.disabled:hover,
|
||||
.datepicker table tr td.active.highlighted.disabled:hover,
|
||||
.datepicker table tr td.active[disabled]:hover,
|
||||
.datepicker table tr td.active.highlighted[disabled]:hover,
|
||||
|
||||
.datepicker table tr td.active.disabled:hover, .datepicker table tr td.active.disabled:focus, .datepicker table tr td.active.disabled.focus, .datepicker table tr td.active[disabled]:hover, .datepicker table tr td.active[disabled]:focus, .datepicker table tr td.active[disabled].focus,
|
||||
fieldset[disabled] .datepicker table tr td.active:hover,
|
||||
fieldset[disabled] .datepicker table tr td.active.highlighted:hover,
|
||||
.datepicker table tr td.active.disabled:focus,
|
||||
.datepicker table tr td.active.highlighted.disabled:focus,
|
||||
.datepicker table tr td.active[disabled]:focus,
|
||||
.datepicker table tr td.active.highlighted[disabled]:focus,
|
||||
fieldset[disabled] .datepicker table tr td.active:focus,
|
||||
fieldset[disabled] .datepicker table tr td.active.focus, .datepicker table tr td.active.highlighted.disabled:hover, .datepicker table tr td.active.highlighted.disabled:focus, .datepicker table tr td.active.highlighted.disabled.focus, .datepicker table tr td.active.highlighted[disabled]:hover, .datepicker table tr td.active.highlighted[disabled]:focus, .datepicker table tr td.active.highlighted[disabled].focus,
|
||||
fieldset[disabled] .datepicker table tr td.active.highlighted:hover,
|
||||
fieldset[disabled] .datepicker table tr td.active.highlighted:focus,
|
||||
.datepicker table tr td.active.disabled.focus,
|
||||
.datepicker table tr td.active.highlighted.disabled.focus,
|
||||
.datepicker table tr td.active[disabled].focus,
|
||||
.datepicker table tr td.active.highlighted[disabled].focus,
|
||||
fieldset[disabled] .datepicker table tr td.active.focus,
|
||||
fieldset[disabled] .datepicker table tr td.active.highlighted.focus {
|
||||
background-color: #337ab7;
|
||||
border-color: #2e6da4;
|
||||
background-color: #007bff;
|
||||
border-color: #0277f4;
|
||||
}
|
||||
|
||||
.datepicker table tr td span {
|
||||
display: block;
|
||||
width: 23%;
|
||||
@@ -507,172 +447,127 @@ fieldset[disabled] .datepicker table tr td.active.highlighted.focus {
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.datepicker table tr td span:hover,
|
||||
.datepicker table tr td span.focused {
|
||||
background: #eeeeee;
|
||||
|
||||
.datepicker table tr td span:hover, .datepicker table tr td span.focused {
|
||||
color: #212529;
|
||||
background: #e9e9ea;
|
||||
}
|
||||
.datepicker table tr td span.disabled,
|
||||
.datepicker table tr td span.disabled:hover {
|
||||
|
||||
.datepicker table tr td span.disabled, .datepicker table tr td span.disabled:hover {
|
||||
background: none;
|
||||
color: #777777;
|
||||
color: #6c757d;
|
||||
cursor: default;
|
||||
}
|
||||
.datepicker table tr td span.active,
|
||||
.datepicker table tr td span.active:hover,
|
||||
.datepicker table tr td span.active.disabled,
|
||||
.datepicker table tr td span.active.disabled:hover {
|
||||
|
||||
.datepicker table tr td span.active, .datepicker table tr td span.active:hover, .datepicker table tr td span.active.disabled, .datepicker table tr td span.active.disabled:hover {
|
||||
color: #fff;
|
||||
background-color: #337ab7;
|
||||
border-color: #2e6da4;
|
||||
background-color: #007bff;
|
||||
border-color: #0277f4;
|
||||
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
.datepicker table tr td span.active:focus,
|
||||
.datepicker table tr td span.active:hover:focus,
|
||||
.datepicker table tr td span.active.disabled:focus,
|
||||
.datepicker table tr td span.active.disabled:hover:focus,
|
||||
.datepicker table tr td span.active.focus,
|
||||
.datepicker table tr td span.active:hover.focus,
|
||||
.datepicker table tr td span.active.disabled.focus,
|
||||
.datepicker table tr td span.active.disabled:hover.focus {
|
||||
|
||||
.datepicker table tr td span.active:focus, .datepicker table tr td span.active.focus, .datepicker table tr td span.active:hover:focus, .datepicker table tr td span.active:hover.focus, .datepicker table tr td span.active.disabled:focus, .datepicker table tr td span.active.disabled.focus, .datepicker table tr td span.active.disabled:hover:focus, .datepicker table tr td span.active.disabled:hover.focus {
|
||||
color: #fff;
|
||||
background-color: #286090;
|
||||
border-color: #122b40;
|
||||
background-color: #1a88ff;
|
||||
border-color: #4199f7;
|
||||
}
|
||||
.datepicker table tr td span.active:hover,
|
||||
.datepicker table tr td span.active:hover:hover,
|
||||
.datepicker table tr td span.active.disabled:hover,
|
||||
.datepicker table tr td span.active.disabled:hover:hover {
|
||||
|
||||
.datepicker table tr td span.active:hover, .datepicker table tr td span.active:hover:hover, .datepicker table tr td span.active.disabled:hover, .datepicker table tr td span.active.disabled:hover:hover {
|
||||
color: #fff;
|
||||
background-color: #286090;
|
||||
border-color: #204d74;
|
||||
background-color: #80bdff;
|
||||
border-color: #2087f5;
|
||||
}
|
||||
.datepicker table tr td span.active:active,
|
||||
.datepicker table tr td span.active:hover:active,
|
||||
.datepicker table tr td span.active.disabled:active,
|
||||
.datepicker table tr td span.active.disabled:hover:active,
|
||||
.datepicker table tr td span.active.active,
|
||||
.datepicker table tr td span.active:hover.active,
|
||||
.datepicker table tr td span.active.disabled.active,
|
||||
.datepicker table tr td span.active.disabled:hover.active {
|
||||
|
||||
.datepicker table tr td span.active:active, .datepicker table tr td span.active.active, .datepicker table tr td span.active:hover:active, .datepicker table tr td span.active:hover.active, .datepicker table tr td span.active.disabled:active, .datepicker table tr td span.active.disabled.active, .datepicker table tr td span.active.disabled:hover:active, .datepicker table tr td span.active.disabled:hover.active {
|
||||
color: #fff;
|
||||
background-color: #286090;
|
||||
border-color: #204d74;
|
||||
background-color: #1a88ff;
|
||||
border-color: #2087f5;
|
||||
}
|
||||
.datepicker table tr td span.active:active:hover,
|
||||
.datepicker table tr td span.active:hover:active:hover,
|
||||
.datepicker table tr td span.active.disabled:active:hover,
|
||||
.datepicker table tr td span.active.disabled:hover:active:hover,
|
||||
.datepicker table tr td span.active.active:hover,
|
||||
.datepicker table tr td span.active:hover.active:hover,
|
||||
.datepicker table tr td span.active.disabled.active:hover,
|
||||
.datepicker table tr td span.active.disabled:hover.active:hover,
|
||||
.datepicker table tr td span.active:active:focus,
|
||||
.datepicker table tr td span.active:hover:active:focus,
|
||||
.datepicker table tr td span.active.disabled:active:focus,
|
||||
.datepicker table tr td span.active.disabled:hover:active:focus,
|
||||
.datepicker table tr td span.active.active:focus,
|
||||
.datepicker table tr td span.active:hover.active:focus,
|
||||
.datepicker table tr td span.active.disabled.active:focus,
|
||||
.datepicker table tr td span.active.disabled:hover.active:focus,
|
||||
.datepicker table tr td span.active:active.focus,
|
||||
.datepicker table tr td span.active:hover:active.focus,
|
||||
.datepicker table tr td span.active.disabled:active.focus,
|
||||
.datepicker table tr td span.active.disabled:hover:active.focus,
|
||||
.datepicker table tr td span.active.active.focus,
|
||||
.datepicker table tr td span.active:hover.active.focus,
|
||||
.datepicker table tr td span.active.disabled.active.focus,
|
||||
.datepicker table tr td span.active.disabled:hover.active.focus {
|
||||
|
||||
.datepicker table tr td span.active:active:hover, .datepicker table tr td span.active:active:focus, .datepicker table tr td span.active:active.focus, .datepicker table tr td span.active.active:hover, .datepicker table tr td span.active.active:focus, .datepicker table tr td span.active.active.focus, .datepicker table tr td span.active:hover:active:hover, .datepicker table tr td span.active:hover:active:focus, .datepicker table tr td span.active:hover:active.focus, .datepicker table tr td span.active:hover.active:hover, .datepicker table tr td span.active:hover.active:focus, .datepicker table tr td span.active:hover.active.focus, .datepicker table tr td span.active.disabled:active:hover, .datepicker table tr td span.active.disabled:active:focus, .datepicker table tr td span.active.disabled:active.focus, .datepicker table tr td span.active.disabled.active:hover, .datepicker table tr td span.active.disabled.active:focus, .datepicker table tr td span.active.disabled.active.focus, .datepicker table tr td span.active.disabled:hover:active:hover, .datepicker table tr td span.active.disabled:hover:active:focus, .datepicker table tr td span.active.disabled:hover:active.focus, .datepicker table tr td span.active.disabled:hover.active:hover, .datepicker table tr td span.active.disabled:hover.active:focus, .datepicker table tr td span.active.disabled:hover.active.focus {
|
||||
color: #fff;
|
||||
background-color: #204d74;
|
||||
border-color: #122b40;
|
||||
background-color: #2b91ff;
|
||||
border-color: #4199f7;
|
||||
}
|
||||
.datepicker table tr td span.active.disabled:hover,
|
||||
.datepicker table tr td span.active:hover.disabled:hover,
|
||||
.datepicker table tr td span.active.disabled.disabled:hover,
|
||||
.datepicker table tr td span.active.disabled:hover.disabled:hover,
|
||||
.datepicker table tr td span.active[disabled]:hover,
|
||||
.datepicker table tr td span.active:hover[disabled]:hover,
|
||||
.datepicker table tr td span.active.disabled[disabled]:hover,
|
||||
.datepicker table tr td span.active.disabled:hover[disabled]:hover,
|
||||
|
||||
.datepicker table tr td span.active.disabled:hover, .datepicker table tr td span.active.disabled:focus, .datepicker table tr td span.active.disabled.focus, .datepicker table tr td span.active[disabled]:hover, .datepicker table tr td span.active[disabled]:focus, .datepicker table tr td span.active[disabled].focus,
|
||||
fieldset[disabled] .datepicker table tr td span.active:hover,
|
||||
fieldset[disabled] .datepicker table tr td span.active:hover:hover,
|
||||
fieldset[disabled] .datepicker table tr td span.active.disabled:hover,
|
||||
fieldset[disabled] .datepicker table tr td span.active.disabled:hover:hover,
|
||||
.datepicker table tr td span.active.disabled:focus,
|
||||
.datepicker table tr td span.active:hover.disabled:focus,
|
||||
.datepicker table tr td span.active.disabled.disabled:focus,
|
||||
.datepicker table tr td span.active.disabled:hover.disabled:focus,
|
||||
.datepicker table tr td span.active[disabled]:focus,
|
||||
.datepicker table tr td span.active:hover[disabled]:focus,
|
||||
.datepicker table tr td span.active.disabled[disabled]:focus,
|
||||
.datepicker table tr td span.active.disabled:hover[disabled]:focus,
|
||||
fieldset[disabled] .datepicker table tr td span.active:focus,
|
||||
fieldset[disabled] .datepicker table tr td span.active.focus, .datepicker table tr td span.active:hover.disabled:hover, .datepicker table tr td span.active:hover.disabled:focus, .datepicker table tr td span.active:hover.disabled.focus, .datepicker table tr td span.active:hover[disabled]:hover, .datepicker table tr td span.active:hover[disabled]:focus, .datepicker table tr td span.active:hover[disabled].focus,
|
||||
fieldset[disabled] .datepicker table tr td span.active:hover:hover,
|
||||
fieldset[disabled] .datepicker table tr td span.active:hover:focus,
|
||||
fieldset[disabled] .datepicker table tr td span.active:hover.focus, .datepicker table tr td span.active.disabled.disabled:hover, .datepicker table tr td span.active.disabled.disabled:focus, .datepicker table tr td span.active.disabled.disabled.focus, .datepicker table tr td span.active.disabled[disabled]:hover, .datepicker table tr td span.active.disabled[disabled]:focus, .datepicker table tr td span.active.disabled[disabled].focus,
|
||||
fieldset[disabled] .datepicker table tr td span.active.disabled:hover,
|
||||
fieldset[disabled] .datepicker table tr td span.active.disabled:focus,
|
||||
fieldset[disabled] .datepicker table tr td span.active.disabled.focus, .datepicker table tr td span.active.disabled:hover.disabled:hover, .datepicker table tr td span.active.disabled:hover.disabled:focus, .datepicker table tr td span.active.disabled:hover.disabled.focus, .datepicker table tr td span.active.disabled:hover[disabled]:hover, .datepicker table tr td span.active.disabled:hover[disabled]:focus, .datepicker table tr td span.active.disabled:hover[disabled].focus,
|
||||
fieldset[disabled] .datepicker table tr td span.active.disabled:hover:hover,
|
||||
fieldset[disabled] .datepicker table tr td span.active.disabled:hover:focus,
|
||||
.datepicker table tr td span.active.disabled.focus,
|
||||
.datepicker table tr td span.active:hover.disabled.focus,
|
||||
.datepicker table tr td span.active.disabled.disabled.focus,
|
||||
.datepicker table tr td span.active.disabled:hover.disabled.focus,
|
||||
.datepicker table tr td span.active[disabled].focus,
|
||||
.datepicker table tr td span.active:hover[disabled].focus,
|
||||
.datepicker table tr td span.active.disabled[disabled].focus,
|
||||
.datepicker table tr td span.active.disabled:hover[disabled].focus,
|
||||
fieldset[disabled] .datepicker table tr td span.active.focus,
|
||||
fieldset[disabled] .datepicker table tr td span.active:hover.focus,
|
||||
fieldset[disabled] .datepicker table tr td span.active.disabled.focus,
|
||||
fieldset[disabled] .datepicker table tr td span.active.disabled:hover.focus {
|
||||
background-color: #337ab7;
|
||||
border-color: #2e6da4;
|
||||
background-color: #007bff;
|
||||
border-color: #0277f4;
|
||||
}
|
||||
.datepicker table tr td span.old,
|
||||
.datepicker table tr td span.new {
|
||||
color: #777777;
|
||||
|
||||
.datepicker table tr td span.old, .datepicker table tr td span.new {
|
||||
color: #6c757d;
|
||||
}
|
||||
|
||||
.datepicker .datepicker-switch {
|
||||
width: 145px;
|
||||
}
|
||||
|
||||
.datepicker .datepicker-switch,
|
||||
.datepicker .prev,
|
||||
.datepicker .next,
|
||||
.datepicker tfoot tr th {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.datepicker .datepicker-switch:hover,
|
||||
.datepicker .prev:hover,
|
||||
.datepicker .next:hover,
|
||||
.datepicker tfoot tr th:hover {
|
||||
background: #eeeeee;
|
||||
color: #212529;
|
||||
background: #e9e9ea;
|
||||
}
|
||||
|
||||
.datepicker .prev.disabled, .datepicker .next.disabled {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.datepicker .cw {
|
||||
font-size: 10px;
|
||||
width: 12px;
|
||||
padding: 0 2px 0 5px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.input-group.date .input-group-addon {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.input-daterange {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.input-daterange input {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.input-daterange input:first-child {
|
||||
border-radius: 3px 0 0 3px;
|
||||
}
|
||||
|
||||
.input-daterange input:last-child {
|
||||
border-radius: 0 3px 3px 0;
|
||||
}
|
||||
|
||||
.input-daterange .input-group-addon {
|
||||
width: auto;
|
||||
min-width: 16px;
|
||||
padding: 4px 5px;
|
||||
line-height: 1.42857143;
|
||||
text-shadow: 0 1px 0 #fff;
|
||||
line-height: 1.5;
|
||||
border-width: 1px 0;
|
||||
margin-left: -5px;
|
||||
margin-right: -5px;
|
||||
}
|
||||
/*# sourceMappingURL=bootstrap-datepicker3.css.map */
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
1
inst/www/shared/datepicker/js/locales/bootstrap-datepicker-en-CA.min.js
vendored
Normal file
1
inst/www/shared/datepicker/js/locales/bootstrap-datepicker-en-CA.min.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates["en-CA"]={days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],daysShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],daysMin:["Su","Mo","Tu","We","Th","Fr","Sa"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],monthsShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],today:"Today",monthsTitle:"Months",clear:"Clear",weekStart:0,format:"yyyy-mm-dd"},a.fn.datepicker.deprecated("This filename doesn't follow the convention, use bootstrap-datepicker.en-CA.js instead.")}(jQuery);
|
||||
1
inst/www/shared/datepicker/js/locales/bootstrap-datepicker.ar-tn.min.js
vendored
Normal file
1
inst/www/shared/datepicker/js/locales/bootstrap-datepicker.ar-tn.min.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates["ar-tn"]={days:["الأحد","الاثنين","الثلاثاء","الأربعاء","الخميس","الجمعة","السبت","الأحد"],daysShort:["أحد","اثنين","ثلاثاء","أربعاء","خميس","جمعة","سبت","أحد"],daysMin:["ح","ن","ث","ع","خ","ج","س","ح"],months:["جانفي","فيفري","مارس","أفريل","ماي","جوان","جويليه","أوت","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],monthsShort:["جانفي","فيفري","مارس","أفريل","ماي","جوان","جويليه","أوت","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],today:"هذا اليوم",rtl:!0}}(jQuery);
|
||||
@@ -1 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.az={days:["Bazar","Bazar ertəsi","Çərşənbə axşamı","Çərşənbə","Cümə axşamı","Cümə","Şənbə"],daysShort:["B.","B.e","Ç.a","Ç.","C.a","C.","Ş."],daysMin:["B.","B.e","Ç.a","Ç.","C.a","C.","Ş."],months:["Yanvar","Fevral","Mart","Aprel","May","İyun","İyul","Avqust","Sentyabr","Oktyabr","Noyabr","Dekabr"],monthsShort:["Yan","Fev","Mar","Apr","May","İyun","İyul","Avq","Sen","Okt","Noy","Dek"],today:"Bu gün",weekStart:1}}(jQuery);
|
||||
!function(a){a.fn.datepicker.dates.az={days:["Bazar","Bazar ertəsi","Çərşənbə axşamı","Çərşənbə","Cümə axşamı","Cümə","Şənbə"],daysShort:["B.","B.e","Ç.a","Ç.","C.a","C.","Ş."],daysMin:["B.","B.e","Ç.a","Ç.","C.a","C.","Ş."],months:["Yanvar","Fevral","Mart","Aprel","May","İyun","İyul","Avqust","Sentyabr","Oktyabr","Noyabr","Dekabr"],monthsShort:["Yan","Fev","Mar","Apr","May","İyun","İyul","Avq","Sen","Okt","Noy","Dek"],today:"Bu gün",weekStart:1,clear:"Təmizlə",monthsTitle:"Aylar"}}(jQuery);
|
||||
1
inst/www/shared/datepicker/js/locales/bootstrap-datepicker.bm.min.js
vendored
Normal file
1
inst/www/shared/datepicker/js/locales/bootstrap-datepicker.bm.min.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.bm={days:["Kari","Ntɛnɛn","Tarata","Araba","Alamisa","Juma","Sibiri"],daysShort:["Kar","Ntɛ","Tar","Ara","Ala","Jum","Sib"],daysMin:["Ka","Nt","Ta","Ar","Al","Ju","Si"],months:["Zanwuyekalo","Fewuruyekalo","Marisikalo","Awirilikalo","Mɛkalo","Zuwɛnkalo","Zuluyekalo","Utikalo","Sɛtanburukalo","ɔkutɔburukalo","Nowanburukalo","Desanburukalo"],monthsShort:["Zan","Few","Mar","Awi","Mɛ","Zuw","Zul","Uti","Sɛt","ɔku","Now","Des"],today:"Bi",monthsTitle:"Kalo",clear:"Ka jɔsi",weekStart:1,format:"dd/mm/yyyy"}}(jQuery);
|
||||
1
inst/www/shared/datepicker/js/locales/bootstrap-datepicker.bn.min.js
vendored
Normal file
1
inst/www/shared/datepicker/js/locales/bootstrap-datepicker.bn.min.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.bn={days:["রবিবার","সোমবার","মঙ্গলবার","বুধবার","বৃহস্পতিবার","শুক্রবার","শনিবার"],daysShort:["রবিবার","সোমবার","মঙ্গলবার","বুধবার","বৃহস্পতিবার","শুক্রবার","শনিবার"],daysMin:["রবি","সোম","মঙ্গল","বুধ","বৃহস্পতি","শুক্র","শনি"],months:["জানুয়ারী","ফেব্রুয়ারি","মার্চ","এপ্রিল","মে","জুন","জুলাই","অগাস্ট","সেপ্টেম্বর","অক্টোবর","নভেম্বর","ডিসেম্বর"],monthsShort:["জানুয়ারী","ফেব্রুয়ারি","মার্চ","এপ্রিল","মে","জুন","জুলাই","অগাস্ট","সেপ্টেম্বর","অক্টোবর","নভেম্বর","ডিসেম্বর"],today:"আজ",monthsTitle:"মাস",clear:"পরিষ্কার",weekStart:0,format:"mm/dd/yyyy"}}(jQuery);
|
||||
1
inst/www/shared/datepicker/js/locales/bootstrap-datepicker.br.min.js
vendored
Normal file
1
inst/www/shared/datepicker/js/locales/bootstrap-datepicker.br.min.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.br={days:["Sul","Lun","Meurzh","Merc'her","Yaou","Gwener","Sadorn"],daysShort:["Sul","Lun","Meu.","Mer.","Yao.","Gwe.","Sad."],daysMin:["Su","L","Meu","Mer","Y","G","Sa"],months:["Genver","C'hwevrer","Meurzh","Ebrel","Mae","Mezheven","Gouere","Eost","Gwengolo","Here","Du","Kerzu"],monthsShort:["Genv.","C'hw.","Meur.","Ebre.","Mae","Mezh.","Goue.","Eost","Gwen.","Here","Du","Kerz."],today:"Hiziv",monthsTitle:"Miz",clear:"Dilemel",weekStart:1,format:"dd/mm/yyyy"}}(jQuery);
|
||||
@@ -1 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.cs={days:["Neděle","Pondělí","Úterý","Středa","Čtvrtek","Pátek","Sobota"],daysShort:["Ned","Pon","Úte","Stř","Čtv","Pát","Sob"],daysMin:["Ne","Po","Út","St","Čt","Pá","So"],months:["Leden","Únor","Březen","Duben","Květen","Červen","Červenec","Srpen","Září","Říjen","Listopad","Prosinec"],monthsShort:["Led","Úno","Bře","Dub","Kvě","Čer","Čnc","Srp","Zář","Říj","Lis","Pro"],today:"Dnes",clear:"Vymazat",weekStart:1,format:"dd.m.yyyy"}}(jQuery);
|
||||
!function(a){a.fn.datepicker.dates.cs={days:["Neděle","Pondělí","Úterý","Středa","Čtvrtek","Pátek","Sobota"],daysShort:["Ned","Pon","Úte","Stř","Čtv","Pát","Sob"],daysMin:["Ne","Po","Út","St","Čt","Pá","So"],months:["Leden","Únor","Březen","Duben","Květen","Červen","Červenec","Srpen","Září","Říjen","Listopad","Prosinec"],monthsShort:["Led","Úno","Bře","Dub","Kvě","Čer","Čnc","Srp","Zář","Říj","Lis","Pro"],today:"Dnes",clear:"Vymazat",monthsTitle:"Měsíc",weekStart:1,format:"dd.mm.yyyy"}}(jQuery);
|
||||
@@ -1 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.da={days:["søndag","mandag","tirsdag","onsdag","torsdag","fredag","lørdag"],daysShort:["søn","man","tir","ons","tor","fre","lør"],daysMin:["sø","ma","ti","on","to","fr","lø"],months:["januar","februar","marts","april","maj","juni","juli","august","september","oktober","november","december"],monthsShort:["jan","feb","mar","apr","maj","jun","jul","aug","sep","okt","nov","dec"],today:"I Dag",clear:"Nulstil"}}(jQuery);
|
||||
!function(a){a.fn.datepicker.dates.da={days:["Søndag","Mandag","Tirsdag","Onsdag","Torsdag","Fredag","Lørdag"],daysShort:["Søn","Man","Tir","Ons","Tor","Fre","Lør"],daysMin:["Sø","Ma","Ti","On","To","Fr","Lø"],months:["Januar","Februar","Marts","April","Maj","Juni","Juli","August","September","Oktober","November","December"],monthsShort:["Jan","Feb","Mar","Apr","Maj","Jun","Jul","Aug","Sep","Okt","Nov","Dec"],today:"I Dag",weekStart:1,clear:"Nulstil",format:"dd/mm/yyyy",monthsTitle:"Måneder"}}(jQuery);
|
||||
1
inst/www/shared/datepicker/js/locales/bootstrap-datepicker.en-CA.min.js
vendored
Normal file
1
inst/www/shared/datepicker/js/locales/bootstrap-datepicker.en-CA.min.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates["en-CA"]={days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],daysShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],daysMin:["Su","Mo","Tu","We","Th","Fr","Sa"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],monthsShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],today:"Today",monthsTitle:"Months",clear:"Clear",weekStart:0,format:"yyyy-mm-dd"}}(jQuery);
|
||||
1
inst/www/shared/datepicker/js/locales/bootstrap-datepicker.en-IE.min.js
vendored
Normal file
1
inst/www/shared/datepicker/js/locales/bootstrap-datepicker.en-IE.min.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates["en-IE"]={days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],daysShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],daysMin:["Su","Mo","Tu","We","Th","Fr","Sa"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],monthsShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],today:"Today",monthsTitle:"Months",clear:"Clear",weekStart:1,format:"dd/mm/yyyy"}}(jQuery);
|
||||
1
inst/www/shared/datepicker/js/locales/bootstrap-datepicker.en-NZ.min.js
vendored
Normal file
1
inst/www/shared/datepicker/js/locales/bootstrap-datepicker.en-NZ.min.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates["en-NZ"]={days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],daysShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],daysMin:["Su","Mo","Tu","We","Th","Fr","Sa"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],monthsShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],today:"Today",monthsTitle:"Months",clear:"Clear",weekStart:1,format:"d/mm/yyyy"}}(jQuery);
|
||||
1
inst/www/shared/datepicker/js/locales/bootstrap-datepicker.en-ZA.min.js
vendored
Normal file
1
inst/www/shared/datepicker/js/locales/bootstrap-datepicker.en-ZA.min.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates["en-ZA"]={days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],daysShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],daysMin:["Su","Mo","Tu","We","Th","Fr","Sa"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],monthsShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],today:"Today",monthsTitle:"Months",clear:"Clear",weekStart:1,format:"yyyy/mm/d"}}(jQuery);
|
||||
@@ -1 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.eu={days:["Igandea","Astelehena","Asteartea","Asteazkena","Osteguna","Ostirala","Larunbata"],daysShort:["Ig","Al","Ar","Az","Og","Ol","Lr"],daysMin:["Ig","Al","Ar","Az","Og","Ol","Lr"],months:["Urtarrila","Otsaila","Martxoa","Apirila","Maiatza","Ekaina","Uztaila","Abuztua","Iraila","Urria","Azaroa","Abendua"],monthsShort:["Urt","Ots","Mar","Api","Mai","Eka","Uzt","Abu","Ira","Urr","Aza","Abe"],today:"Gaur"}}(jQuery);
|
||||
!function(a){a.fn.datepicker.dates.eu={days:["Igandea","Astelehena","Asteartea","Asteazkena","Osteguna","Ostirala","Larunbata"],daysShort:["Ig","Al","Ar","Az","Og","Ol","Lr"],daysMin:["Ig","Al","Ar","Az","Og","Ol","Lr"],months:["Urtarrila","Otsaila","Martxoa","Apirila","Maiatza","Ekaina","Uztaila","Abuztua","Iraila","Urria","Azaroa","Abendua"],monthsShort:["Urt","Ots","Mar","Api","Mai","Eka","Uzt","Abu","Ira","Urr","Aza","Abe"],today:"Gaur",monthsTitle:"Hilabeteak",clear:"Ezabatu",weekStart:1,format:"yyyy/mm/dd"}}(jQuery);
|
||||
1
inst/www/shared/datepicker/js/locales/bootstrap-datepicker.hi.min.js
vendored
Normal file
1
inst/www/shared/datepicker/js/locales/bootstrap-datepicker.hi.min.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.hi={days:["रविवार","सोमवार","मंगलवार","बुधवार","गुरुवार","शुक्रवार","शनिवार"],daysShort:["सूर्य","सोम","मंगल","बुध","गुरु","शुक्र","शनि"],daysMin:["र","सो","मं","बु","गु","शु","श"],months:["जनवरी","फ़रवरी","मार्च","अप्रैल","मई","जून","जुलाई","अगस्त","सितम्बर","अक्टूबर","नवंबर","दिसम्बर"],monthsShort:["जन","फ़रवरी","मार्च","अप्रैल","मई","जून","जुलाई","अगस्त","सितं","अक्टूबर","नवं","दिसम्बर"],today:"आज",monthsTitle:"महीने",clear:"साफ",weekStart:1,format:"dd / mm / yyyy"}}(jQuery);
|
||||
@@ -1 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.hy={days:["Կիրակի","Երկուշաբթի","Երեքշաբթի","Չորեքշաբթի","Հինգշաբթի","Ուրբաթ","Շաբաթ"],daysShort:["Կրկ","Երկ","Երք","Չրք","Հնգ","Ուր","Շբթ"],daysMin:["Կրկ","Երկ","Երք","Չրք","Հնգ","Ուր","Շբթ"],months:["Հունվար","Փետրվար","Մարտ","Ապրիլ","Մայիս","Հունիս","Հուլիս","Օգոստոս","Սեպտեմբեր","Հոկտեմբեր","Նոյեմբեր","Դեկտեմբեր"],monthsShort:["Հուն","Փետ","Մար","Ապր","Մայ","Հնս","Հլս","Օգս","Սեպ","Հոկ","Նմբ","Դեկ"],today:"Այսօր",clear:"Ջնջել",format:"dd.mm.yyyy",weekStart:1}}(jQuery);
|
||||
!function(a){a.fn.datepicker.dates.hy={days:["Կիրակի","Երկուշաբթի","Երեքշաբթի","Չորեքշաբթի","Հինգշաբթի","Ուրբաթ","Շաբաթ"],daysShort:["Կիր","Երկ","Երե","Չոր","Հին","Ուրբ","Շաբ"],daysMin:["Կի","Եկ","Եք","Չո","Հի","Ու","Շա"],months:["Հունվար","Փետրվար","Մարտ","Ապրիլ","Մայիս","Հունիս","Հուլիս","Օգոստոս","Սեպտեմբեր","Հոկտեմբեր","Նոյեմբեր","Դեկտեմբեր"],monthsShort:["Հնվ","Փետ","Մար","Ապր","Մայ","Հուն","Հուլ","Օգս","Սեպ","Հոկ","Նոյ","Դեկ"],today:"Այսօր",clear:"Ջնջել",format:"dd.mm.yyyy",weekStart:1,monthsTitle:"Ամիսնէր"}}(jQuery);
|
||||
@@ -1 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.ka={days:["კვირა","ორშაბათი","სამშაბათი","ოთხშაბათი","ხუთშაბათი","პარასკევი","შაბათი"],daysShort:["კვი","ორშ","სამ","ოთხ","ხუთ","პარ","შაბ"],daysMin:["კვ","ორ","სა","ოთ","ხუ","პა","შა"],months:["იანვარი","თებერვალი","მარტი","აპრილი","მაისი","ივნისი","ივლისი","აგვისტო","სექტემბერი","ოქტომები","ნოემბერი","დეკემბერი"],monthsShort:["იან","თებ","მარ","აპრ","მაი","ივნ","ივლ","აგვ","სექ","ოქტ","ნოე","დეკ"],today:"დღეს",clear:"გასუფთავება",weekStart:1,format:"dd.mm.yyyy"}}(jQuery);
|
||||
!function(a){a.fn.datepicker.dates.ka={days:["კვირა","ორშაბათი","სამშაბათი","ოთხშაბათი","ხუთშაბათი","პარასკევი","შაბათი"],daysShort:["კვი","ორშ","სამ","ოთხ","ხუთ","პარ","შაბ"],daysMin:["კვ","ორ","სა","ოთ","ხუ","პა","შა"],months:["იანვარი","თებერვალი","მარტი","აპრილი","მაისი","ივნისი","ივლისი","აგვისტო","სექტემბერი","ოქტომბერი","ნოემბერი","დეკემბერი"],monthsShort:["იან","თებ","მარ","აპრ","მაი","ივნ","ივლ","აგვ","სექ","ოქტ","ნოე","დეკ"],today:"დღეს",clear:"გასუფთავება",weekStart:1,format:"dd.mm.yyyy"}}(jQuery);
|
||||
@@ -1 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.kh={days:["អាទិត្យ","ចន្ទ","អង្គារ","ពុធ","ព្រហស្បតិ៍","សុក្រ","សៅរ៍","អាទិត្យ"],daysShort:["អា.ទិ","ចន្ទ","អង្គារ","ពុធ","ព្រ.ហ","សុក្រ","សៅរ៍","អា.ទិ"],daysMin:["អា.ទិ","ចន្ទ","អង្គារ","ពុធ","ព្រ.ហ","សុក្រ","សៅរ៍","អា.ទិ"],months:["មករា","កុម្ភះ","មិនា","មេសា","ឧសភា","មិថុនា","កក្កដា","សីហា","កញ្ញា","តុលា","វិច្ឆិកា","ធ្នូ"],monthsShort:["មករា","កុម្ភះ","មិនា","មេសា","ឧសភា","មិថុនា","កក្កដា","សីហា","កញ្ញា","តុលា","វិច្ឆិកា","ធ្នូ"],today:"ថ្ងៃនេះ",clear:"សំអាត"}}(jQuery);
|
||||
!function(a){a.fn.datepicker.dates.kh={days:["អាទិត្យ","ចន្ទ","អង្គារ","ពុធ","ព្រហស្បតិ៍","សុក្រ","សៅរ៍"],daysShort:["អា.ទិ","ចន្ទ","អង្គារ","ពុធ","ព្រ.ហ","សុក្រ","សៅរ៍"],daysMin:["អា.ទិ","ចន្ទ","អង្គារ","ពុធ","ព្រ.ហ","សុក្រ","សៅរ៍"],months:["មករា","កុម្ភះ","មិនា","មេសា","ឧសភា","មិថុនា","កក្កដា","សីហា","កញ្ញា","តុលា","វិច្ឆិកា","ធ្នូ"],monthsShort:["មករា","កុម្ភះ","មិនា","មេសា","ឧសភា","មិថុនា","កក្កដា","សីហា","កញ្ញា","តុលា","វិច្ឆិកា","ធ្នូ"],today:"ថ្ងៃនេះ",clear:"សំអាត"},a.fn.datepicker.deprecated('The language code "kh" is deprecated and will be removed in 2.0. For Khmer support use "km" instead.')}(jQuery);
|
||||
1
inst/www/shared/datepicker/js/locales/bootstrap-datepicker.km.min.js
vendored
Normal file
1
inst/www/shared/datepicker/js/locales/bootstrap-datepicker.km.min.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.km={days:["អាទិត្យ","ចន្ទ","អង្គារ","ពុធ","ព្រហស្បតិ៍","សុក្រ","សៅរ៍"],daysShort:["អា.ទិ","ចន្ទ","អង្គារ","ពុធ","ព្រ.ហ","សុក្រ","សៅរ៍"],daysMin:["អា.ទិ","ចន្ទ","អង្គារ","ពុធ","ព្រ.ហ","សុក្រ","សៅរ៍"],months:["មករា","កុម្ភះ","មិនា","មេសា","ឧសភា","មិថុនា","កក្កដា","សីហា","កញ្ញា","តុលា","វិច្ឆិកា","ធ្នូ"],monthsShort:["មករា","កុម្ភះ","មិនា","មេសា","ឧសភា","មិថុនា","កក្កដា","សីហា","កញ្ញា","តុលា","វិច្ឆិកា","ធ្នូ"],today:"ថ្ងៃនេះ",clear:"សំអាត"}}(jQuery);
|
||||
@@ -1 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.kr={days:["일요일","월요일","화요일","수요일","목요일","금요일","토요일"],daysShort:["일","월","화","수","목","금","토"],daysMin:["일","월","화","수","목","금","토"],months:["1월","2월","3월","4월","5월","6월","7월","8월","9월","10월","11월","12월"],monthsShort:["1월","2월","3월","4월","5월","6월","7월","8월","9월","10월","11월","12월"]}}(jQuery);
|
||||
!function(a){a.fn.datepicker.dates.kr={days:["일요일","월요일","화요일","수요일","목요일","금요일","토요일"],daysShort:["일","월","화","수","목","금","토"],daysMin:["일","월","화","수","목","금","토"],months:["1월","2월","3월","4월","5월","6월","7월","8월","9월","10월","11월","12월"],monthsShort:["1월","2월","3월","4월","5월","6월","7월","8월","9월","10월","11월","12월"]},a.fn.datepicker.deprecated('The language code "kr" is deprecated and will be removed in 2.0. For korean support use "ko" instead.')}(jQuery);
|
||||
@@ -1 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.lv={days:["Svētdiena","Pirmdiena","Otrdiena","Trešdiena","Ceturtdiena","Piektdiena","Sestdiena"],daysShort:["Sv","P","O","T","C","Pk","S"],daysMin:["Sv","Pr","Ot","Tr","Ce","Pk","Se"],months:["Janvāris","Februāris","Marts","Aprīlis","Maijs","Jūnijs","Jūlijs","Augusts","Septembris","Oktobris","Novembris","Decembris"],monthsShort:["Jan","Feb","Mar","Apr","Mai","Jūn","Jūl","Aug","Sep","Okt","Nov","Dec"],today:"Šodien",weekStart:1}}(jQuery);
|
||||
!function(a){a.fn.datepicker.dates.lv={days:["Svētdiena","Pirmdiena","Otrdiena","Trešdiena","Ceturtdiena","Piektdiena","Sestdiena"],daysShort:["Sv","P","O","T","C","Pk","S"],daysMin:["Sv","Pr","Ot","Tr","Ce","Pk","Se"],months:["Janvāris","Februāris","Marts","Aprīlis","Maijs","Jūnijs","Jūlijs","Augusts","Septembris","Oktobris","Novembris","Decembris"],monthsShort:["Jan","Feb","Mar","Apr","Mai","Jūn","Jūl","Aug","Sep","Okt","Nov","Dec"],monthsTitle:"Mēneši",today:"Šodien",clear:"Nodzēst",weekStart:1}}(jQuery);
|
||||
@@ -1 +0,0 @@
|
||||
!function(a){a.fn.datepicker.dates.nb={days:["Søndag","Mandag","Tirsdag","Onsdag","Torsdag","Fredag","Lørdag"],daysShort:["Søn","Man","Tir","Ons","Tor","Fre","Lør"],daysMin:["Sø","Ma","Ti","On","To","Fr","Lø"],months:["Januar","Februar","Mars","April","Mai","Juni","Juli","August","September","Oktober","November","Desember"],monthsShort:["Jan","Feb","Mar","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Des"],today:"I Dag",format:"dd.mm.yyyy"}}(jQuery);
|
||||
@@ -1 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.no={days:["Søndag","Mandag","Tirsdag","Onsdag","Torsdag","Fredag","Lørdag"],daysShort:["Søn","Man","Tir","Ons","Tor","Fre","Lør"],daysMin:["Sø","Ma","Ti","On","To","Fr","Lø"],months:["Januar","Februar","Mars","April","Mai","Juni","Juli","August","September","Oktober","November","Desember"],monthsShort:["Jan","Feb","Mar","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Des"],today:"I dag",clear:"Nullstill",weekStart:1,format:"dd.mm.yyyy"}}(jQuery);
|
||||
!function(a){a.fn.datepicker.dates.no={days:["søndag","mandag","tirsdag","onsdag","torsdag","fredag","lørdag"],daysShort:["søn","man","tir","ons","tor","fre","lør"],daysMin:["sø","ma","ti","on","to","fr","lø"],months:["januar","februar","mars","april","mai","juni","juli","august","september","oktober","november","desember"],monthsShort:["jan","feb","mar","apr","mai","jun","jul","aug","sep","okt","nov","des"],today:"i dag",monthsTitle:"Måneder",clear:"Nullstill",weekStart:1,format:"dd.mm.yyyy"}}(jQuery);
|
||||
1
inst/www/shared/datepicker/js/locales/bootstrap-datepicker.oc.min.js
vendored
Normal file
1
inst/www/shared/datepicker/js/locales/bootstrap-datepicker.oc.min.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.oc={days:["Dimenge","Diluns","Dimars","Dimècres","Dijòus","Divendres","Dissabte"],daysShort:["Dim","Dil","Dmr","Dmc","Dij","Div","Dis"],daysMin:["dg","dl","dr","dc","dj","dv","ds"],months:["Genièr","Febrièr","Març","Abrial","Mai","Junh","Julhet","Agost","Setembre","Octobre","Novembre","Decembre"],monthsShort:["Gen","Feb","Mar","Abr","Mai","Jun","Jul","Ago","Set","Oct","Nov","Dec"],today:"Uèi",monthsTitle:"Meses",clear:"Escafar",weekStart:1,format:"dd/mm/yyyy"}}(jQuery);
|
||||
@@ -1 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.pl={days:["niedziela","poniedziałek","wtorek","środa","czwartek","piątek","sobota"],daysShort:["niedz.","pon.","wt.","śr.","czw.","piąt.","sob."],daysMin:["ndz.","pn.","wt.","śr.","czw.","pt.","sob."],months:["styczeń","luty","marzec","kwiecień","maj","czerwiec","lipiec","sierpień","wrzesień","październik","listopad","grudzień"],monthsShort:["sty.","lut.","mar.","kwi.","maj","cze.","lip.","sie.","wrz.","paź.","lis.","gru."],today:"dzisiaj",weekStart:1,clear:"wyczyść",format:"dd.mm.yyyy"}}(jQuery);
|
||||
!function(a){a.fn.datepicker.dates.pl={days:["Niedziela","Poniedziałek","Wtorek","Środa","Czwartek","Piątek","Sobota"],daysShort:["Niedz.","Pon.","Wt.","Śr.","Czw.","Piąt.","Sob."],daysMin:["Ndz.","Pn.","Wt.","Śr.","Czw.","Pt.","Sob."],months:["Styczeń","Luty","Marzec","Kwiecień","Maj","Czerwiec","Lipiec","Sierpień","Wrzesień","Październik","Listopad","Grudzień"],monthsShort:["Sty.","Lut.","Mar.","Kwi.","Maj","Cze.","Lip.","Sie.","Wrz.","Paź.","Lis.","Gru."],today:"Dzisiaj",weekStart:1,clear:"Wyczyść",format:"dd.mm.yyyy"}}(jQuery);
|
||||
@@ -1 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.ro={days:["Duminică","Luni","Marţi","Miercuri","Joi","Vineri","Sâmbătă"],daysShort:["Dum","Lun","Mar","Mie","Joi","Vin","Sâm"],daysMin:["Du","Lu","Ma","Mi","Jo","Vi","Sâ"],months:["Ianuarie","Februarie","Martie","Aprilie","Mai","Iunie","Iulie","August","Septembrie","Octombrie","Noiembrie","Decembrie"],monthsShort:["Ian","Feb","Mar","Apr","Mai","Iun","Iul","Aug","Sep","Oct","Nov","Dec"],today:"Astăzi",clear:"Șterge",weekStart:1}}(jQuery);
|
||||
!function(a){a.fn.datepicker.dates.ro={days:["Duminică","Luni","Marţi","Miercuri","Joi","Vineri","Sâmbătă"],daysShort:["Dum","Lun","Mar","Mie","Joi","Vin","Sâm"],daysMin:["Du","Lu","Ma","Mi","Jo","Vi","Sâ"],months:["Ianuarie","Februarie","Martie","Aprilie","Mai","Iunie","Iulie","August","Septembrie","Octombrie","Noiembrie","Decembrie"],monthsShort:["Ian","Feb","Mar","Apr","Mai","Iun","Iul","Aug","Sep","Oct","Nov","Dec"],today:"Astăzi",clear:"Șterge",weekStart:1,format:"dd/mm/yyyy"}}(jQuery);
|
||||
@@ -1 +1 @@
|
||||
!function(a){a.fn.datepicker.dates["rs-latin"]={days:["Nedelja","Ponedeljak","Utorak","Sreda","Četvrtak","Petak","Subota"],daysShort:["Ned","Pon","Uto","Sre","Čet","Pet","Sub"],daysMin:["N","Po","U","Sr","Č","Pe","Su"],months:["Januar","Februar","Mart","April","Maj","Jun","Jul","Avgust","Septembar","Oktobar","Novembar","Decembar"],monthsShort:["Jan","Feb","Mar","Apr","Maj","Jun","Jul","Avg","Sep","Okt","Nov","Dec"],today:"Danas",weekStart:1,format:"dd.mm.yyyy"}}(jQuery);
|
||||
!function(a){a.fn.datepicker.dates["rs-latin"]={days:["Nedelja","Ponedeljak","Utorak","Sreda","Četvrtak","Petak","Subota"],daysShort:["Ned","Pon","Uto","Sre","Čet","Pet","Sub"],daysMin:["N","Po","U","Sr","Č","Pe","Su"],months:["Januar","Februar","Mart","April","Maj","Jun","Jul","Avgust","Septembar","Oktobar","Novembar","Decembar"],monthsShort:["Jan","Feb","Mar","Apr","Maj","Jun","Jul","Avg","Sep","Okt","Nov","Dec"],today:"Danas",weekStart:1,format:"dd.mm.yyyy"},a.fn.datepicker.deprecated('This language code "rs-latin" is deprecated (invalid serbian language code) and will be removed in 2.0. For Serbian latin support use "sr-latin" instead.')}(jQuery);
|
||||
@@ -1 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.rs={days:["Недеља","Понедељак","Уторак","Среда","Четвртак","Петак","Субота"],daysShort:["Нед","Пон","Уто","Сре","Чет","Пет","Суб"],daysMin:["Н","По","У","Ср","Ч","Пе","Су"],months:["Јануар","Фебруар","Март","Април","Мај","Јун","Јул","Август","Септембар","Октобар","Новембар","Децембар"],monthsShort:["Јан","Феб","Мар","Апр","Мај","Јун","Јул","Авг","Сеп","Окт","Нов","Дец"],today:"Данас",weekStart:1,format:"dd.mm.yyyy"}}(jQuery);
|
||||
!function(a){a.fn.datepicker.dates.rs={days:["Недеља","Понедељак","Уторак","Среда","Четвртак","Петак","Субота"],daysShort:["Нед","Пон","Уто","Сре","Чет","Пет","Суб"],daysMin:["Н","По","У","Ср","Ч","Пе","Су"],months:["Јануар","Фебруар","Март","Април","Мај","Јун","Јул","Август","Септембар","Октобар","Новембар","Децембар"],monthsShort:["Јан","Феб","Мар","Апр","Мај","Јун","Јул","Авг","Сеп","Окт","Нов","Дец"],today:"Данас",weekStart:1,format:"dd.mm.yyyy"},a.fn.datepicker.deprecated('This language code "rs" is deprecated (invalid serbian language code) and will be removed in 2.0. For Serbian support use "sr" instead.')}(jQuery);
|
||||
@@ -1 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.ru={days:["Воскресенье","Понедельник","Вторник","Среда","Четверг","Пятница","Суббота"],daysShort:["Вск","Пнд","Втр","Срд","Чтв","Птн","Суб"],daysMin:["Вс","Пн","Вт","Ср","Чт","Пт","Сб"],months:["Январь","Февраль","Март","Апрель","Май","Июнь","Июль","Август","Сентябрь","Октябрь","Ноябрь","Декабрь"],monthsShort:["Янв","Фев","Мар","Апр","Май","Июн","Июл","Авг","Сен","Окт","Ноя","Дек"],today:"Сегодня",clear:"Очистить",format:"dd.mm.yyyy",weekStart:1}}(jQuery);
|
||||
!function(a){a.fn.datepicker.dates.ru={days:["Воскресенье","Понедельник","Вторник","Среда","Четверг","Пятница","Суббота"],daysShort:["Вск","Пнд","Втр","Срд","Чтв","Птн","Суб"],daysMin:["Вс","Пн","Вт","Ср","Чт","Пт","Сб"],months:["Январь","Февраль","Март","Апрель","Май","Июнь","Июль","Август","Сентябрь","Октябрь","Ноябрь","Декабрь"],monthsShort:["Янв","Фев","Мар","Апр","Май","Июн","Июл","Авг","Сен","Окт","Ноя","Дек"],today:"Сегодня",clear:"Очистить",format:"dd.mm.yyyy",weekStart:1,monthsTitle:"Месяцы"}}(jQuery);
|
||||
1
inst/www/shared/datepicker/js/locales/bootstrap-datepicker.si.min.js
vendored
Normal file
1
inst/www/shared/datepicker/js/locales/bootstrap-datepicker.si.min.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.si={days:["ඉරිදා","සඳුදා","අඟහරුවාදා","බදාදා","බ්රහස්පතින්දා","සිකුරාදා","සෙනසුරාදා"],daysShort:["ඉරි","සඳු","අඟ","බදා","බ්රහ","සිකු","සෙන"],daysMin:["ඉ","ස","අ","බ","බ්ර","සි","සෙ"],months:["ජනවාරි","පෙබරවාරි","මාර්තු","අප්රේල්","මැයි","ජුනි","ජූලි","අගෝස්තු","සැප්තැම්බර්","ඔක්තෝබර්","නොවැම්බර්","දෙසැම්බර්"],monthsShort:["ජන","පෙබ","මාර්","අප්රේ","මැයි","ජුනි","ජූලි","අගෝ","සැප්","ඔක්","නොවැ","දෙසැ"],today:"අද",monthsTitle:"මාස",clear:"මකන්න",weekStart:0,format:"yyyy-mm-dd"}}(jQuery);
|
||||
@@ -1 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.sl={days:["Nedelja","Ponedeljek","Torek","Sreda","Četrtek","Petek","Sobota"],daysShort:["Ned","Pon","Tor","Sre","Čet","Pet","Sob"],daysMin:["Ne","Po","To","Sr","Če","Pe","So"],months:["Januar","Februar","Marec","April","Maj","Junij","Julij","Avgust","September","Oktober","November","December"],monthsShort:["Jan","Feb","Mar","Apr","Maj","Jun","Jul","Avg","Sep","Okt","Nov","Dec"],today:"Danes"}}(jQuery);
|
||||
!function(a){a.fn.datepicker.dates.sl={days:["Nedelja","Ponedeljek","Torek","Sreda","Četrtek","Petek","Sobota"],daysShort:["Ned","Pon","Tor","Sre","Čet","Pet","Sob"],daysMin:["Ne","Po","To","Sr","Če","Pe","So"],months:["Januar","Februar","Marec","April","Maj","Junij","Julij","Avgust","September","Oktober","November","December"],monthsShort:["Jan","Feb","Mar","Apr","Maj","Jun","Jul","Avg","Sep","Okt","Nov","Dec"],today:"Danes",weekStart:1}}(jQuery);
|
||||
@@ -1 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.sq={days:["E Diel","E Hënë","E Martē","E Mërkurë","E Enjte","E Premte","E Shtunë"],daysShort:["Die","Hën","Mar","Mër","Enj","Pre","Shtu"],daysMin:["Di","Hë","Ma","Më","En","Pr","Sht"],months:["Janar","Shkurt","Mars","Prill","Maj","Qershor","Korrik","Gusht","Shtator","Tetor","Nëntor","Dhjetor"],monthsShort:["Jan","Shk","Mar","Pri","Maj","Qer","Korr","Gu","Sht","Tet","Nën","Dhjet"],today:"Sot"}}(jQuery);
|
||||
!function(a){a.fn.datepicker.dates.sq={days:["E Diel","E Hënë","E Martē","E Mërkurë","E Enjte","E Premte","E Shtunë"],daysShort:["Die","Hën","Mar","Mër","Enj","Pre","Shtu"],daysMin:["Di","Hë","Ma","Më","En","Pr","Sht"],months:["Janar","Shkurt","Mars","Prill","Maj","Qershor","Korrik","Gusht","Shtator","Tetor","Nëntor","Dhjetor"],monthsShort:["Jan","Shk","Mar","Pri","Maj","Qer","Korr","Gu","Sht","Tet","Nën","Dhjet"],monthsTitle:"Muaj",today:"Sot",weekStart:1,format:"dd/mm/yyyy",clear:"Pastro"}}(jQuery);
|
||||
@@ -1 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.sv={days:["Söndag","Måndag","Tisdag","Onsdag","Torsdag","Fredag","Lördag"],daysShort:["Sön","Mån","Tis","Ons","Tor","Fre","Lör"],daysMin:["Sö","Må","Ti","On","To","Fr","Lö"],months:["Januari","Februari","Mars","April","Maj","Juni","Juli","Augusti","September","Oktober","November","December"],monthsShort:["Jan","Feb","Mar","Apr","Maj","Jun","Jul","Aug","Sep","Okt","Nov","Dec"],today:"Idag",format:"yyyy-mm-dd",weekStart:1,clear:"Rensa"}}(jQuery);
|
||||
!function(a){a.fn.datepicker.dates.sv={days:["söndag","måndag","tisdag","onsdag","torsdag","fredag","lördag"],daysShort:["sön","mån","tis","ons","tor","fre","lör"],daysMin:["sö","må","ti","on","to","fr","lö"],months:["januari","februari","mars","april","maj","juni","juli","augusti","september","oktober","november","december"],monthsShort:["jan","feb","mar","apr","maj","jun","jul","aug","sep","okt","nov","dec"],today:"Idag",format:"yyyy-mm-dd",weekStart:1,clear:"Rensa"}}(jQuery);
|
||||
1
inst/www/shared/datepicker/js/locales/bootstrap-datepicker.ta.min.js
vendored
Normal file
1
inst/www/shared/datepicker/js/locales/bootstrap-datepicker.ta.min.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.ta={days:["ஞாயிறு","திங்கள்","செவ்வாய்","புதன்","வியாழன்","வெள்ளி","சனி"],daysShort:["ஞாயி","திங்","செவ்","புத","வியா","வெள்","சனி"],daysMin:["ஞா","தி","செ","பு","வி","வெ","ச"],months:["ஜனவரி","பிப்ரவரி","மார்ச்","ஏப்ரல்","மே","ஜூன்","ஜூலை","ஆகஸ்டு","செப்டம்பர்","அக்டோபர்","நவம்பர்","டிசம்பர்"],monthsShort:["ஜன","பிப்","மார்","ஏப்","மே","ஜூன்","ஜூலை","ஆக","செப்","அக்","நவ","டிச"],today:"இன்று",monthsTitle:"மாதங்கள்",clear:"நீக்கு",weekStart:1,format:"dd/mm/yyyy"}}(jQuery);
|
||||
1
inst/www/shared/datepicker/js/locales/bootstrap-datepicker.tg.min.js
vendored
Normal file
1
inst/www/shared/datepicker/js/locales/bootstrap-datepicker.tg.min.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.tg={days:["Якшанбе","Душанбе","Сешанбе","Чоршанбе","Панҷшанбе","Ҷумъа","Шанбе"],daysShort:["Яшб","Дшб","Сшб","Чшб","Пшб","Ҷум","Шнб"],daysMin:["Яш","Дш","Сш","Чш","Пш","Ҷм","Шб"],months:["Январ","Феврал","Март","Апрел","Май","Июн","Июл","Август","Сентябр","Октябр","Ноябр","Декабр"],monthsShort:["Янв","Фев","Мар","Апр","Май","Июн","Июл","Авг","Сен","Окт","Ноя","Дек"],today:"Имрӯз",monthsTitle:"Моҳҳо",clear:"Тоза намудан",weekStart:1,format:"dd.mm.yyyy"}}(jQuery);
|
||||
1
inst/www/shared/datepicker/js/locales/bootstrap-datepicker.tk.min.js
vendored
Normal file
1
inst/www/shared/datepicker/js/locales/bootstrap-datepicker.tk.min.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.tk={days:["Ýekşenbe","Duşenbe","Sişenbe","Çarşenbe","Penşenbe","Anna","Şenbe"],daysShort:["Ýek","Duş","Siş","Çar","Pen","Ann","Şen"],daysMin:["Ýe","Du","Si","Ça","Pe","An","Şe"],months:["Ýanwar","Fewral","Mart","Aprel","Maý","Iýun","Iýul","Awgust","Sentýabr","Oktýabr","Noýabr","Dekabr"],monthsShort:["Ýan","Few","Mar","Apr","Maý","Iýn","Iýl","Awg","Sen","Okt","Noý","Dek"],today:"Bu gün",monthsTitle:"Aýlar",clear:"Aýyr",weekStart:1,format:"dd.mm.yyyy"}}(jQuery);
|
||||
1
inst/www/shared/datepicker/js/locales/bootstrap-datepicker.uz-cyrl.min.js
vendored
Normal file
1
inst/www/shared/datepicker/js/locales/bootstrap-datepicker.uz-cyrl.min.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates["uz-cyrl"]={days:["Якшанба","Душанба","Сешанба","Чоршанба","Пайшанба","Жума","Шанба"],daysShort:["Якш","Ду","Се","Чор","Пай","Жу","Ша"],daysMin:["Як","Ду","Се","Чо","Па","Жу","Ша"],months:["Январь","Февраль","Март","Апрель","Май","Июнь","Июль","Август","Сентябрь","Октябрь","Ноябрь","Декабрь"],monthsShort:["Янв","Фев","Мар","Апр","Май","Июн","Июл","Авг","Сен","Окт","Ноя","Дек"],today:"Бугун",clear:"Ўчириш",format:"dd.mm.yyyy",weekStart:1,monthsTitle:"Ойлар"}}(jQuery);
|
||||
1
inst/www/shared/datepicker/js/locales/bootstrap-datepicker.uz-latn.min.js
vendored
Normal file
1
inst/www/shared/datepicker/js/locales/bootstrap-datepicker.uz-latn.min.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates["uz-latn"]={days:["Yakshanba","Dushanba","Seshanba","Chorshanba","Payshanba","Juma","Shanba"],daysShort:["Yak","Du","Se","Chor","Pay","Ju","Sha"],daysMin:["Ya","Du","Se","Cho","Pa","Ju","Sha"],months:["Yanvar","Fevral","Mart","Aprel","May","Iyun","Iyul","Avgust","Sentabr","Oktabr","Noyabr","Dekabr"],monthsShort:["Yan","Fev","Mar","Apr","May","Iyn","Iyl","Avg","Sen","Okt","Noy","Dek"],today:"Bugun",clear:"O'chirish",format:"dd.mm.yyyy",weekStart:1,monthsTitle:"Oylar"}}(jQuery);
|
||||
@@ -1 +1 @@
|
||||
!function(a){a.fn.datepicker.dates["zh-CN"]={days:["星期日","星期一","星期二","星期三","星期四","星期五","星期六"],daysShort:["周日","周一","周二","周三","周四","周五","周六"],daysMin:["日","一","二","三","四","五","六"],months:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],monthsShort:["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],today:"今日",clear:"清除",format:"yyyy年mm月dd日",titleFormat:"yyyy年mm月",weekStart:1}}(jQuery);
|
||||
!function(a){a.fn.datepicker.dates["zh-CN"]={days:["星期日","星期一","星期二","星期三","星期四","星期五","星期六"],daysShort:["周日","周一","周二","周三","周四","周五","周六"],daysMin:["日","一","二","三","四","五","六"],months:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],monthsShort:["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],today:"今天",monthsTitle:"选择月份",clear:"清除",format:"yyyy-mm-dd",titleFormat:"yyyy年mm月",weekStart:1}}(jQuery);
|
||||
92
inst/www/shared/datepicker/scss/build3.scss
Normal file
92
inst/www/shared/datepicker/scss/build3.scss
Normal file
@@ -0,0 +1,92 @@
|
||||
// Datepicker .scss buildfile. Includes select mixins/variables from bootstrap
|
||||
// and imports the included datepicker.scss to output a minimal datepicker.css
|
||||
//
|
||||
// Usage:
|
||||
// lessc build3.scss datepicker.css
|
||||
//
|
||||
// Variables and mixins copied from Bootstrap 3.3.5
|
||||
|
||||
// These are BS3 variables that are used in datepicker3.scss. So, when compiling against
|
||||
// a BS3 bootstraplib theme, these variables should already be defined. Here we set
|
||||
// *defaults* for these variables based on BS4 variables, so this scss can work for
|
||||
// both BS3 and BS4
|
||||
$gray: mix($body-bg, $body-color, 33.5%) !default;
|
||||
$gray-light: mix($body-bg, $body-color, 46.7%) !default;
|
||||
$gray-lighter: mix($body-bg, $body-color, 90%) !default;
|
||||
$brand-primary: $primary !default;
|
||||
$btn-primary-color: $body-bg !default;
|
||||
$btn-primary-bg: $primary !default;
|
||||
$btn-primary-border: mix($body-color, $btn-primary-bg, 5%) !default;
|
||||
$state-info-bg: mix($body-bg, $info, 80%) !default;
|
||||
$border-radius-base: $border-radius !default;
|
||||
$dropdown-border: $dropdown-border-color !default;
|
||||
// These variables are also used in datepicker3.scss, but we don't need to set them since
|
||||
// they're the same in BS3 and BS4
|
||||
//$line-height-base: 1.428571429;
|
||||
//$btn-link-disabled-color: $gray-light;
|
||||
//$dropdown-bg: #fff;
|
||||
|
||||
// Setup BS4 style color contrasting
|
||||
$yiq-contrasted-threshold: 150 !default;
|
||||
$yiq-text-dark: #212529 !default;
|
||||
$yiq-text-light: #fff !default;
|
||||
|
||||
@function color-yiq($color, $dark: $yiq-text-dark, $light: $yiq-text-light) {
|
||||
$r: red($color);
|
||||
$g: green($color);
|
||||
$b: blue($color);
|
||||
|
||||
$yiq: (($r * 299) + ($g * 587) + ($b * 114)) / 1000;
|
||||
|
||||
@if ($yiq >= $yiq-contrasted-threshold) {
|
||||
@return $dark;
|
||||
} @else {
|
||||
@return $light;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin button-variant($background, $border) {
|
||||
$color: color-yiq($background);
|
||||
|
||||
color: $color;
|
||||
background-color: $background;
|
||||
border-color: $border;
|
||||
|
||||
&:focus,
|
||||
&.focus {
|
||||
color: $color;
|
||||
background-color: mix($background, $color, 90%);
|
||||
border-color: mix($border, $color, 75%);
|
||||
}
|
||||
&:hover {
|
||||
color: $color;
|
||||
background-color: mix($background, $color, 50%);
|
||||
border-color: mix($border, $color, 88%);
|
||||
}
|
||||
&:active,
|
||||
&.active {
|
||||
color: $color;
|
||||
background-color: mix($background, $color, 90%);
|
||||
border-color: mix($border, $color, 88%);
|
||||
|
||||
&:hover,
|
||||
&:focus,
|
||||
&.focus {
|
||||
color: $color;
|
||||
background-color: mix($background, $color, 83%);
|
||||
border-color: mix($border, $color, 75%);
|
||||
}
|
||||
}
|
||||
&.disabled,
|
||||
&[disabled],
|
||||
fieldset[disabled] & {
|
||||
&:hover,
|
||||
&:focus,
|
||||
&.focus {
|
||||
background-color: $background;
|
||||
border-color: $border;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@import "datepicker3.scss";
|
||||
260
inst/www/shared/datepicker/scss/datepicker3.scss
Normal file
260
inst/www/shared/datepicker/scss/datepicker3.scss
Normal file
@@ -0,0 +1,260 @@
|
||||
.datepicker {
|
||||
border-radius: $border-radius-base;
|
||||
&-inline {
|
||||
width: 220px;
|
||||
}
|
||||
direction: ltr;
|
||||
&-rtl {
|
||||
direction: rtl;
|
||||
&.dropdown-menu { left: auto; }
|
||||
table tr td span {
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
&-dropdown {
|
||||
top: 0;
|
||||
left: 0;
|
||||
padding: 4px;
|
||||
&:before {
|
||||
content: '';
|
||||
display: inline-block;
|
||||
border-left: 7px solid transparent;
|
||||
border-right: 7px solid transparent;
|
||||
border-bottom: 7px solid $dropdown-border;
|
||||
border-top: 0;
|
||||
border-bottom-color: rgba(0,0,0,.2);
|
||||
position: absolute;
|
||||
}
|
||||
&:after {
|
||||
content: '';
|
||||
display: inline-block;
|
||||
border-left: 6px solid transparent;
|
||||
border-right: 6px solid transparent;
|
||||
border-bottom: 6px solid $dropdown-bg;
|
||||
border-top: 0;
|
||||
position: absolute;
|
||||
}
|
||||
&.datepicker-orient-left:before { left: 6px; }
|
||||
&.datepicker-orient-left:after { left: 7px; }
|
||||
&.datepicker-orient-right:before { right: 6px; }
|
||||
&.datepicker-orient-right:after { right: 7px; }
|
||||
&.datepicker-orient-bottom:before { top: -7px; }
|
||||
&.datepicker-orient-bottom:after { top: -6px; }
|
||||
&.datepicker-orient-top:before {
|
||||
bottom: -7px;
|
||||
border-bottom: 0;
|
||||
border-top: 7px solid $dropdown-border;
|
||||
}
|
||||
&.datepicker-orient-top:after {
|
||||
bottom: -6px;
|
||||
border-bottom: 0;
|
||||
border-top: 6px solid $dropdown-bg;
|
||||
}
|
||||
}
|
||||
table {
|
||||
margin: 0;
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
tr {
|
||||
td, th {
|
||||
text-align: center;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
border-radius: 4px;
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Inline display inside a table presents some problems with
|
||||
// border and background colors.
|
||||
.table-striped & table tr {
|
||||
td, th {
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
table tr td {
|
||||
&.old,
|
||||
&.new {
|
||||
color: $btn-link-disabled-color;
|
||||
}
|
||||
&.day:hover,
|
||||
&.focused {
|
||||
color: color-yiq($gray-lighter);
|
||||
background: $gray-lighter;
|
||||
cursor: pointer;
|
||||
}
|
||||
&.disabled,
|
||||
&.disabled:hover {
|
||||
background: none;
|
||||
color: $btn-link-disabled-color;
|
||||
cursor: default;
|
||||
}
|
||||
&.highlighted {
|
||||
$highlighted-bg: $state-info-bg;
|
||||
@include button-variant($highlighted-bg, darken($highlighted-bg, 20%));
|
||||
border-radius: 0;
|
||||
|
||||
&.focused {
|
||||
background: darken($highlighted-bg, 10%);
|
||||
}
|
||||
|
||||
&.disabled,
|
||||
&.disabled:active {
|
||||
background: $highlighted-bg;
|
||||
color: $btn-link-disabled-color;
|
||||
}
|
||||
}
|
||||
&.today {
|
||||
$today-bg: lighten(orange, 30%);
|
||||
@include button-variant($today-bg, darken($today-bg, 20%));
|
||||
|
||||
&.focused {
|
||||
background: darken($today-bg, 10%);
|
||||
}
|
||||
|
||||
&.disabled,
|
||||
&.disabled:active {
|
||||
background: $today-bg;
|
||||
color: $btn-link-disabled-color;
|
||||
}
|
||||
}
|
||||
&.range {
|
||||
$range-bg: $gray-lighter;
|
||||
@include button-variant($range-bg, darken($range-bg, 20%));
|
||||
border-radius: 0;
|
||||
|
||||
&.focused {
|
||||
background: darken($range-bg, 10%);
|
||||
}
|
||||
|
||||
&.disabled,
|
||||
&.disabled:active {
|
||||
background: $range-bg;
|
||||
color: $btn-link-disabled-color;
|
||||
}
|
||||
}
|
||||
&.range.highlighted {
|
||||
$range-highlighted-bg: mix($state-info-bg, $gray-lighter, 50%);
|
||||
@include button-variant($range-highlighted-bg, darken($range-highlighted-bg, 20%));
|
||||
|
||||
&.focused {
|
||||
background: darken($range-highlighted-bg, 10%);
|
||||
}
|
||||
|
||||
&.disabled,
|
||||
&.disabled:active {
|
||||
background: $range-highlighted-bg;
|
||||
color: $btn-link-disabled-color;
|
||||
}
|
||||
}
|
||||
&.range.today {
|
||||
$range-today-bg: mix(orange, $gray-lighter, 50%);
|
||||
@include button-variant($range-today-bg, darken($range-today-bg, 20%));
|
||||
|
||||
&.disabled,
|
||||
&.disabled:active {
|
||||
background: $range-today-bg;
|
||||
color: $btn-link-disabled-color;
|
||||
}
|
||||
}
|
||||
&.selected,
|
||||
&.selected.highlighted {
|
||||
@include button-variant($gray-light, $gray);
|
||||
text-shadow: 0 -1px 0 rgba(0,0,0,.25);
|
||||
}
|
||||
&.active,
|
||||
&.active.highlighted {
|
||||
@include button-variant($btn-primary-bg, $btn-primary-border);
|
||||
text-shadow: 0 -1px 0 rgba(0,0,0,.25);
|
||||
}
|
||||
span {
|
||||
display: block;
|
||||
width: 23%;
|
||||
height: 54px;
|
||||
line-height: 54px;
|
||||
float: left;
|
||||
margin: 1%;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
&:hover,
|
||||
&.focused {
|
||||
color: color-yiq($gray-lighter);
|
||||
background: $gray-lighter;
|
||||
}
|
||||
&.disabled,
|
||||
&.disabled:hover {
|
||||
background: none;
|
||||
color: $btn-link-disabled-color;
|
||||
cursor: default;
|
||||
}
|
||||
&.active,
|
||||
&.active:hover,
|
||||
&.active.disabled,
|
||||
&.active.disabled:hover {
|
||||
@include button-variant($btn-primary-bg, $btn-primary-border);
|
||||
text-shadow: 0 -1px 0 rgba(0,0,0,.25);
|
||||
}
|
||||
&.old,
|
||||
&.new {
|
||||
color: $btn-link-disabled-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.datepicker-switch {
|
||||
width: 145px;
|
||||
}
|
||||
|
||||
.datepicker-switch,
|
||||
.prev,
|
||||
.next,
|
||||
tfoot tr th {
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
color: color-yiq($gray-lighter);
|
||||
background: $gray-lighter;
|
||||
}
|
||||
}
|
||||
|
||||
.prev, .next {
|
||||
&.disabled {
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
// Basic styling for calendar-week cells
|
||||
.cw {
|
||||
font-size: 10px;
|
||||
width: 12px;
|
||||
padding: 0 2px 0 5px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
.input-group.date .input-group-addon {
|
||||
cursor: pointer;
|
||||
}
|
||||
.input-daterange {
|
||||
width: 100%;
|
||||
input {
|
||||
text-align: center;
|
||||
}
|
||||
input:first-child {
|
||||
border-radius: 3px 0 0 3px;
|
||||
}
|
||||
input:last-child {
|
||||
border-radius: 0 3px 3px 0;
|
||||
}
|
||||
.input-group-addon {
|
||||
width: auto;
|
||||
min-width: 16px;
|
||||
padding: 4px 5px;
|
||||
line-height: $line-height-base;
|
||||
border-width: 1px 0;
|
||||
margin-left: -5px;
|
||||
margin-right: -5px;
|
||||
}
|
||||
}
|
||||
@@ -1,150 +1,264 @@
|
||||
/* Ion.RangeSlider
|
||||
// css version 2.0.3
|
||||
// © 2013-2014 Denis Ineshin | IonDen.com
|
||||
// ===================================================================================================================*/
|
||||
|
||||
/* =====================================================================================================================
|
||||
// RangeSlider */
|
||||
|
||||
@charset "UTF-8";
|
||||
/* 'shiny' skin for Ion.RangeSlider, largely based on the 'big' skin, but with smaller dimensions, grayscale grid text, and without gradients
|
||||
© RStudio, Inc, 2014
|
||||
© Denis Ineshin, 2014 https://github.com/IonDen
|
||||
© guybowden, 2014 https://github.com/guybowden
|
||||
*/
|
||||
.irs {
|
||||
position: relative; display: block;
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
position: relative;
|
||||
display: block;
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
font-size: 12px;
|
||||
font-family: Arial, sans-serif;
|
||||
}
|
||||
.irs-line {
|
||||
position: relative; display: block;
|
||||
overflow: hidden;
|
||||
outline: none !important;
|
||||
}
|
||||
.irs-line-left, .irs-line-mid, .irs-line-right {
|
||||
position: absolute; display: block;
|
||||
top: 0;
|
||||
}
|
||||
.irs-line-left {
|
||||
left: 0; width: 11%;
|
||||
}
|
||||
.irs-line-mid {
|
||||
left: 9%; width: 82%;
|
||||
}
|
||||
.irs-line-right {
|
||||
right: 0; width: 11%;
|
||||
}
|
||||
|
||||
.irs-bar {
|
||||
position: absolute; display: block;
|
||||
left: 0; width: 0;
|
||||
}
|
||||
.irs-bar-edge {
|
||||
position: absolute; display: block;
|
||||
top: 0; left: 0;
|
||||
}
|
||||
.irs-line {
|
||||
position: relative;
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
outline: none !important;
|
||||
}
|
||||
|
||||
.irs-shadow {
|
||||
position: absolute; display: none;
|
||||
left: 0; width: 0;
|
||||
}
|
||||
.irs-bar {
|
||||
position: absolute;
|
||||
display: block;
|
||||
left: 0;
|
||||
width: 0;
|
||||
}
|
||||
|
||||
.irs-slider {
|
||||
position: absolute; display: block;
|
||||
cursor: default;
|
||||
z-index: 1;
|
||||
}
|
||||
.irs-slider.single {
|
||||
.irs-shadow {
|
||||
position: absolute;
|
||||
display: none;
|
||||
left: 0;
|
||||
width: 0;
|
||||
}
|
||||
|
||||
}
|
||||
.irs-slider.from {
|
||||
.irs-handle {
|
||||
position: absolute;
|
||||
display: block;
|
||||
box-sizing: border-box;
|
||||
cursor: pointer;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
}
|
||||
.irs-slider.to {
|
||||
.irs-handle.type_last {
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
}
|
||||
.irs-slider.type_last {
|
||||
z-index: 2;
|
||||
}
|
||||
.irs-min, .irs-max {
|
||||
position: absolute;
|
||||
display: block;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.irs-min {
|
||||
position: absolute; display: block;
|
||||
left: 0;
|
||||
cursor: default;
|
||||
}
|
||||
.irs-max {
|
||||
position: absolute; display: block;
|
||||
right: 0;
|
||||
cursor: default;
|
||||
}
|
||||
.irs-min {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.irs-from, .irs-to, .irs-single {
|
||||
position: absolute; display: block;
|
||||
top: 0; left: 0;
|
||||
cursor: default;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.irs-max {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.irs-from, .irs-to, .irs-single {
|
||||
position: absolute;
|
||||
display: block;
|
||||
top: 0;
|
||||
left: 0;
|
||||
cursor: default;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.irs-grid {
|
||||
position: absolute; display: none;
|
||||
bottom: 0; left: 0;
|
||||
width: 100%; height: 20px;
|
||||
position: absolute;
|
||||
display: none;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.irs-with-grid .irs-grid {
|
||||
display: block;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.irs-grid-pol {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 1px;
|
||||
height: 8px;
|
||||
background: #000;
|
||||
}
|
||||
|
||||
.irs-grid-pol.small {
|
||||
height: 4px;
|
||||
}
|
||||
|
||||
.irs-grid-text {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
font-size: 9px;
|
||||
line-height: 9px;
|
||||
padding: 0 3px;
|
||||
color: #000;
|
||||
}
|
||||
.irs-grid-pol {
|
||||
position: absolute;
|
||||
top: 0; left: 0;
|
||||
width: 1px; height: 8px;
|
||||
background: #000;
|
||||
}
|
||||
.irs-grid-pol.small {
|
||||
height: 4px;
|
||||
}
|
||||
.irs-grid-text {
|
||||
position: absolute;
|
||||
bottom: 0; left: 0;
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
font-size: 9px; line-height: 9px;
|
||||
padding: 0 3px;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.irs-disable-mask {
|
||||
position: absolute; display: block;
|
||||
top: 0; left: -1%;
|
||||
width: 102%; height: 100%;
|
||||
cursor: default;
|
||||
background: rgba(0,0,0,0.0);
|
||||
z-index: 2;
|
||||
position: absolute;
|
||||
display: block;
|
||||
top: 0;
|
||||
left: -1%;
|
||||
width: 102%;
|
||||
height: 100%;
|
||||
cursor: default;
|
||||
background: rgba(0, 0, 0, 0);
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.lt-ie9 .irs-disable-mask {
|
||||
background: #000;
|
||||
filter: alpha(opacity=0);
|
||||
cursor: not-allowed;
|
||||
background: #000;
|
||||
filter: alpha(opacity=0);
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.irs-disabled {
|
||||
opacity: 0.4;
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
|
||||
.irs-hidden-input {
|
||||
position: absolute !important;
|
||||
display: block !important;
|
||||
top: 0 !important;
|
||||
left: 0 !important;
|
||||
width: 0 !important;
|
||||
height: 0 !important;
|
||||
font-size: 0 !important;
|
||||
line-height: 0 !important;
|
||||
padding: 0 !important;
|
||||
margin: 0 !important;
|
||||
overflow: hidden;
|
||||
outline: none !important;
|
||||
z-index: -9999 !important;
|
||||
background: none !important;
|
||||
border-style: solid !important;
|
||||
border-color: transparent !important;
|
||||
position: absolute !important;
|
||||
display: block !important;
|
||||
top: 0 !important;
|
||||
left: 0 !important;
|
||||
width: 0 !important;
|
||||
height: 0 !important;
|
||||
font-size: 0 !important;
|
||||
line-height: 0 !important;
|
||||
padding: 0 !important;
|
||||
margin: 0 !important;
|
||||
overflow: hidden;
|
||||
outline: none !important;
|
||||
z-index: -9999 !important;
|
||||
background: none !important;
|
||||
border-style: solid !important;
|
||||
border-color: transparent !important;
|
||||
}
|
||||
|
||||
.irs {
|
||||
font-family: Arial, sans-serif;
|
||||
}
|
||||
|
||||
.irs--shiny {
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.irs--shiny.irs-with-grid {
|
||||
height: 60px;
|
||||
}
|
||||
|
||||
.irs--shiny .irs-line {
|
||||
top: 25px;
|
||||
height: 8px;
|
||||
background: linear-gradient(to bottom, #dedede -50%, white 150%);
|
||||
background-color: #ededed;
|
||||
border: 1px solid #cccccc;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.irs--shiny .irs-bar {
|
||||
top: 25px;
|
||||
height: 8px;
|
||||
border-top: 1px solid #428bca;
|
||||
border-bottom: 1px solid #428bca;
|
||||
background: #428bca;
|
||||
}
|
||||
|
||||
.irs--shiny .irs-bar--single {
|
||||
border-radius: 8px 0 0 8px;
|
||||
}
|
||||
|
||||
.irs--shiny .irs-shadow {
|
||||
top: 38px;
|
||||
height: 2px;
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.irs--shiny .lt-ie9 .irs-shadow {
|
||||
filter: alpha(opacity=30);
|
||||
}
|
||||
|
||||
.irs--shiny .irs-handle {
|
||||
top: 17px;
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
border: 1px solid #ababab;
|
||||
background-color: #dedede;
|
||||
box-shadow: 1px 1px 3px rgba(255, 255, 255, 0.3);
|
||||
border-radius: 22px;
|
||||
}
|
||||
|
||||
.irs--shiny .irs-handle.state_hover, .irs--shiny .irs-handle:hover {
|
||||
background: white;
|
||||
}
|
||||
|
||||
.irs--shiny .irs-min,
|
||||
.irs--shiny .irs-max {
|
||||
top: 0;
|
||||
padding: 1px 3px;
|
||||
color: #333333;
|
||||
text-shadow: none;
|
||||
background-color: rgba(0, 0, 0, 0.1);
|
||||
border-radius: 3px;
|
||||
font-size: 10px;
|
||||
line-height: 1.333;
|
||||
}
|
||||
|
||||
.irs--shiny .lt-ie9 .irs-min,
|
||||
.irs--shiny .lt-ie9 .irs-max {
|
||||
background: #cccccc;
|
||||
}
|
||||
|
||||
.irs--shiny .irs-from,
|
||||
.irs--shiny .irs-to,
|
||||
.irs--shiny .irs-single {
|
||||
color: #fff;
|
||||
text-shadow: none;
|
||||
padding: 1px 3px;
|
||||
background-color: #428bca;
|
||||
border-radius: 3px;
|
||||
font-size: 11px;
|
||||
line-height: 1.333;
|
||||
}
|
||||
|
||||
.irs--shiny .lt-ie9 .irs-from,
|
||||
.irs--shiny .lt-ie9 .irs-to,
|
||||
.irs--shiny .lt-ie9 .irs-single {
|
||||
background: #999999;
|
||||
}
|
||||
|
||||
.irs--shiny .irs-grid {
|
||||
height: 27px;
|
||||
}
|
||||
|
||||
.irs--shiny .irs-grid-pol {
|
||||
background-color: black;
|
||||
}
|
||||
|
||||
.irs--shiny .irs-grid-text {
|
||||
bottom: 5px;
|
||||
color: #1a1a1a;
|
||||
}
|
||||
|
||||
.irs--shiny .irs-grid-pol.small {
|
||||
background-color: #999999;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,106 +0,0 @@
|
||||
/* Ion.RangeSlider, Flat UI Skin
|
||||
// css version 2.0.3
|
||||
// © Denis Ineshin, 2014 https://github.com/IonDen
|
||||
// ===================================================================================================================*/
|
||||
|
||||
/* =====================================================================================================================
|
||||
// Skin details */
|
||||
|
||||
.irs-line-mid,
|
||||
.irs-line-left,
|
||||
.irs-line-right,
|
||||
.irs-bar,
|
||||
.irs-bar-edge,
|
||||
.irs-slider {
|
||||
background: url(../img/sprite-skin-flat.png) repeat-x;
|
||||
}
|
||||
|
||||
.irs {
|
||||
height: 40px;
|
||||
}
|
||||
.irs-with-grid {
|
||||
height: 60px;
|
||||
}
|
||||
.irs-line {
|
||||
height: 12px; top: 25px;
|
||||
}
|
||||
.irs-line-left {
|
||||
height: 12px;
|
||||
background-position: 0 -30px;
|
||||
}
|
||||
.irs-line-mid {
|
||||
height: 12px;
|
||||
background-position: 0 0;
|
||||
}
|
||||
.irs-line-right {
|
||||
height: 12px;
|
||||
background-position: 100% -30px;
|
||||
}
|
||||
|
||||
.irs-bar {
|
||||
height: 12px; top: 25px;
|
||||
background-position: 0 -60px;
|
||||
}
|
||||
.irs-bar-edge {
|
||||
top: 25px;
|
||||
height: 12px; width: 9px;
|
||||
background-position: 0 -90px;
|
||||
}
|
||||
|
||||
.irs-shadow {
|
||||
height: 3px; top: 34px;
|
||||
background: #000;
|
||||
opacity: 0.25;
|
||||
}
|
||||
.lt-ie9 .irs-shadow {
|
||||
filter: alpha(opacity=25);
|
||||
}
|
||||
|
||||
.irs-slider {
|
||||
width: 16px; height: 18px;
|
||||
top: 22px;
|
||||
background-position: 0 -120px;
|
||||
}
|
||||
.irs-slider.state_hover, .irs-slider:hover {
|
||||
background-position: 0 -150px;
|
||||
}
|
||||
|
||||
.irs-min, .irs-max {
|
||||
color: #999;
|
||||
font-size: 10px; line-height: 1.333;
|
||||
text-shadow: none;
|
||||
top: 0; padding: 1px 3px;
|
||||
background: #e1e4e9;
|
||||
-moz-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.irs-from, .irs-to, .irs-single {
|
||||
color: #fff;
|
||||
font-size: 10px; line-height: 1.333;
|
||||
text-shadow: none;
|
||||
padding: 1px 5px;
|
||||
background: #ed5565;
|
||||
-moz-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.irs-from:after, .irs-to:after, .irs-single:after {
|
||||
position: absolute; display: block; content: "";
|
||||
bottom: -6px; left: 50%;
|
||||
width: 0; height: 0;
|
||||
margin-left: -3px;
|
||||
overflow: hidden;
|
||||
border: 3px solid transparent;
|
||||
border-top-color: #ed5565;
|
||||
}
|
||||
|
||||
|
||||
.irs-grid-pol {
|
||||
background: #e1e4e9;
|
||||
}
|
||||
.irs-grid-text {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.irs-disabled {
|
||||
}
|
||||
@@ -1,124 +0,0 @@
|
||||
/* Ion.RangeSlider, Simple Skin
|
||||
// css version 2.0.3
|
||||
// © Denis Ineshin, 2014 https://github.com/IonDen
|
||||
// © guybowden, 2014 https://github.com/guybowden
|
||||
// ===================================================================================================================*/
|
||||
|
||||
/* =====================================================================================================================
|
||||
// Skin details */
|
||||
|
||||
.irs {
|
||||
height: 55px;
|
||||
}
|
||||
.irs-with-grid {
|
||||
height: 75px;
|
||||
}
|
||||
.irs-line {
|
||||
height: 10px; top: 33px;
|
||||
background: #EEE;
|
||||
background: linear-gradient(to bottom, #DDD -50%, #FFF 150%); /* W3C */
|
||||
border: 1px solid #CCC;
|
||||
border-radius: 16px;
|
||||
-moz-border-radius: 16px;
|
||||
}
|
||||
.irs-line-left {
|
||||
height: 8px;
|
||||
}
|
||||
.irs-line-mid {
|
||||
height: 8px;
|
||||
}
|
||||
.irs-line-right {
|
||||
height: 8px;
|
||||
}
|
||||
|
||||
.irs-bar {
|
||||
height: 10px; top: 33px;
|
||||
border-top: 1px solid #428bca;
|
||||
border-bottom: 1px solid #428bca;
|
||||
background: #428bca;
|
||||
background: linear-gradient(to top, rgba(66,139,202,1) 0%,rgba(127,195,232,1) 100%); /* W3C */
|
||||
}
|
||||
.irs-bar-edge {
|
||||
height: 10px; top: 33px;
|
||||
width: 14px;
|
||||
border: 1px solid #428bca;
|
||||
border-right: 0;
|
||||
background: #428bca;
|
||||
background: linear-gradient(to top, rgba(66,139,202,1) 0%,rgba(127,195,232,1) 100%); /* W3C */
|
||||
border-radius: 16px 0 0 16px;
|
||||
-moz-border-radius: 16px 0 0 16px;
|
||||
}
|
||||
|
||||
.irs-shadow {
|
||||
height: 2px; top: 38px;
|
||||
background: #000;
|
||||
opacity: 0.3;
|
||||
border-radius: 5px;
|
||||
-moz-border-radius: 5px;
|
||||
}
|
||||
.lt-ie9 .irs-shadow {
|
||||
filter: alpha(opacity=30);
|
||||
}
|
||||
|
||||
.irs-slider {
|
||||
top: 25px;
|
||||
width: 27px; height: 27px;
|
||||
border: 1px solid #AAA;
|
||||
background: #DDD;
|
||||
background: linear-gradient(to bottom, rgba(255,255,255,1) 0%,rgba(220,220,220,1) 20%,rgba(255,255,255,1) 100%); /* W3C */
|
||||
border-radius: 27px;
|
||||
-moz-border-radius: 27px;
|
||||
box-shadow: 1px 1px 3px rgba(0,0,0,0.3);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.irs-slider.state_hover, .irs-slider:hover {
|
||||
background: #FFF;
|
||||
}
|
||||
|
||||
.irs-min, .irs-max {
|
||||
color: #333;
|
||||
font-size: 12px; line-height: 1.333;
|
||||
text-shadow: none;
|
||||
top: 0;
|
||||
padding: 1px 5px;
|
||||
background: rgba(0,0,0,0.1);
|
||||
border-radius: 3px;
|
||||
-moz-border-radius: 3px;
|
||||
}
|
||||
|
||||
.lt-ie9 .irs-min, .lt-ie9 .irs-max {
|
||||
background: #ccc;
|
||||
}
|
||||
|
||||
.irs-from, .irs-to, .irs-single {
|
||||
color: #fff;
|
||||
font-size: 14px; line-height: 1.333;
|
||||
text-shadow: none;
|
||||
padding: 1px 5px;
|
||||
background: #428bca;
|
||||
border-radius: 3px;
|
||||
-moz-border-radius: 3px;
|
||||
}
|
||||
.lt-ie9 .irs-from, .lt-ie9 .irs-to, .lt-ie9 .irs-single {
|
||||
background: #999;
|
||||
}
|
||||
|
||||
.irs-grid {
|
||||
height: 27px;
|
||||
}
|
||||
.irs-grid-pol {
|
||||
opacity: 0.5;
|
||||
background: #428bca;
|
||||
}
|
||||
.irs-grid-pol.small {
|
||||
background: #999;
|
||||
}
|
||||
|
||||
.irs-grid-text {
|
||||
bottom: 5px;
|
||||
color: #99a4ac;
|
||||
}
|
||||
|
||||
.irs-disabled {
|
||||
}
|
||||
@@ -1,116 +0,0 @@
|
||||
/* Ion.RangeSlider, Modern Skin
|
||||
// css version 2.0.3
|
||||
// © Denis Ineshin, 2014 https://github.com/IonDen
|
||||
// ===================================================================================================================*/
|
||||
|
||||
/* =====================================================================================================================
|
||||
// Skin details */
|
||||
|
||||
.irs-line-mid,
|
||||
.irs-line-left,
|
||||
.irs-line-right,
|
||||
.irs-bar,
|
||||
.irs-bar-edge,
|
||||
.irs-slider {
|
||||
background: url(../img/sprite-skin-modern.png) repeat-x;
|
||||
}
|
||||
|
||||
.irs {
|
||||
height: 50px;
|
||||
}
|
||||
.irs-with-grid {
|
||||
height: 70px;
|
||||
}
|
||||
.irs-line {
|
||||
height: 6px; top: 25px;
|
||||
}
|
||||
.irs-line-left {
|
||||
height: 6px;
|
||||
background-position: 0 -30px;
|
||||
}
|
||||
.irs-line-mid {
|
||||
height: 6px;
|
||||
background-position: 0 0;
|
||||
}
|
||||
.irs-line-right {
|
||||
height: 6px;
|
||||
background-position: 100% -30px;
|
||||
}
|
||||
|
||||
.irs-bar {
|
||||
height: 6px; top: 25px;
|
||||
background-position: 0 -60px;
|
||||
}
|
||||
.irs-bar-edge {
|
||||
top: 25px;
|
||||
height: 6px; width: 6px;
|
||||
background-position: 0 -90px;
|
||||
}
|
||||
|
||||
.irs-shadow {
|
||||
height: 5px; top: 25px;
|
||||
background: #000;
|
||||
opacity: 0.25;
|
||||
}
|
||||
.lt-ie9 .irs-shadow {
|
||||
filter: alpha(opacity=25);
|
||||
}
|
||||
|
||||
.irs-slider {
|
||||
width: 11px; height: 18px;
|
||||
top: 31px;
|
||||
background-position: 0 -120px;
|
||||
}
|
||||
.irs-slider.state_hover, .irs-slider:hover {
|
||||
background-position: 0 -150px;
|
||||
}
|
||||
|
||||
.irs-min, .irs-max {
|
||||
color: #999;
|
||||
font-size: 10px; line-height: 1.333;
|
||||
text-shadow: none;
|
||||
top: 0; padding: 1px 3px;
|
||||
background: #e1e4e9;
|
||||
-moz-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.irs-from, .irs-to, .irs-single {
|
||||
color: #fff;
|
||||
font-size: 10px; line-height: 1.333;
|
||||
text-shadow: none;
|
||||
padding: 1px 5px;
|
||||
background: #20b426;
|
||||
-moz-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.irs-from:after, .irs-to:after, .irs-single:after {
|
||||
position: absolute; display: block; content: "";
|
||||
bottom: -6px; left: 50%;
|
||||
width: 0; height: 0;
|
||||
margin-left: -3px;
|
||||
overflow: hidden;
|
||||
border: 3px solid transparent;
|
||||
border-top-color: #20b426;
|
||||
}
|
||||
|
||||
.irs-grid {
|
||||
height: 34px;
|
||||
}
|
||||
.irs-grid-pol {
|
||||
background: #c0c0c0;
|
||||
}
|
||||
.irs-grid-text {
|
||||
bottom: 12px;
|
||||
color: #c0c0c0;
|
||||
}
|
||||
|
||||
.irs-disable-mask {
|
||||
|
||||
}
|
||||
.irs-disabled {
|
||||
|
||||
}
|
||||
.lt-ie9 .irs-disabled {
|
||||
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
/* Ion.RangeSlider, Nice Skin
|
||||
// css version 2.0.3
|
||||
// © Denis Ineshin, 2014 https://github.com/IonDen
|
||||
// ===================================================================================================================*/
|
||||
|
||||
/* =====================================================================================================================
|
||||
// Skin details */
|
||||
|
||||
.irs-line-mid,
|
||||
.irs-line-left,
|
||||
.irs-line-right,
|
||||
.irs-bar,
|
||||
.irs-bar-edge,
|
||||
.irs-slider {
|
||||
background: url(../img/sprite-skin-nice.png) repeat-x;
|
||||
}
|
||||
|
||||
.irs {
|
||||
height: 40px;
|
||||
}
|
||||
.irs-with-grid {
|
||||
height: 60px;
|
||||
}
|
||||
.irs-line {
|
||||
height: 8px; top: 25px;
|
||||
}
|
||||
.irs-line-left {
|
||||
height: 8px;
|
||||
background-position: 0 -30px;
|
||||
}
|
||||
.irs-line-mid {
|
||||
height: 8px;
|
||||
background-position: 0 0;
|
||||
}
|
||||
.irs-line-right {
|
||||
height: 8px;
|
||||
background-position: 100% -30px;
|
||||
}
|
||||
|
||||
.irs-bar {
|
||||
height: 8px; top: 25px;
|
||||
background-position: 0 -60px;
|
||||
}
|
||||
.irs-bar-edge {
|
||||
top: 25px;
|
||||
height: 8px; width: 11px;
|
||||
background-position: 0 -90px;
|
||||
}
|
||||
|
||||
.irs-shadow {
|
||||
height: 1px; top: 34px;
|
||||
background: #000;
|
||||
opacity: 0.15;
|
||||
}
|
||||
.lt-ie9 .irs-shadow {
|
||||
filter: alpha(opacity=15);
|
||||
}
|
||||
|
||||
.irs-slider {
|
||||
width: 22px; height: 22px;
|
||||
top: 17px;
|
||||
background-position: 0 -120px;
|
||||
}
|
||||
.irs-slider.state_hover, .irs-slider:hover {
|
||||
background-position: 0 -150px;
|
||||
}
|
||||
|
||||
.irs-min, .irs-max {
|
||||
color: #999;
|
||||
font-size: 10px; line-height: 1.333;
|
||||
text-shadow: none;
|
||||
top: 0; padding: 1px 3px;
|
||||
background: rgba(0,0,0,0.1);
|
||||
-moz-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.lt-ie9 .irs-min, .lt-ie9 .irs-max {
|
||||
background: #ccc;
|
||||
}
|
||||
|
||||
.irs-from, .irs-to, .irs-single {
|
||||
color: #fff;
|
||||
font-size: 10px; line-height: 1.333;
|
||||
text-shadow: none;
|
||||
padding: 1px 5px;
|
||||
background: rgba(0,0,0,0.3);
|
||||
-moz-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.lt-ie9 .irs-from, .lt-ie9 .irs-to, .lt-ie9 .irs-single {
|
||||
background: #999;
|
||||
}
|
||||
|
||||
.irs-grid-pol {
|
||||
background: #99a4ac;
|
||||
}
|
||||
.irs-grid-text {
|
||||
color: #99a4ac;
|
||||
}
|
||||
|
||||
.irs-disabled {
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
/* Ion.RangeSlider, Round Skin
|
||||
// css version 2.2.0
|
||||
// © Denis Ineshin, 2014 https://github.com/IonDen
|
||||
// © Veaceslav Grimalschi, 2018 https://github.com/grimalschi
|
||||
// ===================================================================================================================*/
|
||||
|
||||
/* =====================================================================================================================
|
||||
// Skin details */
|
||||
|
||||
.irs {
|
||||
height: 50px;
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
.irs-with-grid {
|
||||
height: 67px;
|
||||
}
|
||||
|
||||
.irs-line {
|
||||
top: 36px;
|
||||
height: 4px;
|
||||
background: #DEE4EC;
|
||||
border-radius: 16px;
|
||||
}
|
||||
|
||||
.irs-bar, .irs-bar-edge {
|
||||
top: 36px;
|
||||
height: 4px;
|
||||
background: #006CFA;
|
||||
}
|
||||
.irs-bar-edge {
|
||||
width: 12px;
|
||||
}
|
||||
|
||||
.irs-shadow {
|
||||
height: 4px;
|
||||
top: 40px;
|
||||
background: #DEE4EC;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.lt-ie9 .irs-shadow {
|
||||
filter: alpha(opacity=25);
|
||||
}
|
||||
|
||||
.irs-slider {
|
||||
top: 35px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-top: -10px;
|
||||
border: 4px solid #006CFA;
|
||||
background: white;
|
||||
border-radius: 27px;
|
||||
box-shadow: 0 1px 3px rgba(0,0,255,0.3);
|
||||
cursor: pointer;
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
.irs-slider.state_hover, .irs-slider:hover {
|
||||
background: #f0f6ff;
|
||||
}
|
||||
|
||||
.irs-min, .irs-max {
|
||||
color: #333;
|
||||
font-size: 14px;
|
||||
top: 0;
|
||||
padding: 3px 5px;
|
||||
background: rgba(0,0,0,0.1);
|
||||
border-radius: 3px;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.irs-from, .irs-to, .irs-single {
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
text-shadow: none;
|
||||
padding: 3px 5px;
|
||||
background: #006CFA;
|
||||
border-radius: 3px;
|
||||
line-height: 1;
|
||||
}
|
||||
.irs-from:after, .irs-to:after, .irs-single:after {
|
||||
position: absolute;
|
||||
display: block;
|
||||
content: "";
|
||||
bottom: -6px;
|
||||
left: 50%;
|
||||
width: 0;
|
||||
height: 0;
|
||||
margin-left: -3px;
|
||||
overflow: hidden;
|
||||
border: 3px solid transparent;
|
||||
border-top-color: #006CFA;
|
||||
}
|
||||
|
||||
.irs-grid {
|
||||
height: 27px;
|
||||
}
|
||||
.irs-grid-pol {
|
||||
background: #DEE4EC;
|
||||
}
|
||||
|
||||
.irs-grid-text {
|
||||
bottom: 4px;
|
||||
color: silver;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
@@ -1,128 +0,0 @@
|
||||
/* Ion.RangeSlider, Shiny Skin
|
||||
|
||||
// This skin has been modified for use with Shiny.
|
||||
// It's based on the HTML5 skin, which doesn't require any sprites, but
|
||||
// has been modified to have no gradients, and to have dimensions similar to
|
||||
// the skinNice theme.
|
||||
|
||||
// css version 2.0.0
|
||||
// © RStudio, Inc, 2014
|
||||
// © Denis Ineshin, 2014 https://github.com/IonDen
|
||||
// © guybowden, 2014 https://github.com/guybowden
|
||||
// ===================================================================================================================*/
|
||||
|
||||
/* =====================================================================================================================
|
||||
// Skin details */
|
||||
|
||||
.irs {
|
||||
height: 40px;
|
||||
}
|
||||
.irs-with-grid {
|
||||
height: 60px;
|
||||
}
|
||||
.irs-line {
|
||||
height: 8px; top: 25px;
|
||||
background: #EEE;
|
||||
background: linear-gradient(to bottom, #DDD -50%, #FFF 150%); /* W3C */
|
||||
border: 1px solid #CCC;
|
||||
border-radius: 16px;
|
||||
-moz-border-radius: 16px;
|
||||
}
|
||||
.irs-line-left {
|
||||
height: 8px;
|
||||
}
|
||||
.irs-line-mid {
|
||||
height: 8px;
|
||||
}
|
||||
.irs-line-right {
|
||||
height: 8px;
|
||||
}
|
||||
|
||||
.irs-bar {
|
||||
height: 8px; top: 25px;
|
||||
border-top: 1px solid #428bca;
|
||||
border-bottom: 1px solid #428bca;
|
||||
background: #428bca;
|
||||
}
|
||||
.irs-bar-edge {
|
||||
height: 8px; top: 25px;
|
||||
width: 14px;
|
||||
border: 1px solid #428bca;
|
||||
border-right: 0;
|
||||
background: #428bca;
|
||||
border-radius: 16px 0 0 16px;
|
||||
-moz-border-radius: 16px 0 0 16px;
|
||||
}
|
||||
|
||||
.irs-shadow {
|
||||
height: 2px; top: 38px;
|
||||
background: #000;
|
||||
opacity: 0.3;
|
||||
border-radius: 5px;
|
||||
-moz-border-radius: 5px;
|
||||
}
|
||||
.lt-ie9 .irs-shadow {
|
||||
filter: alpha(opacity=30);
|
||||
}
|
||||
|
||||
.irs-slider {
|
||||
top: 17px;
|
||||
width: 22px; height: 22px;
|
||||
border: 1px solid #AAA;
|
||||
background: #DDD;
|
||||
border-radius: 27px;
|
||||
-moz-border-radius: 27px;
|
||||
box-shadow: 1px 1px 3px rgba(0,0,0,0.3);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#irs-active-slider, .irs-slider:hover {
|
||||
background: #FFF;
|
||||
}
|
||||
|
||||
.irs-min, .irs-max {
|
||||
color: #333;
|
||||
font-size: 10px; line-height: 1.333;
|
||||
text-shadow: none;
|
||||
top: 0;
|
||||
padding: 1px 3px;
|
||||
background: rgba(0,0,0,0.1);
|
||||
border-radius: 3px;
|
||||
-moz-border-radius: 3px;
|
||||
}
|
||||
|
||||
.lt-ie9 .irs-min, .lt-ie9 .irs-max {
|
||||
background: #ccc;
|
||||
}
|
||||
|
||||
.irs-from, .irs-to, .irs-single {
|
||||
color: #fff;
|
||||
font-size: 11px; line-height: 1.333;
|
||||
text-shadow: none;
|
||||
padding: 1px 3px;
|
||||
background: #428bca;
|
||||
border-radius: 3px;
|
||||
-moz-border-radius: 3px;
|
||||
}
|
||||
.lt-ie9 .irs-from, .lt-ie9 .irs-to, .lt-ie9 .irs-single {
|
||||
background: #999;
|
||||
}
|
||||
|
||||
.irs-grid {
|
||||
height: 27px;
|
||||
}
|
||||
.irs-grid-pol {
|
||||
opacity: 0.5;
|
||||
background: #428bca;
|
||||
}
|
||||
.irs-grid-pol.small {
|
||||
background: #999;
|
||||
}
|
||||
|
||||
.irs-grid-text {
|
||||
bottom: 5px;
|
||||
color: #99a4ac;
|
||||
}
|
||||
|
||||
.irs-disabled {
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
/* Ion.RangeSlider, Simple Skin
|
||||
// css version 2.0.3
|
||||
// © Denis Ineshin, 2014 https://github.com/IonDen
|
||||
// ===================================================================================================================*/
|
||||
|
||||
/* =====================================================================================================================
|
||||
// Skin details */
|
||||
|
||||
.irs-line-mid,
|
||||
.irs-line-left,
|
||||
.irs-line-right,
|
||||
.irs-bar,
|
||||
.irs-bar-edge,
|
||||
.irs-slider {
|
||||
background: url(../img/sprite-skin-simple.png) repeat-x;
|
||||
}
|
||||
|
||||
.irs {
|
||||
height: 40px;
|
||||
}
|
||||
.irs-with-grid {
|
||||
height: 60px;
|
||||
}
|
||||
.irs-line {
|
||||
height: 6px; top: 25px;
|
||||
}
|
||||
.irs-line-left {
|
||||
height: 6px;
|
||||
background-position: 0 -30px;
|
||||
}
|
||||
.irs-line-mid {
|
||||
height: 6px;
|
||||
background-position: 0 0;
|
||||
}
|
||||
.irs-line-right {
|
||||
height: 6px;
|
||||
background-position: 100% -30px;
|
||||
}
|
||||
|
||||
.irs-bar {
|
||||
height: 6px; top: 25px;
|
||||
background-position: 0 -60px;
|
||||
}
|
||||
.irs-bar-edge {
|
||||
top: 25px;
|
||||
height: 6px; width: 7px;
|
||||
background-position: 0 -90px;
|
||||
}
|
||||
|
||||
.irs-shadow {
|
||||
height: 1px; top: 34px;
|
||||
background: #000;
|
||||
opacity: 0.75;
|
||||
}
|
||||
.lt-ie9 .irs-shadow {
|
||||
filter: alpha(opacity=75);
|
||||
}
|
||||
|
||||
.irs-slider {
|
||||
width: 8px; height: 15px;
|
||||
top: 21px;
|
||||
background-position: 0 -120px;
|
||||
}
|
||||
.irs-slider.state_hover, .irs-slider:hover {
|
||||
background-position: 0 -150px;
|
||||
}
|
||||
|
||||
.irs-min, .irs-max {
|
||||
color: #c0c0c0;
|
||||
font-size: 10px; line-height: 1.333;
|
||||
text-shadow: none;
|
||||
top: 0; padding: 1px 3px;
|
||||
background: rgba(0,0,0,0.1);
|
||||
-moz-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.lt-ie9 .irs-min, .lt-ie9 .irs-max {
|
||||
background: #3654b0;
|
||||
}
|
||||
|
||||
.irs-from, .irs-to, .irs-single {
|
||||
color: #000;
|
||||
font-size: 10px; line-height: 1.333;
|
||||
text-shadow: none;
|
||||
padding: 1px 5px;
|
||||
background: rgba(255,255,255,0.8);
|
||||
-moz-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.lt-ie9 .irs-from, .lt-ie9 .irs-to, .lt-ie9 .irs-single {
|
||||
background: #d8dff3;
|
||||
}
|
||||
|
||||
.irs-grid-pol {
|
||||
background: #777;
|
||||
}
|
||||
.irs-grid-text {
|
||||
color: #e0e0e0;
|
||||
}
|
||||
|
||||
.irs-disabled {
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
/* Ion.RangeSlider, Square Skin
|
||||
// css version 2.2.0
|
||||
// © Denis Ineshin, 2014 https://github.com/IonDen
|
||||
// © Veaceslav Grimalschi, 2018 https://github.com/grimalschi
|
||||
// ===================================================================================================================*/
|
||||
|
||||
/* =====================================================================================================================
|
||||
// Skin details */
|
||||
|
||||
.irs {
|
||||
height: 45px;
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
.irs-with-grid {
|
||||
height: 62px;
|
||||
}
|
||||
|
||||
.irs-line {
|
||||
top: 31px;
|
||||
height: 4px;
|
||||
background: #DEDEDE;
|
||||
}
|
||||
|
||||
.irs-bar, .irs-bar-edge {
|
||||
top: 31px;
|
||||
height: 4px;
|
||||
background: black;
|
||||
}
|
||||
.irs-bar-edge {
|
||||
width: 8px;
|
||||
}
|
||||
|
||||
.irs-shadow {
|
||||
height: 2px;
|
||||
top: 37px;
|
||||
background: #DEDEDE;
|
||||
}
|
||||
|
||||
.irs-slider {
|
||||
top: 30px;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
margin-top: -5px;
|
||||
border: 3px solid black;
|
||||
background: white;
|
||||
cursor: pointer;
|
||||
box-sizing: content-box;
|
||||
-webkit-transform: rotate(45deg);
|
||||
-ms-transform: rotate(45deg);
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
.irs-slider.state_hover, .irs-slider:hover {
|
||||
background: #f0f0f0;
|
||||
}
|
||||
|
||||
.irs-min, .irs-max {
|
||||
color: #333;
|
||||
font-size: 13px;
|
||||
top: 0;
|
||||
padding: 3px 4px;
|
||||
background: rgba(0,0,0,0.1);
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.irs-from, .irs-to, .irs-single {
|
||||
color: #fff;
|
||||
font-size: 13px;
|
||||
text-shadow: none;
|
||||
padding: 3px 4px;
|
||||
background: black;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.irs-grid {
|
||||
height: 27px;
|
||||
}
|
||||
.irs-grid-pol {
|
||||
background: #DEDEDE;
|
||||
}
|
||||
|
||||
.irs-grid-text {
|
||||
bottom: 4px;
|
||||
color: silver;
|
||||
font-size: 11px;
|
||||
}
|
||||
427
inst/www/shared/ionrangeslider/css/normalize.css
vendored
427
inst/www/shared/ionrangeslider/css/normalize.css
vendored
@@ -1,427 +0,0 @@
|
||||
/*! normalize.css v3.0.2 | MIT License | git.io/normalize */
|
||||
|
||||
/**
|
||||
* 1. Set default font family to sans-serif.
|
||||
* 2. Prevent iOS text size adjust after orientation change, without disabling
|
||||
* user zoom.
|
||||
*/
|
||||
|
||||
html {
|
||||
font-family: sans-serif; /* 1 */
|
||||
-ms-text-size-adjust: 100%; /* 2 */
|
||||
-webkit-text-size-adjust: 100%; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove default margin.
|
||||
*/
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* HTML5 display definitions
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Correct `block` display not defined for any HTML5 element in IE 8/9.
|
||||
* Correct `block` display not defined for `details` or `summary` in IE 10/11
|
||||
* and Firefox.
|
||||
* Correct `block` display not defined for `main` in IE 11.
|
||||
*/
|
||||
|
||||
article,
|
||||
aside,
|
||||
details,
|
||||
figcaption,
|
||||
figure,
|
||||
footer,
|
||||
header,
|
||||
hgroup,
|
||||
main,
|
||||
menu,
|
||||
nav,
|
||||
section,
|
||||
summary {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct `inline-block` display not defined in IE 8/9.
|
||||
* 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.
|
||||
*/
|
||||
|
||||
audio,
|
||||
canvas,
|
||||
progress,
|
||||
video {
|
||||
display: inline-block; /* 1 */
|
||||
vertical-align: baseline; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent modern browsers from displaying `audio` without controls.
|
||||
* Remove excess height in iOS 5 devices.
|
||||
*/
|
||||
|
||||
audio:not([controls]) {
|
||||
display: none;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address `[hidden]` styling not present in IE 8/9/10.
|
||||
* Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22.
|
||||
*/
|
||||
|
||||
[hidden],
|
||||
template {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Links
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove the gray background color from active links in IE 10.
|
||||
*/
|
||||
|
||||
a {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Improve readability when focused and also mouse hovered in all browsers.
|
||||
*/
|
||||
|
||||
a:active,
|
||||
a:hover {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
/* Text-level semantics
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Address styling not present in IE 8/9/10/11, Safari, and Chrome.
|
||||
*/
|
||||
|
||||
abbr[title] {
|
||||
border-bottom: 1px dotted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address style set to `bolder` in Firefox 4+, Safari, and Chrome.
|
||||
*/
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address styling not present in Safari and Chrome.
|
||||
*/
|
||||
|
||||
dfn {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address variable `h1` font-size and margin within `section` and `article`
|
||||
* contexts in Firefox 4+, Safari, and Chrome.
|
||||
*/
|
||||
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
margin: 0.67em 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address styling not present in IE 8/9.
|
||||
*/
|
||||
|
||||
mark {
|
||||
background: #ff0;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address inconsistent and variable font size in all browsers.
|
||||
*/
|
||||
|
||||
small {
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent `sub` and `sup` affecting `line-height` in all browsers.
|
||||
*/
|
||||
|
||||
sub,
|
||||
sup {
|
||||
font-size: 75%;
|
||||
line-height: 0;
|
||||
position: relative;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
sup {
|
||||
top: -0.5em;
|
||||
}
|
||||
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
}
|
||||
|
||||
/* Embedded content
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove border when inside `a` element in IE 8/9/10.
|
||||
*/
|
||||
|
||||
img {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct overflow not hidden in IE 9/10/11.
|
||||
*/
|
||||
|
||||
svg:not(:root) {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Grouping content
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Address margin not present in IE 8/9 and Safari.
|
||||
*/
|
||||
|
||||
figure {
|
||||
margin: 1em 40px;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address differences between Firefox and other browsers.
|
||||
*/
|
||||
|
||||
hr {
|
||||
-moz-box-sizing: content-box;
|
||||
box-sizing: content-box;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Contain overflow in all browsers.
|
||||
*/
|
||||
|
||||
pre {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address odd `em`-unit font size rendering in all browsers.
|
||||
*/
|
||||
|
||||
code,
|
||||
kbd,
|
||||
pre,
|
||||
samp {
|
||||
font-family: monospace, monospace;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
/* Forms
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Known limitation: by default, Chrome and Safari on OS X allow very limited
|
||||
* styling of `select`, unless a `border` property is set.
|
||||
*/
|
||||
|
||||
/**
|
||||
* 1. Correct color not being inherited.
|
||||
* Known issue: affects color of disabled elements.
|
||||
* 2. Correct font properties not being inherited.
|
||||
* 3. Address margins set differently in Firefox 4+, Safari, and Chrome.
|
||||
*/
|
||||
|
||||
button,
|
||||
input,
|
||||
optgroup,
|
||||
select,
|
||||
textarea {
|
||||
color: inherit; /* 1 */
|
||||
font: inherit; /* 2 */
|
||||
margin: 0; /* 3 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Address `overflow` set to `hidden` in IE 8/9/10/11.
|
||||
*/
|
||||
|
||||
button {
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address inconsistent `text-transform` inheritance for `button` and `select`.
|
||||
* All other form control elements do not inherit `text-transform` values.
|
||||
* Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.
|
||||
* Correct `select` style inheritance in Firefox.
|
||||
*/
|
||||
|
||||
button,
|
||||
select {
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
|
||||
* and `video` controls.
|
||||
* 2. Correct inability to style clickable `input` types in iOS.
|
||||
* 3. Improve usability and consistency of cursor style between image-type
|
||||
* `input` and others.
|
||||
*/
|
||||
|
||||
button,
|
||||
html input[type="button"], /* 1 */
|
||||
input[type="reset"],
|
||||
input[type="submit"] {
|
||||
-webkit-appearance: button; /* 2 */
|
||||
cursor: pointer; /* 3 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-set default cursor for disabled elements.
|
||||
*/
|
||||
|
||||
button[disabled],
|
||||
html input[disabled] {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove inner padding and border in Firefox 4+.
|
||||
*/
|
||||
|
||||
button::-moz-focus-inner,
|
||||
input::-moz-focus-inner {
|
||||
border: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address Firefox 4+ setting `line-height` on `input` using `!important` in
|
||||
* the UA stylesheet.
|
||||
*/
|
||||
|
||||
input {
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
/**
|
||||
* It's recommended that you don't attempt to style these elements.
|
||||
* Firefox's implementation doesn't respect box-sizing, padding, or width.
|
||||
*
|
||||
* 1. Address box sizing set to `content-box` in IE 8/9/10.
|
||||
* 2. Remove excess padding in IE 8/9/10.
|
||||
*/
|
||||
|
||||
input[type="checkbox"],
|
||||
input[type="radio"] {
|
||||
box-sizing: border-box; /* 1 */
|
||||
padding: 0; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Fix the cursor style for Chrome's increment/decrement buttons. For certain
|
||||
* `font-size` values of the `input`, it causes the cursor style of the
|
||||
* decrement button to change from `default` to `text`.
|
||||
*/
|
||||
|
||||
input[type="number"]::-webkit-inner-spin-button,
|
||||
input[type="number"]::-webkit-outer-spin-button {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Address `appearance` set to `searchfield` in Safari and Chrome.
|
||||
* 2. Address `box-sizing` set to `border-box` in Safari and Chrome
|
||||
* (include `-moz` to future-proof).
|
||||
*/
|
||||
|
||||
input[type="search"] {
|
||||
-webkit-appearance: textfield; /* 1 */
|
||||
-moz-box-sizing: content-box;
|
||||
-webkit-box-sizing: content-box; /* 2 */
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove inner padding and search cancel button in Safari and Chrome on OS X.
|
||||
* Safari (but not Chrome) clips the cancel button when the search input has
|
||||
* padding (and `textfield` appearance).
|
||||
*/
|
||||
|
||||
input[type="search"]::-webkit-search-cancel-button,
|
||||
input[type="search"]::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define consistent border, margin, and padding.
|
||||
*/
|
||||
|
||||
fieldset {
|
||||
border: 1px solid #c0c0c0;
|
||||
margin: 0 2px;
|
||||
padding: 0.35em 0.625em 0.75em;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct `color` not being inherited in IE 8/9/10/11.
|
||||
* 2. Remove padding so people aren't caught out if they zero out fieldsets.
|
||||
*/
|
||||
|
||||
legend {
|
||||
border: 0; /* 1 */
|
||||
padding: 0; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove default vertical scrollbar in IE 8/9/10/11.
|
||||
*/
|
||||
|
||||
textarea {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't inherit the `font-weight` (applied by a rule above).
|
||||
* NOTE: the default cannot safely be changed in Chrome and Safari on OS X.
|
||||
*/
|
||||
|
||||
optgroup {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* Tables
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove most spacing between table cells.
|
||||
*/
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
||||
|
||||
td,
|
||||
th {
|
||||
padding: 0;
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 304 B |
Binary file not shown.
|
Before Width: | Height: | Size: 505 B |
Binary file not shown.
|
Before Width: | Height: | Size: 694 B |
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user