最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - focusing the cursor in textArea after clicking an action button in shiny - Stack Overflow

programmeradmin2浏览0评论

I am not an expert in html or JavaScript by any means. So, I hope for you assistance with this issue.

I thought I should provide a smaller version of my app in order to be able to explain the problem. Here is the app.R of a simple app that allows the user to write, let's say a word, in the textArea. The first letter of the word will appear automatically as the label of the action button, if the user clicks on the action button, the contents of the textArea will be updated stating whether the word the user wrote starts with a vowel or with a consonant.

library(shiny)
library(shinydashboard)

# Define UI for application 
ui <- dashboardPage(
    dashboardHeader(
            title = "page_title"
    ),
    dashboardSidebar(
    ),
    dashboardBody(
            tabBox(title = "app_title",
                    id = "id", width = "800px",
                    tabPanel("tab1)",
                             fluidRow(
                                     column(width = 12,
                                            box(
                                                    status = "info", solidHeader = TRUE,
                                                    collapsible = FALSE,
                                                    width = 12, 
                                                    title = "textInput", 
                                                    tags$textarea(id = "text_input1", rows =  2, cols = 50, "", autofocus = "autofocus"), 
                                                    fluidRow(
                                                            column(width = 12, 
                                                            actionButton("actionbutton1", label = textOutput("actionbutton1_label"))
                                                            )))))),
                    tabPanel("tab2"
                    ))))

# Define server logic 

server <- function(input, output, session) {
    data1 <- eventReactive(input$actionbutton1, {substr(input$text_input1, 1, 1)})
    output$actionbutton1_label <- renderPrint(cat(noquote({substr(input$text_input1, 1, 1)})))
    observe({
            if (input$actionbutton1 == 0) return()
            isolate({
                    if (data1() %in% c("a", "e", "i", "o", "u")) {
                            updateTextInput(session, "text_input1",
                                            value = paste(input$text_input1, "starts with a vowel", "", sep = " "))
                    }
                    else {
                            updateTextInput(session, "text_input1",
                                            value = paste(input$text_input1, "starts with a consonant", "", sep = " "))
                    }
            })
    })}
# Run the application 
shinyApp(ui = ui, server = server)

The problem definition: When you run the above app for the first time, you will see the cursor in the textArea because the argument autofocus = "autofocus" in the textArea tag definition, so no problem with the focus on loading. When you click on the action button, the cursor is no longer in the textArea. This may seem unnecessary in the case of this simple app, but in the case of the actual app, it's important and I'd hope to have the cursor back in the textArea after the user clicks the action button.

The issue again is that whenever the user of the app clicks on the action button, the cursor disappears from the textArea and the user of the app has to click in the text area to get the cursor back and continue with his/her input. I hope to save the user this extra click by keeping the cursor always alive and focused in the textArea no matter how many times the user uses other elements of the app interface.

Research: there are many posts online relating to how to control the position of the cursor. Among these posts, I think, and please correct me if I'm wrong, that this approach is pretty much the most relevant one to what I hope to acplish:

.html

What is it specifically that I need help with:

If you click on the above link, you will find a very interesting piece of html code that I copy here:

<form name="myform2">
<input type="text" name="mytextfield2">
<input type="button" name="mybutton" value="Set Focus"   OnClick="document.myform2.mytextfield2.focus();">
</form>

Here is what I hope you're able to help me with, how and where can I embed this code in my shiny ui.R? Of course, I will have to assign a form for both the textArea and the button and I will change the names of the textArea and the button accordingly. I just need to pretty much make the above html code ui.R friendly (readable and executable). Any help with this is very much appreciated.

What I tried so far and it didn't work:

