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#id
element.$("#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
$button(
tags"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)
function(){
ui <-fluidPage(
# We create a plotOutput, which will show an alert when
# it is clicked
plotOutput(
"plot"
%>% tagAppendAttributes(
) onclick = "alert('iris plot!')"
)
)
} function(input, output, session){
server <-$plot <- renderPlot({
outputplot(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}
.