2

I'm building an app which includes embedded video and audio files. I've got action buttons that let users navigate forwards, but I need them to be greyed out until the embedded video/audio is complete.

With things that require user input I find this easy enough to do with enable/disable/toggle and shinyjs, but I can't find a way to do it with embedded files. I imagine I could do something with observeEvent, but I don't know what the observed event would be - does a video finishing have a unique hidden id somewhere?

library(shiny)
ui <- fluidPage(
  HTML('<iframe width="560" height="315" src="https://www.youtube.com/embed/Hrc1WrC8ihE" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>'), #random youtube video without copyright
  br(),
  br(),
  actionButton("test", "test") #need this disabled out until the video is complete
)
server <- function(input, output, session) {
}
shinyApp(ui, server)

It's probably something that could be sorted with javascript too, but I have no experience there.

Any help would be appreciated!

Edit

The video embedding in this example is different to what I've got in my code just to keep it reproducible. I have saved mp4 files that I'm embedding, not youtube links.

Casper
  • 33
  • 3
  • Frankly, I would be surprised if the solution did not _require_ manual javascript, not just "could be". The fact that you're opening an `iframe` might complicate things, as that means you want the parent page to "snoop" on the child frame to know when something has occurred. Generally (I'm not an iframe expert), there are mechanisms for explicit communication between the parent and iframe, perhaps using postMessage, see https://javascriptbit.com/transfer-data-between-parent-window-and-iframe-postmessage-api/. Hope this helps! – r2evans Apr 01 '23 at 16:27
  • 1
    I might have added a complication there then - I added the iframe for a reprex. In my actual code I have embedded mp4. Didn't realize that'd make a big difference, I'll post an edit. – Casper Apr 01 '23 at 16:49

1 Answers1

1

An iframe has a load event. This works but the video is quickly loaded so it's not easy to see:

library(shiny)

js <- "
$(document).ready(function() {
  $('#thebutton').prop('disabled', true);
  $('iframe').on('load', function() {
    $('#thebutton').prop('disabled', false);
  });
});
"

ui <- fluidPage(
  tags$head(
    tags$script(HTML(js))
  ),
  HTML('<iframe width="560" height="315" src="https://www.youtube.com/embed/Hrc1WrC8ihE" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>'), #random youtube video without copyright
  br(), br(),
  actionButton("thebutton", "test") 
)

server <- function(input, output, session) { }

shinyApp(ui, server)
Stéphane Laurent
  • 75,186
  • 15
  • 119
  • 225
  • Ah, I need it to be greyed out until video completion though, when the embedded video is done playing, not when it's loaded in. Also, would this work for embedded mp4 files, as opposed to iframes? – Casper Apr 01 '23 at 17:40
  • @Casper There's a `play` event for videos. – Stéphane Laurent Apr 01 '23 at 18:56