# Shiny App without Shiny: a JavaScript Exercise in R Markdown

## Change the number of bins of a histogram with JavaScript

### Yihui Xie 2023-02-07

Please ignore the title of this post. It’s an exaggeration. In this post, I want to show an example that has the feel of a Shiny app, but it doesn’t really use Shiny or R as the backend when it runs. This example is from an answer of mine on a forum, and mainly intended for beginners who are interested in learning a little bit JavaScript, although I’m not a JavaScript expert. Below is the full R Markdown document:

``````---
title: "Change the number of bins of a histogram"
---

```{r, setup, echo=FALSE}
n_breaks = c(5, 10, 15, 20)
shiny::selectInput(
'n_breaks',
label = 'Number of bins',
choices = n_breaks,
selected = 5)
```

Draw all histograms and put them in a container with
the class `hist-all`.

```{r, class.chunk='hist-all'}
x = faithful\$eruptions
for (i in n_breaks) {
hist(x, breaks = seq(min(x), max(x), length.out = i + 1),
main = paste('n = ', i))
}
```

But we hide all of those images initially with CSS.

```{css}
/* hide all images */
.hist-all img { display: none; }
/* but show the image with the class 'show' */
.hist-all .show { display: block; }
```

When the choice in the select input is changed, show
the histogram with the selected number of bins.

```{js}
(d => {
const s = d.getElementById('n_breaks'),  // the select input
imgs = d.querySelectorAll('.hist-all img');  // all histograms

// add the class 'show' to the i-th image, where i is the
// selected number in the select input
function showImg() {
const i = s.selectedIndex;
imgs.forEach((el, k) => {
// k is the index of the image; i is the index of the choice
// in the select input; add the class 'show' if the two
// indices are equal
el.classList.toggle('show', k == i);
});
}

// show the initial image
showImg();

// show a different image when select input is changed
s.onchange = showImg;
})(document);
```
``````

You can knit the document to HTML to play with the select input, or just visit my demo. Personally I liked this example because it’s a combination of my favorite technologies: R, CSS, and JavaScript. R for drawing plots, CSS for appearance, and JavaScript for interaction. I have tried to comment the code in detail, and I hope it’s not too hard to understand. The key piece of JavaScript is `el.classList.toggle()`.

This example could be useful when you want to present several plots one by one on a static HTML page that has no R or Shiny running behind it. But guess what? Someday you may be able to run real Shiny apps in your web browser without R or Shiny—WASM for the win!