1

I have the following shiny app:

library(shiny)
ui <- fluidPage(
   titlePanel("Datatable for dynamic text selection"),
   sidebarLayout(
      sidebarPanel(
        dataTableOutput("pairs")
      ),
      mainPanel(
       strong("Sentence"), htmlOutput("content"),
       strong("Selection"),textOutput("selection")
      )
   )
)

server <- function(input, output) {
   output$content <- renderText("A sample sentence for demo purpose")
   df <- data.frame(SrNo=1:5, Pairs=c("A sample", "sample sentence", 
                                      "sentence for", "for demo", "demo purpose"))
   output$pairs <- renderDataTable(datatable(df, selection = "single" ))

   observeEvent(input$pairs_cell_clicked,{
     info = input$pairs_cell_clicked
    if(is.null(info$value)) return()
    output$selection <- renderText(info$value)
   })
   }

shinyApp(ui = ui, server = server)

The app displays a sentence in htmlOutput and corresponding pair of words in datatable. At present clicking any of the pair of words in datatable displays it under the Selection.

How can I modify the code so that instead of displaying the pair of words, it appears as selection in htmlOutput?

Screenshot enter image description here

Imran Ali
  • 2,223
  • 2
  • 28
  • 41

1 Answers1

1

You can use gsub to wrap the selected text in a span with a CSS attribute to change the background color.

In your server.R, you could try (ellipsis where code doesn't change):

server <- function(input, output) {
  sample_text = "A sample sentence for demo purpose";
  output$content <- renderText(sample_text)

  .....

  observeEvent(input$pairs_cell_clicked,{

   .....

    output$content <- renderText(HTML(gsub(info$value,paste0("<span style='background-color:orange'>",info$value,"</span>"),sample_text)))
  })
}

EDIT:

To mimic the user selecting the text using his mouse you could do:

select_text = JS(
                 'table.on("click.td", "tr", function () {
                            contentdiv = document.getElementById("content");
                            var selectedCell=this.lastChild;
                            var sentence = contentdiv.innerHTML;
                            var target = selectedCell.innerHTML;
                            var sentenceIndex = sentence.indexOf(target); 
                            selection = window.getSelection();
                            range = document.createRange();
                            range.setStart(contentdiv.firstChild, sentenceIndex);
                            range.setEnd(contentdiv.firstChild, (sentenceIndex + target.length));
                            selection.removeAllRanges();
                            selection.addRange(range);
                  })'
              )                                              



server <- function(input, output) {
  sample_text = "A sample sentence for demo purpose";
  output$content <- renderText(sample_text)
  df <- data.frame(SrNo=1:5, Pairs=c("A sample", "sample sentence", 
                                     "sentence for", "for demo", "demo purpose"))
  output$pairs <- renderDataTable({datatable(df, selection = "single", callback=select_text)})

  observeEvent(input$pairs_cell_clicked,{
    info = input$pairs_cell_clicked
    if(is.null(info$value)) return()
    output$selection <- renderText(info$value)  
    })
}

JS inspired from this answer.

Community
  • 1
  • 1
NicE
  • 21,165
  • 3
  • 51
  • 68
  • Highlighting would not help. I really need to select the pair in the sentence, as I further plan to provide buttons to extend the selection to the left and right of the pair. – Imran Ali Mar 02 '17 at 08:14
  • can you translate select to programming terms? You could use `regexpr` to get the index of the match – NicE Mar 02 '17 at 08:15
  • I think [this post](http://stackoverflow.com/questions/6139107/programatically-select-text-in-a-contenteditable-html-element) is somehow related. Sorry that I am unable to come up with the exact terminology – Imran Ali Mar 02 '17 at 08:19
  • Hum ok, I still think it's easier to use a `span` here, you can easily extend the `span` by moving the tags one word up of down using regexp and retrieve the text between it as well. – NicE Mar 02 '17 at 08:22
  • If you used a textAreaInput maybe a selection like the one you posted could work? – NicE Mar 02 '17 at 08:24
  • I want the click on datatable entries to serve as convenience for selection. If the user has to make selection on his own, he will have to click and drag using mouse. – Imran Ali Mar 02 '17 at 08:24
  • 1
    I see, so you want to mimick a click and drag using the mouse programatically when the user clicks on the datatable. Something like this ? http://stackoverflow.com/questions/985272/selecting-text-in-an-element-akin-to-highlighting-with-your-mouse – NicE Mar 02 '17 at 08:29
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/137032/discussion-between-imran-ali-and-nice). – Imran Ali Mar 02 '17 at 08:30