Выделите слово в DT блестящим на основе регулярных выражений - PullRequest
5 голосов
/ 17 июня 2019

Используя DT в блестящем, я хочу иметь возможность выделить выбранное слово. Установка searchHighlight = TRUE близка к тому, что я хочу, но это также выделит слова, которые включают в себя поиск. Например, если я ищу «on», оно также будет соответствовать «stone», выделяя «on» в середине.

ПРИМЕР ИЗОБРАЖЕНИЯ:

Words within words being highlighted

Я могу уточнить параметры поиска, чтобы regex = TRUE, но тогда подсветка не происходит. Это также верно, если я хочу использовать регулярные выражения, например, «on | in».

ПРИМЕР (включая регулярное выражение):

library(shiny)
library(DT)
library(data.table)

example_data <- data.table(words = c("on", "scone", "wrong", "stone"), 
                           description = c("The word on", "Scone is not on.", "Not on either", "Not here at all"))

ui = shinyUI(fluidPage(

  sidebarLayout(
    sidebarPanel(
      textInput("word_select", label = "Word to search")
      ),
    mainPanel(
      dataTableOutput("word_searched")
    )
  )
))

server = shinyServer(function(input, output, session) {

  output$word_searched <- renderDataTable({
    datatable(
      example_data, 
      options = list(searchHighlight = TRUE, 
                     search = list(regex = TRUE, 
                                   search = paste0("\\b", tolower(input$word_select), "\\b")))
    )
  })

  })

shinyApp(ui = ui, server = server)

DT уже фильтруется по слову с помощью реактивного выражения, поэтому все поля обязательно будут включать выбранное слово, но я просто хочу избежать путаницы со стороны пользователей, считающих, что более длинные слова вводятся в поиск по ошибке. Я не делал этого в примере, но просто подтверждаю, что это не тот элемент, который меня беспокоит.

Спасибо за вашу помощь.

(ИЗМЕНЕНО, чтобы добавить пример слова с пунктуацией в данных примера.)

Ответы [ 2 ]

1 голос
/ 11 июля 2019

Вместо того, чтобы полагаться на функциональность поиска в datatable, вы можете создать элемент reactive, который сначала фильтрует по вводу, а затем заменяет соответствующие слова тем же словом, встроенным в тег <span style="background-color:yellow;">. Это должно обеспечить большую гибкость поиска благодаря более сложному регулярному выражению.

Вам нужно будет добавить escape = F к datatable, чтобы тег HTML интерпретировался правильно. Я добавил options = list(dom = "lt") к datatable, чтобы удалить поле поиска в datatable и обратить внимание на левое поле поиска.

Критерии фильтрации оставлены нечеткими, чтобы таблица не исчезла до тех пор, пока не будет найдено идеальное совпадение - то есть таблица не должна исчезнуть, когда вы наберете «o», потому что нет идеального совпадения, а затем снова появитесь в «on». Затем блики появляются, только если найдено подходящее слово, то есть on, On и on., но не stone, scone и т. Д. Вот пример того, как оно выглядит:

enter image description here

А вот и код. Обратите внимание, что я использую функции фильтрации и мутации dplyr, потому что они могут быть легко применены к нескольким столбцам с помощью их *_all вариантов:

library(shiny)
library(DT)
library(data.table)
library(dplyr) # For `filter_all` and `mutate_all`.

example_data <- iris
    # data.table(words = c("on", "scone", "wrong", "stone"), 
    #                        description = c("The word on", "Scone is not on.", "Not on either", "Not here at all"))

ui = shinyUI(fluidPage(

    sidebarLayout(
        sidebarPanel(
            textInput("word_select", label = "Word to search")
        ),
        mainPanel(
            dataTableOutput("word_searched")
        )
    )
))

server = shinyServer(function(input, output, session) {

    # This is your reactive element.
    df_reactive <- reactive({
            example_data %>%
                # Filter if input is anywhere, even in other words.
                filter_all(any_vars(grepl(input$word_select, ., T, T))) %>% 
                # Replace complete words with same in HTML.
                mutate_all(~ gsub(
                              paste(c("\\b(", input$word_select, ")\\b"), collapse = ""),
                              "<span style='background-color:yellow;'>\\1</span>",
                              .,
                              TRUE,
                              TRUE
                              )
                          )
    })

    # Render your reactive element here.
    output$word_searched <- renderDataTable({
        datatable(df_reactive(), escape = F, options = list(dom = "lt"))
    })

})

shinyApp(ui = ui, server = server)
0 голосов
/ 19 июня 2019

Я не уверен, что это именно то, что вам нужно, но это близко, я думаю: это не выполняет точный поиск (например, "on" будет соответствовать "камню"), но это только выделяет точное совпадение (например, «вкл» не будет выделено).При этом используется библиотека mark.js.

dtable <- datatable(iris[c(1,2,51,52,101,102),], 
                    options = list(
                      mark = list(accuracy = "exactly")
                    )
)
dep1 <- htmltools::htmlDependency(
  "datatables.mark", "2.0.1", 
  src = c(href = "https://cdn.datatables.net/plug-ins/1.10.19/features/mark.js"),
  script = "datatables.mark.min.js")
dep2 <- htmltools::htmlDependency(
  "jquery.mark", "8.11.1", 
  src = c(href = "https://cdnjs.cloudflare.com/ajax/libs/mark.js/8.11.1"), 
  script = "jquery.mark.min.js")
dtable$dependencies <- c(dtable$dependencies, list(dep1, dep2))
dtable

enter image description here

...