17.3 Client-Side JavaScript
This whole topic is related to JavaScript, but is stated with relation to R and Shiny. These three are all intertwined with each other. If extend beyond R and {shiny}, you can expand the interaction of your web app. Examples include: Small JavaScript functions that will prevent you from writing complex algorithmic logic in your application server.
alert("message")is a built-in alert-box mechanism. This is built into the user’s browser and can replace a call to the server, likeshinyalert.var x = prompt("this", "that");is a function that opens a built-in prompt window. We can recieve input and store it in a variable for future use.
17.3.1 Common Patterns
Examples of Client-Side use of JavaScript:
alert("message")is a built-in alert-box mechanism. This is built into the user’s browser and can replace a call to the server, likeshinyalert.var x = prompt("this", "that");is a function that opens a built-in prompt window. We can recieve input and store it in a variable for future use.$('#id').css('color', 'green');, or in vanilla JavaScriptdocument.getElementById("demo").style.color = "green";changes the CSS attributes of the selected element(s). Here, we are switching to green on the#idelement.$("#id").text("this"), or in vanilla JavaScriptdocument.getElementById("id").innerText = "this";changes the text content to “this”.$("#id").remove();, or in vanilla JavaScriptvar elem = document.querySelector('#some-element'); elem.parentNode.removeChild(elem);completely removes the element from the DOM. It can be used as a replacement forshiny::removeUI(), or as a conditional UI.
Note that this code doesn’t remove the input values on the server side: the elements only disappear from the UI, but nothing is sent to the server side.
17.3.2 Where to put them: Back to JavaScript Events
It is great we are discussing all levels of JavaScript implementation…but where to put them?
Here are some examples of adding JavaScript functions to DOM events:
onclick
The onclick attribute can be added straight inside the HTML tag when possible:
# Building a button using the native HTML tag
# (i.e. not using the actionButton() function)
# This button only goal is to launch this JS code
# when it is clicked
tags$button(
"Show",
onclick = "$('#plot').show()"
)Or with shiny::tagAppendAttributes():
# Using tagAppendAttributes() allows to add attributes to the
# outputed UI element
plotOutput(
"plot"
) %>% tagAppendAttributes(
onclick = "alert('hello world')"
)Here is, for example, a small {shiny} app that implements this behavior:
library(shiny)
library(magrittr)
ui <- function(){
fluidPage(
# We create a plotOutput, which will show an alert when
# it is clicked
plotOutput(
"plot"
) %>% tagAppendAttributes(
onclick = "alert('iris plot!')"
)
)
}
server <- function(input, output, session){
output$plot <- renderPlot({
plot(iris)
})
}
shinyApp(ui, server)Lets put this into Golem!!!
Use the add_js_file("name") function in Golem.
- In
/inst/app/www/script.js
function alertme(id){
// Asking information
var name = prompt("Who are you?");
// Showing an alert
alert("Hello " + name + "! You're seeing " + id);
}- Then in R
plotOutput(
"plot"
) %>% tagAppendAttributes(
# Calling the function which has been defined in the
# external script
onclick = "alertme('plot')"
)Last example, you can also add jQuery calls too! Inside this inst/app/www/script.js, you can also attach a new behavior with jQuery to one or several elements.
For example, you can add this alertme / onclick behavior to all plots of the app:
function alertme(id){
var name = prompt("Who are you?");
alert("Hello " + name + "! You're seeing " + id);
}
/* We're adding this so that the function is launched only
when the document is ready */
$(function(){
// Selecting all `{shiny}` plots
$(".shiny-plot-output").on("click", function(){
/* Calling the alertme function with the id
of the clicked plot */
alertme(this.id);
});
});We’ve unpacked a lot here…but there is more. Check out JavaScript Events in {shiny} for the full list of JavaScript events available in {shiny}.