I've got an app that is embedding a timeline via the htmlOutput function in Shiny. The code is a bit long-winded, but can be seen in full
here and a (sort of) working demo can be seen
here. Essentially, though, the problem can be broken down as such:
The problem: The height of the timeline is currently hard coded to maximize the view on my work computer. However, on smaller screens, a height of 1000px is too big,
so I want to change it dynamically such that it's 100% of the height of
the screen minus the height of the menu bar. The code that does this
(using JQuery) is:
$("#timeline-embed").css("height", ($(window).outerHeight() - $("#menu").outerHeight()) + "px");
However,
when I try to add this code to $(document).ready(), $(window).ready(),
or $(window).load(), it fires too quickly as Shiny has not populated the
timeline yet and it re-renders everything, thus resetting the height
value that is hard coded. However, this code does work when used with
window.onresize.
The question: How do I properly get
JQuery to wait to run this piece of code until after Shiny has fully
rendered the timeline? It's worth noting that outside of the Shiny app,
this code works fine if it's appended to $(window).load().
The (barebones) app:# ui.R
shinyUI(fluidPage(
fluidRow(
id = "menu",
column(4, actionButton(...), actionButton(...)),
column(4, offset = 4, actionButton(...), ...)
),
fluidRow(
class = "timeline",
column(12,
div(class = "outer", htmlOutput("timeline"))
)
))
# server.R
library(shiny)
library(magrittr)
source("timelinejs.R")
shinyServer(function(input, output, session) {
tl <- new_timeline() %>% add_event(headline = "Example Event", text = "This is just a sample slide and should be deleted", start_date = "2015")
output$timeline <- renderUI({
tl %>% save(destfile = NA) %>% HTML() # this forces the timeline to spit out the HTML of the timeline so it can be embedded
})
})
# timelinejs.R
.generate_html <- function(timeline) {
timeline_json <- code_to_generate_json() # pseudo-code
html_string <- paste('<!DOCTYPE html><html><head>...</head><body><div id = "timeline-embed" style = "width: 100%; height: 1000px;"></div><script type = "text/javascript">var timeline_json =',
timeline_json,
'; window.timeline = new TL.Timeline("timeline_embed", timeline_json);</script></body></html>')
timeline$html_string <- html_string
return(timeline)
}
save <- function(timeline, destfile) {
timeline <- .generate_html(timeline)
if (
is.na(destfile)) {
return(timeline$html_string)
} else {
write(self$html_string, file = destfile)
}
}