Valter Beaković Valter Beaković - 2 months ago 22
R Question

Multi page intro.js with Shiny

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".

Answer

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>")  
    ))
Comments