From aaa299d418dbb1c8270cfc236abf6c16c565b918 Mon Sep 17 00:00:00 2001 From: JJ Allaire Date: Thu, 26 Jul 2012 09:45:29 -0700 Subject: [PATCH] add source code to tutorial topics --- _includes/tutorial/hello-shiny.md | 60 ++++++++++++++++++- _includes/tutorial/html-ui.md | 93 +++++++++++++++++++++++++++++ _includes/tutorial/more-widgets.md | 79 ++++++++++++++++++++++++ _includes/tutorial/reactivity.md | 96 ++++++++++++++++++++++++++++++ _includes/tutorial/shiny-text.md | 66 ++++++++++++++++++++ _includes/tutorial/sliders.md | 23 ++++++- _includes/tutorial/tabsets.md | 90 ++++++++++++++++++++++++++++ tutorial/index.html | 3 + 8 files changed, 508 insertions(+), 2 deletions(-) diff --git a/_includes/tutorial/hello-shiny.md b/_includes/tutorial/hello-shiny.md index 65e5cb547..2fcae00c0 100644 --- a/_includes/tutorial/hello-shiny.md +++ b/_includes/tutorial/hello-shiny.md @@ -1,2 +1,60 @@ -![Hello Shiny Screenshot](screenshots/hello-shiny.png) \ No newline at end of file +![Hello Shiny Screenshot](screenshots/hello-shiny.png) + +The Hello Shiny example is a simple application that generates a random distribution with a configurable number of observations and then plots it. To run the example type: + +
> library(shiny)
+> runExample("01_hello")
+
+ +#### ui.R + +
library(shiny)
+
+# Define UI for application that plots random distributions 
+shinyUI(pageWithSidebar(
+
+  # Application title
+  headerPanel("Hello Shiny!"),
+
+  # Sidebar with a slider input for number of observations
+  sidebarPanel(
+    sliderInput("obs", 
+                "Number of observations:", 
+                min = 0, 
+                max = 1000, 
+                value = 500)
+  ),
+
+  # Show a plot of the generated distribution
+  mainPanel(
+    plotOutput("distPlot")
+  )
+))
+
+ +#### server.R + +
library(shiny)
+
+# Define server logic required to generate and plot a random distribution
+shinyServer(function(input, output) {
+
+  # Function that generates a plot of the distribution. The function
+  # is wrapped in a call to reactivePlot to indicate that:
+  #
+  #  1) It is "reactive" and therefore should be automatically 
+  #     re-executed when inputs change
+  #  2) Its output type is a plot 
+  #
+  output$distPlot <- reactivePlot(function() {
+
+    # convert string input to an integer
+    obs <- as.integer(input$obs)
+
+    # generate an rnorm distribution and plot it
+    dist <- rnorm(obs)
+    hist(dist)
+  })
+})
+
diff --git a/_includes/tutorial/html-ui.md b/_includes/tutorial/html-ui.md index a5cad3c72..90bb5dcb2 100644 --- a/_includes/tutorial/html-ui.md +++ b/_includes/tutorial/html-ui.md @@ -1,3 +1,96 @@ + ![HTML UI Screenshot](screenshots/html-ui.png) +To run the example type: + +
> library(shiny)
+> runExample("08_html")
+
+ +#### www/index.html + +
<html>
+
+<head>
+  <script src="shared/jquery.js" type="text/javascript"></script>
+  <script src="shared/shiny.js" type="text/javascript"></script>
+  <link rel="stylesheet" type="text/css" href="shared/shiny.css"/> 
+</head>
+ 
+<body>
+  <h1>HTML UI</h1>
+ 
+  <p>
+    <label>Distribution type:</label><br />
+    <select name="dist">
+      <option value="norm">Normal</option>
+      <option value="unif">Uniform</option>
+      <option value="lnorm">Log-normal</option>
+      <option value="exp">Exponential</option>
+    </select> 
+  </p>
+ 
+  <p>
+    <label>Number of observations:</label><br /> 
+    <input type="number" name="n" value="500" min="1" max="1000" />
+  </p>
+ 
+  <pre id="summary" class="shiny-text-output"></pre> 
+  
+  <div id="plot" class="shiny-plot-output" 
+       style="width: 100%; height: 400px"></div> 
+  
+  <div id="table" class="shiny-html-output"></div>
+</body>
+
+</html>
+
+ + +#### server.R + +
library(shiny)
+
+# Define server logic for random distribution application
+shinyServer(function(input, output) {
+
+  # Reactive function to generate the requested distribution. This is 
+  # called whenever the inputs change. The output functions defined 
+  # below then all used the value computed from this function
+  data <- reactive(function() {  
+    dist <- switch(input$dist,
+                   norm = rnorm,
+                   unif = runif,
+                   lnorm = rlnorm,
+                   exp = rexp,
+                   rnorm)
+
+    dist(as.integer(input$n))
+  })
+
+  # Generate a plot of the data. Also uses the inputs to build the 
+  # plot label. Note that the dependencies on both the inputs and
+  # the data reactive function are both tracked, and all functions 
+  # are called in the sequence implied by the dependency graph
+  output$plot <- reactivePlot(function() {
+    dist <- input$dist
+    n <- input$n
+
+    hist(data(), 
+         main=paste('r', dist, '(', n, ')', sep=''))
+  })
+
+  # Generate a summary of the data
+  output$summary <- reactivePrint(function() {
+    summary(data())
+  })
+
+  # Generate an HTML table view of the data
+  output$table <- reactiveTable(function() {
+    data.frame(x=data())
+  })
+})
+
+ + diff --git a/_includes/tutorial/more-widgets.md b/_includes/tutorial/more-widgets.md index f9a0b79a6..c7f587fe1 100644 --- a/_includes/tutorial/more-widgets.md +++ b/_includes/tutorial/more-widgets.md @@ -1,3 +1,82 @@ ![More Widgets Screenshot](screenshots/more-widgets.png) + +To run the example type: + +
> library(shiny)
+> runExample("07_widgets")
+
+ +#### ui.R + +
library(shiny)
+
+# Define UI for dataset viewer application
+shinyUI(pageWithSidebar(
+
+  # Application title.
+  headerPanel("More Widgets"),
+
+  # Sidebar with controls to select a dataset and specify the number
+  # of observations to view. The helpText function is also used to 
+  # include clarifying text. Most notably, the inclusion of a 
+  # submitButton defers the rendering of output until the user 
+  # explicitly clicks the button (rather than doing it immediately
+  # when inputs change). This is useful if the computations required
+  # to render output are inordinately time-consuming.
+  sidebarPanel(
+    selectInput("dataset", "Choose a dataset:", 
+                choices = c("rock", "pressure", "cars")),
+
+    numericInput("obs", "Number of observations to view:", 10),
+
+    helpText("Note: while the data view will show only the specified",
+             "number of observations, the summary will still be based",
+             "on the full dataset."),
+
+    submitButton("Update View")
+  ),
+
+  # Show a summary of the dataset and an HTML table with the requested
+  # number of observations. Note the use of the h4 function to provide
+  # an additional header above each output section.
+  mainPanel(
+    h4("Summary"),
+    verbatimTextOutput("summary"),
+
+    h4("Observations"),
+    tableOutput("view")
+  )
+))
+
+ +#### server.R + +
library(shiny)
+library(datasets)
+
+# Define server logic required to summarize and view the selected dataset
+shinyServer(function(input, output) {
+
+  # Return the requested dataset
+  datasetInput <- reactive(function() {
+    switch(input$dataset,
+           "rock" = rock,
+           "pressure" = pressure,
+           "cars" = cars)
+  })
+
+  # Generate a summary of the dataset
+  output$summary <- reactivePrint(function() {
+    dataset <- datasetInput()
+    summary(dataset)
+  })
+
+  # Show the first "n" observations
+  output$view <- reactiveTable(function() {
+    obs <- as.integer(input$obs)
+    head(datasetInput(), n = obs)
+  })
+})
+
diff --git a/_includes/tutorial/reactivity.md b/_includes/tutorial/reactivity.md index 5483e89bd..92ad21862 100644 --- a/_includes/tutorial/reactivity.md +++ b/_includes/tutorial/reactivity.md @@ -3,3 +3,99 @@ ![Reactivity Screenshot](screenshots/reactivity.png) +To run the example type: + +
> library(shiny)
+> runExample("03_reactivity")
+
+ +#### ui.R + +
library(shiny)
+
+# Define UI for dataset viewer application
+shinyUI(pageWithSidebar(
+
+  # Application title
+  headerPanel("Reactivity"),
+
+  # Sidebar with controls to provide a caption, select a dataset, and 
+  # specify the number of observations to view. Note that changes made
+  # to the caption in the textInput control are updated in the output
+  # area immediately as you type
+  sidebarPanel(
+    textInput("caption", "Caption:", "Data Summary"),
+
+    selectInput("dataset", "Choose a dataset:", 
+                choices = c("rock", "pressure", "cars")),
+
+    numericInput("obs", "Number of observations to view:", 10)
+  ),
+
+
+  # Show the caption, a summary of the dataset and an HTML table with
+  # the requested number of observations
+  mainPanel(
+    h3(textOutput("caption")), 
+
+    verbatimTextOutput("summary"), 
+
+    tableOutput("view")
+  )
+))
+
+ +#### server.R + +
library(shiny)
+library(datasets)
+
+# Define server logic required to summarize and view the selected dataset
+shinyServer(function(input, output) {
+
+  # By declaring databaseInput as a reactive function we ensure that:
+  #
+  #  1) It is only called when the inputs it depends on changes
+  #  2) The computation and result are shared by all the callers (it 
+  #     only executes a single time)
+  #  3) When the inputs change and the function is re-executed, the
+  #     new result is compared to the previous result; if the two are
+  #     identical, then the callers are not notified
+  #
+  datasetInput <- reactive(function() {
+    switch(input$dataset,
+           "rock" = rock,
+           "pressure" = pressure,
+           "cars" = cars)
+  })
+
+  # The output$caption is computed based on a reactive function that
+  # returns input$caption. When the user changes the "caption" field:
+  #
+  #  1) This function is automatically called to recompute the output 
+  #  2) The new caption is pushed back to the browser for re-display
+  # 
+  # Note that because the data-oriented reactive functions below don't 
+  # depend on input$caption, those functions are NOT called when 
+  # input$caption changes.
+  output$caption <- reactiveText(function() {
+    input$caption
+  })
+
+  # The output$summary depends on the datasetInput reactive function, 
+  # so will be re-executed whenever datasetInput is re-executed 
+  # (i.e. whenever the input$dataset changes)
+  output$summary <- reactivePrint(function() {
+    dataset <- datasetInput()
+    summary(dataset)
+  })
+
+  # The output$view depends on both the databaseInput reactive function
+  # and input$obs, so will be re-executed whenever input$dataset or 
+  # input$obs is changed. 
+  output$view <- reactiveTable(function() {
+    obs <- as.integer(input$obs)
+    head(datasetInput(), n = obs)
+  })
+})
+
diff --git a/_includes/tutorial/shiny-text.md b/_includes/tutorial/shiny-text.md index 1687c93a6..d63499096 100644 --- a/_includes/tutorial/shiny-text.md +++ b/_includes/tutorial/shiny-text.md @@ -1,3 +1,69 @@ ![Tabsets Screenshot](screenshots/shiny-text.png) +To run the example type: + +
> library(shiny)
+> runExample("02_text")
+
+ +#### ui.R + +
library(shiny)
+
+# Define UI for dataset viewer application
+shinyUI(pageWithSidebar(
+
+  # Application title
+  headerPanel("Shiny Text"),
+
+  # Sidebar with controls to select a dataset and specify the number
+  # of observations to view
+  sidebarPanel(
+    selectInput("dataset", "Choose a dataset:", 
+                choices = c("rock", "pressure", "cars")),
+
+    numericInput("obs", "Number of observations to view:", 10)
+  ),
+
+  # Show a summary of the dataset and an HTML table with the requested
+  # number of observations
+  mainPanel(
+    verbatimTextOutput("summary"),
+
+    tableOutput("view")
+  )
+))
+
+ +#### server.R + +
library(shiny)
+library(datasets)
+
+# Define server logic required to summarize and view the selected dataset
+shinyServer(function(input, output) {
+
+  # Return the requested dataset
+  datasetInput <- reactive(function() {
+    switch(input$dataset,
+           "rock" = rock,
+           "pressure" = pressure,
+           "cars" = cars)
+  })
+
+  # Generate a summary of the dataset
+  output$summary <- reactivePrint(function() {
+    dataset <- datasetInput()
+    summary(dataset)
+  })
+
+  # Show the first "n" observations
+  output$view <- reactiveTable(function() {
+    obs <- as.integer(input$obs)
+    head(datasetInput(), n = obs)
+  })
+})
+
+ + diff --git a/_includes/tutorial/sliders.md b/_includes/tutorial/sliders.md index d4f2d638c..dd62c5195 100644 --- a/_includes/tutorial/sliders.md +++ b/_includes/tutorial/sliders.md @@ -1,4 +1,25 @@ -### Sliders +## (Under Construction) + +To run the example type: + +
> library(shiny)
+> runExample("05_sliders")
+
+ +#### ui.R + +
library(shiny)
+
+
+
+ +#### server.R + +
library(shiny)
+
+
+
+ diff --git a/_includes/tutorial/tabsets.md b/_includes/tutorial/tabsets.md index 7c0ed8ec3..21e3f1edb 100644 --- a/_includes/tutorial/tabsets.md +++ b/_includes/tutorial/tabsets.md @@ -2,3 +2,93 @@ ![Tabsets Screenshot](screenshots/tabsets.png) +To run the example type: + +
> library(shiny)
+> runExample("06_tabsets")
+
+ +#### ui.R + +
library(shiny)
+
+# Define UI for random distribution application 
+shinyUI(pageWithSidebar(
+
+  # Application title
+  headerPanel("Tabsets"),
+
+  # Sidebar with controls to select the random distribution type
+  # and number of observations to generate. Note the use of the br()
+  # element to introduce extra vertical spacing
+  sidebarPanel(
+    radioButtons("dist", "Distribution type:",
+                 list("Normal" = "norm",
+                      "Uniform" = "unif",
+                      "Log-normal" = "lnorm",
+                      "Exponential" = "exp")),
+    br(),
+
+    sliderInput("n", 
+                "Number of observations:", 
+                 value = 500,
+                 min = 1, 
+                 max = 1000)
+  ),
+
+  # Show a tabset that includes a plot, summary, and table view
+  # of the generated distribution
+  mainPanel(
+    tabsetPanel(
+      tabPanel("Plot", plotOutput("plot")), 
+      tabPanel("Summary", verbatimTextOutput("summary")), 
+      tabPanel("Table", tableOutput("table"))
+    )
+  )
+))
+
+ +#### server.R + +
library(shiny)
+
+# Define server logic for random distribution application
+shinyServer(function(input, output) {
+
+  # Reactive function to generate the requested distribution. This is 
+  # called whenever the inputs change. The output functions defined 
+  # below then all use the value computed from this function
+  data <- reactive(function() {  
+    dist <- switch(input$dist,
+                   norm = rnorm,
+                   unif = runif,
+                   lnorm = rlnorm,
+                   exp = rexp,
+                   rnorm)
+
+    dist(as.integer(input$n))
+  })
+
+  # Generate a plot of the data. Also uses the inputs to build the 
+  # plot label. Note that the dependencies on both the inputs and
+  # the data reactive function are both tracked, and all functions 
+  # are called in the sequence implied by the dependency graph
+  output$plot <- reactivePlot(function() {
+    dist <- input$dist
+    n <- input$n
+
+    hist(data(), 
+         main=paste('r', dist, '(', n, ')', sep=''))
+  })
+
+  # Generate a summary of the data
+  output$summary <- reactivePrint(function() {
+    summary(data())
+  })
+
+  # Generate an HTML table view of the data
+  output$table <- reactiveTable(function() {
+    data.frame(x=data())
+  })
+})
+
diff --git a/tutorial/index.html b/tutorial/index.html index 61e707ea7..f536ccfc4 100644 --- a/tutorial/index.html +++ b/tutorial/index.html @@ -17,6 +17,9 @@ title: "Tutorial: Building 'shiny' Web Applications with R" .responsive-image { max-width: 100%; } + .console { + color: blue; + }