Skip to content

Instantly share code, notes, and snippets.

@zappingseb
Last active October 4, 2018 12:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zappingseb/40cb90836b870969c72921f5d2745ee8 to your computer and use it in GitHub Desktop.
Save zappingseb/40cb90836b870969c72921f5d2745ee8 to your computer and use it in GitHub Desktop.
Example of a difficult custom input shiny application
library(shiny)
library(glue)
library(jsonlite)
source("DifficultInput.R")
## As this is a GIST, copy the custom_inputs_difficult.js
dir.create("www")
file.copy("custom_inputs_difficult.js","www/custom_inputs_difficult.js", overwrite = TRUE)
ui <- fluidPage(
tags$head(
tags$link(rel = "stylesheet", type = "text/css", href = "https://cdnjs.cloudflare.com/ajax/libs/spectrum/1.8.0/spectrum.css"),
tags$script(src="https://cdnjs.cloudflare.com/ajax/libs/spectrum/1.8.0/spectrum.js"),
tags$script(src="custom_inputs_difficult.js")
),
# Generate a row with a sidebar
sidebarLayout(
# Define the sidebar with one custom input
sidebarPanel(
DifficultInput(id="myid")
),
mainPanel(
tableOutput(outputId = "thetext")
)
)
)
server <- function(input, output) {
# Render the inputs as a table
output$thetext <- renderTable(jsonlite::fromJSON(input$myid))
}
shinyApp(ui, server)
// Difficult Input Binding
//
// Definition of a Shiny InputBinding extension to
// get the values of two color pickers.
//
// https://github.com/zappingseb/customshinyinput
// Author: Sebastian Wolf
// License: MIT
// -----------------------------------------------------
// Create a shiny input binding
// Each custom input needs to be a shiny input binding
// that is defined by the JavaScript class "Shiny" and
// using the method "InputBinding"
// The name can be chosen, here it is "DifficultInputBinding"
var DifficultInputBinding = new Shiny.InputBinding();
// Extend the binding with the functions seen here
$.extend(DifficultInputBinding, {
// The scope defines how the element is described in HTML code
// The best way to find the scope
find: function(scope) {
return $(scope).find(".difficultinput");
},
getValue: function(el) {
// create an empty output array
var output = []
// go over each input element inside the
// defined InputBinding and add the ID
// and the value as a dictionary to the output
$(el).find(".difficultinputItem").each(function(inputitem){
output.push({
name: $(this).attr("id"),
value: $(this).val()
});
});
// return the output as JSON
return(JSON.stringify(output))
},
setValue: function(el, value) {
// todo
},
subscribe: function(el, callback) {
// the jQuery "change" function allows you
// to notice any change to your input elements
$(el).on('change.difficultinputItem', function(event) {
callback(false);
});
// React slower upon key changes inside the elements e.g.
// typing in Textarea
$(el).on('keyup.difficultinputItem', function(event) {
callback(true);
});
},
unsubscribe: function(el) {
$(el).off('.difficultinput');
},
getRatePolicy: function() {
return {
// Can be 'debounce' or 'throttle'
policy: 'debounce',
delay: 500
};
}
});
// Registering the shiny input
//
// The following function call is used to tell shiny that
// there now is a new Shiny.InputBinding that it shall
// deal with and that it's functionality can be found in
// the variable "DifficultInputBinding"
Shiny.inputBindings.register(DifficultInputBinding);
#' Function to return a DoubleColorPicker input
#' @param id (\code{character}) A web element ID, shall not contain dashes or underscores or colon
#' @param col_border (\code{character}) A hex code for the border color default value
#' @param col_fill (\code{character}) A hex code for the fill color default value
#' @return An \code{shiny::div} element with two color pickers
#' @author Sebastian Wolf \email{sebastian@@mail-wolf.de}
DifficultInput <- function(id="myinput", col_border = "#f00", col_fill="#00f"){
# Return a div element of class "doubleclorpicker"
div(
id=id,
class="difficultinput",
## Create a TextArea input
HTML(glue(
"<textarea id='{id}-input-bigtext' name='{id}-input-bigtext' class='difficultinputItem'>default text</textarea>")),
## Create the border Color input
tags$label("Border Color"),
HTML(glue("<input type='text' id='{id}-input-border' value='{col_border}' class='difficultinputItem'/>")),
## Create the FIll color input
tags$label("Fill Color"),
HTML(glue("<input type='text' id='{id}-input-fill' value='{col_fill}' class='difficultinputItem'/>")),
# Include the Javascript code given by the spectrum.js website
HTML(
glue(
"<script>
$('#{id}-input-border').spectrum({{
color: '{col_border}',
preferredFormat: 'hex3'
}});
$('#{id}-input-fill').spectrum({{
color: '{col_fill}',
preferredFormat: 'hex3'
}});
</script>"
)
)# HTML
)#div
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment