0

I'm looking to determine the font color of hover messages based on the background color, i.e. white if background is dark, and black if it is light,

and I came across this SO question with a javascript solution that looks perfect, but now I am struggling to make it work in R

The original javascript comes from here: enter link description here

Most likely I'm missing something silly somewhere as I have used runjs and the sprintf approach before, but can't spot it.

require('shiny')
require('shinyjs')

fontcolor <- function(color){
  sprintf(paste(
    " var bgColor = %s;",
    " var color = (bgColor.charAt(0) === '#') ? bgColor.substring(1, 7) : bgColor;",
    " var r = parseInt(color.substring(0, 2), 16);",
    " var g = parseInt(color.substring(2, 4), 16);",
    " var b = parseInt(color.substring(4, 6), 16);",
    " var uicolors = [r / 255, g / 255, b / 255];",
    " var c = uicolors.map((col) => {",
    "  if (col <= 0.03928) {",
    "    return col / 12.92;",
    "  }",
    "  return Math.pow((col + 0.055) / 1.055, 2.4);",
    " });",
    " var L = (0.2126 * c[0]) + (0.7152 * c[1]) + (0.0722 * c[2]);",
    " var colfont (L > 0.179) ? #000000 : #ffffff;",
    "  Shiny.setInputValue('Frontfont', bgColor, {priority: 'event'});",
    sep = "\n"
  ), color)
}

ui <- fluidPage(
  useShinyjs(),
    textInput('ColorTyped', label = 'Enter hex code'), 
    h5('Font color result'),
    verbatimTextOutput('FontColorSelected')
  )


server <- function(input, output) {

  ColorResult <- reactive({
    runjs(fontcolor(input$ColorTyped))
  })

  output$FontColorSelected <- renderPrint({ 
    ColorResult()
    })

}

shinyApp(ui, server)
Mark
  • 2,789
  • 1
  • 26
  • 66

1 Answers1

1

There were missing quotes in the JS code, and the server logic was not correct.

require('shiny')
require('shinyjs')

froncolor <- function(color){
  sprintf(paste(
    " var bgColor = '%s';",
    " var color = (bgColor.charAt(0) === '#') ? bgColor.substring(1, 7) : bgColor;",
    " var r = parseInt(color.substring(0, 2), 16);",
    " var g = parseInt(color.substring(2, 4), 16);",
    " var b = parseInt(color.substring(4, 6), 16);",
    " var uicolors = [r / 255, g / 255, b / 255];",
    " var c = uicolors.map((col) => {",
    "  if (col <= 0.03928) {",
    "    return col / 12.92;",
    "  }",
    "  return Math.pow((col + 0.055) / 1.055, 2.4);",
    " });",
    " var L = (0.2126 * c[0]) + (0.7152 * c[1]) + (0.0722 * c[2]);",
    " var colfont = (L > 0.179) ? '#000000' : '#ffffff';",
    " Shiny.setInputValue('Frontfont', colfont, {priority: 'event'});",
    sep = "\n"
  ), color)
}

ui <- fluidPage(
  useShinyjs(),
  textInput('ColorTyped', label = 'Enter hex code'), 
  h5('Font color result'),
  verbatimTextOutput('FontColorSelected')
)


server <- function(input, output) {

  observeEvent(input$ColorTyped, {
    runjs(froncolor(input$ColorTyped))
  })

  output$FontColorSelected <- renderPrint({ 
    input$Frontfont
  })

}

shinyApp(ui, server)
Stéphane Laurent
  • 75,186
  • 15
  • 119
  • 225
  • I'll admit, I rushed the dummy app wrapper to create an example that could be used to test it. Thanks for the corrections! – Mark Jul 20 '19 at 10:29