Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multi page intro.js with Shiny

Tags:

r

shiny

intro.js

I am trying to implement into.js multipage functionality on a Shiny app.

The code bellow is an attempt that does not work. The first tab works nicely, the popup for the second page is displayed but without switching the tab.

ui.R

library(shiny)


    shinyUI(tagList(
            tags$head(
                    HTML("<link rel='stylesheet' type='text/css' href='css/introjs.min.css'>")
            ),
            navbarPage("Old Faithful Geyser Data",




      tabPanel(id = "fTab", "First tab",
            HTML("<h1 data-step='1' data-intro='This is a tooltip!'>Basic Usage</h1>"),
           sliderInput("bins",
                       "Number of bins:",
                       min = 1,
                       max = 50,
                       value = 30),

           plotOutput("distPlot"),
           HTML("<a id='startButton' class='btn btn-large btn-success' href='javascript:void(0);'>Help</a>")

      ),
      tabPanel(tabName = "sTab", "Second tab", id = "tt", 
               HTML("<h1 data-step='2' data-intro='This is a second tooltip!'>Basic Usage</h1>"),
                  sliderInput("bins2",
                              "Number of bins:",
                              min = 1,
                              max = 50,
                              value = 30),

                  plotOutput("distPlot2")
                  )
    ),
    HTML("<script type='text/javascript' src='js/intro.min.js'></script>"),
    HTML("<script type='text/javascript'>document.getElementById('startButton').onclick = function() {
         introJs().setOption('doneLabel', 'Next page').start().oncomplete(function() {
         window.location.hash = '#!tt?multipage=true';
         });
         };</script>")  
    ))

server.R

library(shiny)


    shinyServer(function(input, output) {

      output$distPlot <- renderPlot({

        x    <- faithful[, 2] 
        bins <- seq(min(x), max(x), length.out = input$bins + 1)


        hist(x, breaks = bins, col = 'darkgray', border = 'white')

      })
      output$distPlot2 <- renderPlot({


              x    <- faithful[, 2] 
              bins <- seq(min(x), max(x), length.out = input$bins2 + 1)


              hist(x, breaks = bins, col = 'darkgray', border = 'white')

      })

    })

The js and css files from intro.js are in the js and css folders inside the www folder. The intro.js files may be found here

My guess is that I am doing something wrong in the function in the javascript code at the bottom of ui.R. I have tried to adapt the example from here by replacing the window.location.href with window.location.hash and referencing the tab id which is "tt".

like image 397
Valter Beaković Avatar asked Sep 17 '16 09:09

Valter Beaković


2 Answers

@warmoverflow gave an excellent answer. Here is a version of the same answer using rintrojs:

library(shiny)
library(rintrojs)

ui = shinyUI(tagList(
  introjsUI(),
  navbarPage(
    "Old Faithful Geyser Data",

    tabPanel(
      id = "fTab",
      "First tab",
      introBox(
        h1("Basic Usage"),
        data.step = 1,
        data.intro = "This is a tooltip"
      ),
      sliderInput(
        "bins",
        "Number of bins:",
        min = 1,
        max = 50,
        value = 30
      ),

      plotOutput("distPlot"),
      actionButton("startButton", "Help")
    ),
    tabPanel(
      tabName = "sTab",
      "Second tab",
      id = "tt",
      introBox(
        h1("Basic Usage 2"),
        data.step = 2,
        data.intro = "This is a second tooltip"
      ),
      sliderInput(
        "bins2",
        "Number of bins:",
        min = 1,
        max = 50,
        value = 30
      ),

      plotOutput("distPlot2")
    )
  )
))

server = shinyServer(function(input, output, session) {
  output$distPlot <- renderPlot({
    x    <- faithful[, 2]
    bins <- seq(min(x), max(x), length.out = input$bins + 1)


    hist(x,
         breaks = bins,
         col = 'darkgray',
         border = 'white')

  })
  output$distPlot2 <- renderPlot({
    x    <- faithful[, 2]
    bins <- seq(min(x), max(x), length.out = input$bins2 + 1)


    hist(x,
         breaks = bins,
         col = 'darkgray',
         border = 'white')

  })

  observeEvent(input$startButton, {
    introjs(
      session,
      events = list(
        "onchange" = "if (this._currentStep==0) {
        $('a[data-value=\"Second tab\"]').removeClass('active');
        $('a[data-value=\"First tab\"]').addClass('active');
        $('a[data-value=\"First tab\"]').trigger('click');
  }
        if (this._currentStep==1) {
        $('a[data-value=\"First tab\"]').removeClass('active');
        $('a[data-value=\"Second tab\"]').addClass('active');
        $('a[data-value=\"Second tab\"]').trigger('click');
        }"
)
      )

})

  })

shinyApp(ui = ui, server = server)

The tabs don't switch if you go back to the first step of the tour though, so the code only works going forwards through the tour.

NOTE: in rintrojs version 0.1.2.900 and higher, raw javascript needs to be wrapped in I()

like image 118
Carl Avatar answered Nov 18 '22 01:11

Carl


Here is the working solution. Note that you need to

  • Determine the current step to switch tabs. The multi page example does not apply here, as all your steps are on one page (multiple tabs but one page), thus intro.js will display all steps before next page is clicked
  • Use JavaScript/JQuery to simulate the tab click event.

ui.R (server.R unchanged)

library(shiny)


shinyUI(tagList(
  tags$head(
    HTML("<link rel='stylesheet' type='text/css' href='css/introjs.min.css'>")
  ),
  navbarPage("Old Faithful Geyser Data",
             tabPanel(id = "fTab", "First tab",
                      HTML("<h1 data-step='1' data-intro='This is a tooltip!'>Basic Usage</h1>"),
                      sliderInput("bins",
                                  "Number of bins:",
                                  min = 1,
                                  max = 50,
                                  value = 30),

                      plotOutput("distPlot"),
                      HTML("<a id='startButton' class='btn btn-large btn-success' href='javascript:void(0);'>Help</a>")

             ),
             tabPanel(tabName = "sTab", "Second tab", id = "tt", 
                      HTML("<h1 data-step='2' data-intro='This is a second tooltip!'>Basic Usage</h1>"),
                      sliderInput("bins2",
                                  "Number of bins:",
                                  min = 1,
                                  max = 50,
                                  value = 30),

                      plotOutput("distPlot2")
             )
  ),
  HTML("<script type='text/javascript' src='js/intro.min.js'></script>"),
  HTML("<script type='text/javascript'>document.getElementById('startButton').onclick = function() {
       introJs().onchange(function(targetElement) {
          if (this._currentStep==0) {
             $('a[data-value=\"Second tab\"]').removeClass('active');
             $('a[data-value=\"First tab\"]').addClass('active');
             $('a[data-value=\"First tab\"]').trigger('click');
          }
          if (this._currentStep==1) {
             $('a[data-value=\"First tab\"]').removeClass('active');
             $('a[data-value=\"Second tab\"]').addClass('active');
             $('a[data-value=\"Second tab\"]').trigger('click');
          }
       }).start();
       };</script>")  
    ))
like image 4
Xiongbing Jin Avatar answered Nov 18 '22 03:11

Xiongbing Jin