% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/manipulate_widget.R
\name{manipulateWidget}
\alias{manipulateWidget}
\title{Add Controls to Interactive Plots}
\usage{
manipulateWidget(
  .expr,
  ...,
  .updateBtn = FALSE,
  .saveBtn = TRUE,
  .exportBtn = TRUE,
  .exportType = c("html2canvas", "webshot"),
  .viewer = c("pane", "window", "browser"),
  .compare = NULL,
  .compareOpts = compareOptions(),
  .translations = mwTranslations(),
  .return = function(widget, envs) {
     widget
 },
  .width = NULL,
  .height = NULL,
  .runApp = TRUE
)
}
\arguments{
\item{.expr}{expression to evaluate that returns an interactive plot of class
\code{htmlwidget}. This expression is re-evaluated each time a control is
modified.}

\item{...}{One or more named control arguments created with functions
\code{\link{mwSlider}}, \code{\link{mwText}}, etc. The name of each control
is the name of the variable the controls modifies in the expression. One
can also create a group of inputs by passing a list of such control
arguments. for instance \code{mygroup = list(txt = mwText(""), nb =
mwNumeric(0))} creates a group of inputs named mygroup with two inputs
named "txt" and "nb".}

\item{.updateBtn}{Should an update button be added to the controls ? If
\code{TRUE}, then the graphic is updated only when the user clicks on the
update button.}

\item{.saveBtn}{Should an save button be added to the controls ? For saving output as html. Does not work in RStudio Viewer}

\item{.exportBtn}{Should an export button be added to the controls ? For saving output as png. Does not work in RStudio Viewer}

\item{.exportType}{\code{.exportBtn}, using \code{html2canvas} (default) and keeping current zoom, ... or using \code{webshot}}

\item{.viewer}{Controls where the gadget should be displayed. \code{"pane"}
corresponds to the Rstudio viewer, \code{"window"} to a dialog window, and
\code{"browser"} to an external web browser.}

\item{.compare}{Sometimes one wants to compare the same chart but with two
different sets of parameters. This is the purpose of this argument. It can
be a character vector of input names or a named list whose names are the
names of the inputs that should vary between the two charts. Each element
of the list must be a vector or a list of length equal to the number of
charts with the initial values of the corresponding parameter for each
chart. It can also be \code{NULL}. In this case, the parameter is
initialized with the default value for the two charts.}

\item{.compareOpts}{List of options created \code{\link{compareOptions}}.
These options indicate the number of charts to create and their disposition.}

\item{.translations}{List of translation strings created with function
\code{\link{mwTranslations}}. Used to translate UI titles and labels.}

\item{.return}{A function that can be used to modify the output of
\code{manipulateWidget}. It must take two parameters: the first one is the
final widget, the second one is a list of environments containing the input
values of each individual widget. The length of this list is one if .compare
is null, two or more if it has been defined.}

\item{.width}{Width of the UI. Used only on Rmarkdown documents with option
\code{runtime: shiny}.}

\item{.height}{Height of the UI. Used only on Rmarkdown documents with option
\code{runtime: shiny}.}

\item{.runApp}{(advanced usage) If true, a shiny gadget is started. If false,
the function returns a \code{\link{MWController}} object. This object can be
used to check with command line instructions the behavior of the application.
(See help page of \code{\link{MWController}}). Notice that this parameter is
always false in a non-interactive session (for instance when running tests of
a package).}
}
\value{
The result of the expression evaluated with the last values of the controls.
It should be an object of class \code{htmlWidget}.
}
\description{
This function permits to add controls to an interactive plot created with
packages like \code{dygraphs}, \code{highcharter} or \code{plotly} in order
to change the input data or the parameters of the plot.

Technically, the function starts a shiny gadget. The R session is bloqued
until the user clicks on "cancel" or "done". If he clicks on "done", then the
the function returns the last displayed plot so the user can modify it and/or
save it.
}
\section{Advanced Usage}{

The "normal" use of the function is to provide an expression that always
return an \code{htmlwidget}. In such case, every time the user changes the
value of an input, the current widget is destroyed and a new one is created
and rendered.

Some packages provide functions to update a widget that has already been
rendered. This is the case for instance for package \code{leaflet} with the
function \code{\link[leaflet]{leafletProxy}}. To use such functions,
\code{manipulateWidget} evaluates the parameter \code{.expr} with four extra
variables:

\describe{
  \item{\code{.initial}:}{
    \code{TRUE} if the expression is evaluated for the first time and then
    the widget has not been rendered yet, \code{FALSE} if the widget has
    already been rendered.
  }
  \item{\code{.session}:}{
    A shiny session object.
  }
  \item{\code{.output}:}{
    ID of the output in the shiny interface.
  }
  \item{\code{.id}:}{
    Id of the chart. It can be used in comparison mode to make further
    customization without the need to create additional input controls.
  }
}

You can take a look at the last example to see how to use these two
variables to update a leaflet widget.
}

\section{Modify the returned widget}{

  In some specific situations, a developer may want to use
  \code{manipulateWidget} in a function that waits the user to click on the
  "Done" button and modifies the widget returned by \code{manipulateWidget}.
  In such situation, parameter \code{.return} should be used so that
  \code{manipulateWidget} is the last function called. Indeed, if other code
  is present after, the custom function will act very weird in a Rmarkdown
  document with "runtime: shiny".
}

\examples{
# Basic example with fake data
if (require(dygraphs)) {
  mydata <- data.frame(period = 1:100, value = rnorm(100))
  manipulateWidget(dygraph(mydata[range[1]:range[2], ], main = title),
                   range = mwSlider(1, 100, c(1, 100)),
                   title = mwText("Fictive time series"))
}

# Let use manipulateWidget to explore the evolution of energy consumption in
# the world
data("worldEnergyUse")

if (require(plotly)) {
  # Function that generates a chart representing the evolution of energy
  # consumption per country. Creating a function is not necessary. We do it
  # for clarity and reuse in the different examples.
  plotEnergyUse <- function(Country, Period, lwd = 2, col = "gray") {
    dataset <- subset(
      worldEnergyUse,
      country == Country & year >= Period[1] & year <= Period[2]
    )
    plot_ly(dataset) \%>\%
      add_lines(~year, ~energy_used, line = list(width = lwd, color = col)) \%>\%
      layout(title = paste("Energy used in", Country))
  }

  # Launch the interactive visualisation
  manipulateWidget(
    plotEnergyUse(Country, Period),
    Period = mwSlider(1960, 2014, c(1960, 2014)),
    Country = mwSelect(sort(unique(worldEnergyUse$country)), "United States")
  )

  # Directly start comparison mode
  manipulateWidget(
    plotEnergyUse(Country, Period),
    Period = mwSlider(1960, 2014, c(1960, 2014)),
    Country = mwSelect(sort(unique(worldEnergyUse$country))),
    .compare = list(Country = c("United States", "China")),
    .compareOpts = compareOptions(ncol = 2)
  )

  # Dynamic input parameters
  #-------------------------
  # The arguments of an input can depend on the values of other inputs.
  # In this example, when the user changes the region, the choices of input
  # "Country" are updated with the countries of that region.

  # First we create a list that contains for each region the countries in that
  # retion
  refRegions <- by(worldEnergyUse$country, worldEnergyUse$region,
                   function(x) as.character(sort(unique(x))))

  manipulateWidget(
    plotEnergyUse(Country, Period),
    Period = mwSlider(1960, 2014, c(1960, 2014)),
    Region = mwSelect(sort(unique(worldEnergyUse$region))),
    Country = mwSelect(choices = refRegions[[Region]])
  )

  # Grouping inputs
  #----------------
  # Inputs can be visually grouped with function mwGroup()
  manipulateWidget(
    plotEnergyUse(Country, Period, lwd, col),
    Period = mwSlider(1960, 2014, c(1960, 2014)),
    Country = mwSelect(sort(unique(worldEnergyUse$country)), "United States"),
    `Graphical Parameters` = mwGroup(
      lwd = mwSlider(1,10, 2, label = "Line Width"),
      col = mwSelect(choices = c("gray", "black", "red"))
    )
  )

  # Conditional inputs
  #-------------------
  # Inputs can be displayed or hidden depending on the state of other inputs.
  # In this example, user can choose to display the level of aggregation
  # (region or country). Depending on the choixe, the application displays
  # input Region or input Country.
  plotEnergyUseRegion <- function(Region, Period, lwd = 2, col = "gray") {
    dataset <- subset(
      worldEnergyUse,
      region == Region & year >= Period[1] & year <= Period[2]
    )
    dataset <- aggregate(energy_used ~ year, sum, data = dataset)

    plot_ly(dataset) \%>\%
      add_lines(~year, ~energy_used, line = list(width = lwd, color = col)) \%>\%
      layout(title = paste("Energy used in", Region))
  }

  manipulateWidget(
    {
      if (Level == "Region") {
        plotEnergyUseRegion(Region, Period)
      } else {
        plotEnergyUse(Country, Period)
      }
    },
    Period = mwSlider(1960, 2014, c(1960, 2014)),
    Level = mwSelect(c("Region", "Country")),
    Region = mwSelect(sort(unique(worldEnergyUse$region)),
                      .display = Level == "Region"),
    Country = mwSelect(sort(unique(worldEnergyUse$country)),
                       .display = Level == "Country")
  )

}

# Advanced Usage
# --------------
# When .expr is evaluated with tehnical variables:
# .initial: is it the first evaluation?
# .outputId: integer representing the id of the chart
# .output: shiny output id
# .session: shiny session
# They can be used to update an already rendered widget instead of replacing
# it each time an input value is modified.
#
# In this example, we represent on a map, the energy use of countries.
# When the user changes an input, the map is not redrawn. Only the circle
# markers are updated.
if (require(leaflet)) {
  plotMap <- function(Year, MaxRadius = 30, .initial, .session, .output) {
    dataset <- subset(worldEnergyUse, year == Year)
    radius <- sqrt(dataset$energy_used) /
      max(sqrt(worldEnergyUse$energy_used), na.rm = TRUE) * MaxRadius

    if (.initial) { # map has not been rendered yet
      map <- leaflet() \%>\% addTiles()
    } else { # map already rendered
      map <- leafletProxy(.output, .session) \%>\% clearMarkers()
    }

    map \%>\% addCircleMarkers(dataset$long, dataset$lat, radius = radius,
                             color = "gray", weight = 0, fillOpacity = 0.7)
  }

  manipulateWidget(
    plotMap(Year, MaxRadius, .initial, .session, .output),
    Year = mwSlider(1960, 2014, 2014),
    MaxRadius = mwSlider(10, 50, 20)
  )
}
}
