wordcloud2
wordcloud2 copied to clipboard
Click Event in shiny?
Is it possible to return a click on a word of the wordcloud as a click event in shiny in order to bind other objects (e.g. bsModal) to it? For example, in plotly this is a accomplished by generating an object that can be accessed from within the shiny session and holds the event data (e.g. click coordinates) (https://plot.ly/r/shinyapp-linked-click/).
You can use the hoverFunction
to define the event when you move your mouse on a word.
Unlucky, it should be a JS function rather than R function.
hoverFunction = htmlwidgets::JS("function hover() {}")
wordcloud2(demoFreq,hoverFunction = hoverFunction)
See these codes
Here is a function that can be added in shinyUI
to add some click event functionality. This is adapted from an SO answer. The function is not heavily bulletproofed/tested, but has been getting the job done for me so far.
#function to give wordcloud2 click interactivity
wc2ClickedWord = function(cloudOutputId, inputId) {
#ARGUMENTS
# - cloudOutputId: string; outputId of wordcloud2 obj being rendered (should be identical to the value passed to wordcloud2Output)
# - inputId: string; inputId of word clicked on (ie you will reference in server the word by input$inputId)
#OUPUT
# - referencing input in server will return a string of form word:freq (same as hover info shown in wordcloud; ie 'super:32')
#USAGE
# library(shiny)
# library(wordcloud2)
# shinyApp(
# ui=shinyUI(fluidPage(
# wordcloud2Output("my_wc"),
# wordcloud2Output("my_wc2"),
#
# wc2ClickedWord("my_wc", "selected_word"),
# wc2ClickedWord("my_wc2", "selected_word2"),
#
# verbatimTextOutput("print"),
# verbatimTextOutput("print2")
# )),
# server=shinyServer(function(input,output,session){
# output$my_wc = renderWordcloud2(wordcloud2(demoFreq))
# output$my_wc2 = renderWordcloud2(wordcloud2(demoFreq))
#
# output$print = renderPrint(input$selected_word)
# output$print2 = renderPrint(input$selected_word2)
# })
# )
shiny::tags$script(shiny::HTML(
sprintf("$(document).on('click', '#%s', function() {", cloudOutputId),
'word = document.getElementById("wcSpan").innerHTML;',
sprintf("Shiny.onInputChange('%s', word);", inputId),
"});"
))
}
That's COOOOOOOL!
Note, if #32 PR is approved (which I hope it is since it fixes a hover info bug) the click function I posted above will break since it was using the hardcoded wcSpan
Id. If #32 is approved then the below function seems to work for click events.
#function to give wordcloud2 click interactivity
wc2ClickedWord = function(cloudOutputId, inputId) {
#ARGUMENTS
# - cloudOutputId: string; outputId of wordcloud2 obj being rendered (should be identical to the value passed to wordcloud2Output)
# - inputId: string; inputId of word clicked on (ie you will reference in server the word by input$inputId)
#OUPUT
# - referencing input in server will return a string of form word:freq (same as hover info shown in wordcloud; ie 'super:32')
#USAGE
# library(shiny)
# library(wordcloud2)
# shinyApp(
# ui=shinyUI(fluidPage(
# wordcloud2Output("my_wc"),
# wordcloud2Output("my_wc2"),
#
# wc2ClickedWord("my_wc", "selected_word"),
# wc2ClickedWord("my_wc2", "selected_word2"),
#
# verbatimTextOutput("print"),
# verbatimTextOutput("print2")
# )),
# server=shinyServer(function(input,output,session){
# output$my_wc = renderWordcloud2(wordcloud2(demoFreq))
# output$my_wc2 = renderWordcloud2(wordcloud2(demoFreq))
#
# output$print = renderPrint(input$selected_word)
# output$print2 = renderPrint(input$selected_word2)
# })
# )
shiny::tags$script(shiny::HTML(
sprintf("$(document).on('click', '#%s', function() {", cloudOutputId),
sprintf('word = document.getElementById("%swcSpan").innerHTML;', cloudOutputId),
sprintf("Shiny.onInputChange('%s', word);", inputId),
"});"
))
}
@AdamSpannbauer this solution is great (even if I had some issues in Firefox), and perhaps it would be nice to include the function in the main package itself. Have you found any effective way to reset input$inputId to NULL, or, in other words, to deselect the word after you've clicked on it (e.g. by clicking on the background?) clicking on other words works fine, but I haven't found an easy way to get back to the point when no word is selected.
@giocomai a possible way set input$inputId
to NULL
is outlined in this SO answer. You can see this gist for a minimal example of the technique paired with the wordcloud2 click event function I posted in this thread.
@Lchiffon I forked the project to look into adding click events to the wordcloud2::wordcloud2Output
function.
I believe the functionality is fairly easily achieved, but the current method I have working would require adding shiny
as a dependency. Are you open to this added dependency to add click events? If yes, I will polish up the code/documentation for further testing and submit a PR.
I went ahead and made PR #35 that adds a click event to the wordcloud2 widget. This PR as it currently stands would add shiny as an Import if merged.