tags$head(HTML("<form name="myform2">
                         <input type="text" name="text_input1">
                         <input type="button" name="addword1" value="Set Focus" OnClick="document.myform2.text_input1.focus();">
                         </form>"))

As you can see, the syntax is messed up and all sorts of syntax warnings were raised up when I embedded the above code in the ui.R file.

Possibly important: I am using shiny dashboard and both the textArea ad the action button are defined in a tabPanel in a tabBox in the dashboardBody.

Thanks a lot

I am not an expert in html or JavaScript by any means. So, I hope for you assistance with this issue.

I thought I should provide a smaller version of my app in order to be able to explain the problem. Here is the app.R of a simple app that allows the user to write, let's say a word, in the textArea. The first letter of the word will appear automatically as the label of the action button, if the user clicks on the action button, the contents of the textArea will be updated stating whether the word the user wrote starts with a vowel or with a consonant.

library(shiny)
library(shinydashboard)

# Define UI for application 
ui <- dashboardPage(
    dashboardHeader(
            title = "page_title"
    ),
    dashboardSidebar(
    ),
    dashboardBody(
            tabBox(title = "app_title",
                    id = "id", width = "800px",
                    tabPanel("tab1)",
                             fluidRow(
                                     column(width = 12,
                                            box(
                                                    status = "info", solidHeader = TRUE,
                                                    collapsible = FALSE,
                                                    width = 12, 
                                                    title = "textInput", 
                                                    tags$textarea(id = "text_input1", rows =  2, cols = 50, "", autofocus = "autofocus"), 
                                                    fluidRow(
                                                            column(width = 12, 
                                                            actionButton("actionbutton1", label = textOutput("actionbutton1_label"))
                                                            )))))),
                    tabPanel("tab2"
                    ))))

# Define server logic 

server <- function(input, output, session) {
    data1 <- eventReactive(input$actionbutton1, {substr(input$text_input1, 1, 1)})
    output$actionbutton1_label <- renderPrint(cat(noquote({substr(input$text_input1, 1, 1)})))
    observe({
            if (input$actionbutton1 == 0) return()
            isolate({
                    if (data1() %in% c("a", "e", "i", "o", "u")) {
                            updateTextInput(session, "text_input1",
                                            value = paste(input$text_input1, "starts with a vowel", "", sep = " "))
                    }
                    else {
                            updateTextInput(session, "text_input1",
                                            value = paste(input$text_input1, "starts with a consonant", "", sep = " "))
                    }
            })
    })}
# Run the application 
shinyApp(ui = ui, server = server)

The problem definition: When you run the above app for the first time, you will see the cursor in the textArea because the argument autofocus = "autofocus" in the textArea tag definition, so no problem with the focus on loading. When you click on the action button, the cursor is no longer in the textArea. This may seem unnecessary in the case of this simple app, but in the case of the actual app, it's important and I'd hope to have the cursor back in the textArea after the user clicks the action button.

The issue again is that whenever the user of the app clicks on the action button, the cursor disappears from the textArea and the user of the app has to click in the text area to get the cursor back and continue with his/her input. I hope to save the user this extra click by keeping the cursor always alive and focused in the textArea no matter how many times the user uses other elements of the app interface.

Research: there are many posts online relating to how to control the position of the cursor. Among these posts, I think, and please correct me if I'm wrong, that this approach is pretty much the most relevant one to what I hope to acplish:

http://www.mediacollege./internet/javascript/form/focus.html

What is it specifically that I need help with:

If you click on the above link, you will find a very interesting piece of html code that I copy here:

<form name="myform2">
<input type="text" name="mytextfield2">
<input type="button" name="mybutton" value="Set Focus"   OnClick="document.myform2.mytextfield2.focus();">
</form>

Here is what I hope you're able to help me with, how and where can I embed this code in my shiny ui.R? Of course, I will have to assign a form for both the textArea and the button and I will change the names of the textArea and the button accordingly. I just need to pretty much make the above html code ui.R friendly (readable and executable). Any help with this is very much appreciated.

What I tried so far and it didn't work:

tags$head(HTML("<form name="myform2">
                         <input type="text" name="text_input1">
                         <input type="button" name="addword1" value="Set Focus" OnClick="document.myform2.text_input1.focus();">
                         </form>"))

As you can see, the syntax is messed up and all sorts of syntax warnings were raised up when I embedded the above code in the ui.R file.

Possibly important: I am using shiny dashboard and both the textArea ad the action button are defined in a tabPanel in a tabBox in the dashboardBody.

Thanks a lot

Share Improve this question edited Jul 14, 2016 at 6:43 mansanto asked Jul 13, 2016 at 22:38 mansantomansanto 3705 silver badges18 bronze badges 3
  • Does your actionButton has other uses? Because actionButton in Shiny already has an onclick event, so you'll need to either read the actionButton value using the existing onclick event, or remove/modify existing onclick event. – Xiongbing Jin Commented Jul 13, 2016 at 23:52
  • Hi warmoverflow, the action button indeed is used to update the text inside the textArea and it does this successfully. However, as I mentioned, after the user clicks on the action button to update the user's input in the textArea and after this update actually happens, the cursor isn't focused anymore in the textArea and the user has to click inside the textArea to get the cursor to appear again. what do you think? – mansanto Commented Jul 14, 2016 at 0:41
  • You have to paste text together. The way you are writing the strings in the HTML function is wrong. – Carl Commented Jul 14, 2016 at 1:12
Add a ment  | 

2 Answers 2

Reset to default 6

Here is a working version like you asked:

library(shiny)
library(shinydashboard)

# Define UI for application 
ui <- dashboardPage(
  dashboardHeader(
    title = "page_title"
  ),
  dashboardSidebar(
  ),
  dashboardBody(tags$head(tags$script(
    'Shiny.addCustomMessageHandler("refocus",
                                  function(NULL) {
                                    document.getElementById("text_input1").focus();
                                  });'
    )),
    tabBox(title = "app_title",
           id = "id", width = "800px",
           tabPanel("tab1",
                    fluidRow(
                      column(width = 12,
                             box(
                               status = "info", solidHeader = TRUE,
                               collapsible = FALSE,
                               width = 12, 
                               title = "textInput", 
                               tags$textarea(id = "text_input1", rows =  2, cols = 50, "", autofocus = "autofocus"), 
                               fluidRow(
                                 column(width = 12, 
                                        actionButton("actionbutton1", label = textOutput("actionbutton1_label"))
                                 )))))),
           tabPanel("tab2"
           ))))

# Define server logic 

server <- function(input, output, session) {
  data1 <- eventReactive(input$actionbutton1, {

    substr(input$text_input1, 1, 1)

    })

  output$actionbutton1_label <- renderPrint(cat(noquote({substr(input$text_input1, 1, 1)})))

  observeEvent(input$actionbutton1,{

    isolate({
      if (data1() %in% c("a", "e", "i", "o", "u")) {
        updateTextInput(session, "text_input1",
                        value = paste(input$text_input1, "starts with a vowel", "", sep = " "))
      }
      else {
        updateTextInput(session, "text_input1",
                        value = paste(input$text_input1, "starts with a consonant", "", sep = " "))
      }

      session$sendCustomMessage(type="refocus",message=list(NULL))

    })

  })}
# Run the application 
shinyApp(ui = ui, server = server)

So on the UI side you'll need something like this:

tags$script('
Shiny.addCustomMessageHandler("myCallbackHandler",
        function(null) {
          document.myform2.text_input1.focus();
        });
')

Then in the observeEvent related to the actionButton you call this function:

session$sendCustomMessage("myCallbackHandler",list(NULL)) 

So anytime in the server when you call that custom handler it'll focus to the input. You may need to change the javascript in the function to make your page work since I don't know the names of the objects in your HTML.

Hope this helps.

发布评论

评论列表(0)

  1. 暂无评论