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, like shinyalert.

  • 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, like shinyalert.

  • 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 JavaScript document.getElementById("demo").style.color = "green"; changes the CSS attributes of the selected element(s). Here, we are switching to green on the #id element.

  • $("#id").text("this"), or in vanilla JavaScript document.getElementById("id").innerText = "this"; changes the text content to “this”.

  • $("#id").remove();, or in vanilla JavaScript var elem = document.querySelector('#some-element'); elem.parentNode.removeChild(elem); completely removes the element from the DOM. It can be used as a replacement for shiny::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}.