I am trying to include an Outdooractive(.com) map in my Shiny app via Outdooractive's API, which uses an html page with a script tag in the header and a JavaScript tag in the body.
When using Outdooractive's html template, saving it as an html file and then including it in a Shiny App via includeHTML("originalFile.html")
, the map is displayed correctly. However, since I want the coordinates for the map to be interactive (without saving it to file in-between), I tried to create the html in a renderUI
using shiny tags, and display it via uiOutput
. When doing so, the JavaScript part does not seem to be processed at all. The header above the map is shown, as is the text below it, but the map is ignored without error message. Interestingly, the same happens when I replace the tag tags$head
by tags$header
.
Here is my app.R
:
library(shiny)
# Define UI for application that draws a histogram
ui <- fluidPage(
# Application title
titlePanel("Outdooractive Map"),
# Sidebar with a text input for coordinates
sidebarLayout(
sidebarPanel(
textInput ("lng",
"Longitude:",
value = "10.000",
),
textInput("lat",
"Latitude:",
value = "45.555")
),
# Show the map
mainPanel(
#includeHTML("originalFile.html") # This works
textOutput("text"), # This shows the correct longitude/latitude
uiOutput("map") # This seems to ignore the script
)
)
)
# Define server logic required to access API
server <- function(input, output) {
output$map <- renderUI({
lng = input$lng
lat = input$lat
tags$html(
tags$div(
tags$head(tags$title("Test"),
HTML('<meta charset="utf-8">'),
tags$script(
src = '//www.outdooractive.com/alpportal/oa_head.js?proj=api-dev-oa&key=yourtest-outdoora-ctiveapi&lang=en'
),
tags$style(HTML(
'.oax .oax-cluster-marker-cont, .oax-cluster-marker-cont {background-color: red;}'
))),
tags$body(
h2("Outdooractive Routes"),
div(class = 'oax-top-cont'),
tags$script(HTML(paste(
'var conf = {frontendtype: "tour", zoom: 11, center:[ ', lng, ", ", lat, ']}; var fvp = oa.api.flexviewpage( conf );')
)),
HTML('There should be a map on top of me.')
)
),
)
})
output$text <- renderText ({
paste(input$lng, input$lat)
})
}
# Run the application
shinyApp(ui = ui, server = server)
To fully replicate the example, this would be the originalFile.html
(which works when line 23 in app.R
is uncommented):
<!DOCTYPE html>
<html>
<head>
<title>outdooractive platform - API Template</title>
<meta charset="utf-8">
<!-- load Outdooractive Javascript API -->
<script type="text/javascript"
src="//www.outdooractive.com/alpportal/oa_head.js?proj=api-dev-oa&key=yourtest-outdoora-ctiveapi&lang=en"></script>
<style>
.oax .oax-cluster-marker-cont, .oax-cluster-marker-cont {
background-color: red;
}
</style>
</head>
<body>
<br>
<br>
<h2>Outdooractive Routes</h2>
<!-- container used by FlexView API -->
<div class="oax-top-cont"></div>
<!-- and some lines of javascript inside a script tag -->
<script type="text/javascript">
var conf = {
frontendtype: "tour", // choose content type
zoom: 11, // set initial zoom level
center: [ 10.292, 47.546 ] // set initial map center
};
var fvp = oa.api.flexviewpage( conf );
</script>
</body>
</html>
Any pointers would be much appreciated.
I would rather call some JavaScript
in an observer:
library(shiny)
library(shinyjs)
library(glue)
# Define UI for application that draws a histogram
ui <- fluidPage(
useShinyjs(),
includeHTML("header.html"), ## see comment
titlePanel("Outdooractive Map"),
sidebarLayout(
sidebarPanel(
textInput ("lng",
"Longitude:",
value = "10.000",
),
textInput("lat",
"Latitude:",
value = "45.555")
),
mainPanel(
div(
class = "oax-top-cont"
)
)
)
)
server <- function(input, output) {
observe({
script <- glue("var conf = {{",
"frontendtype: 'tour',",
"zoom: 11,",
"center: [{input$lng}, {input$lat}]",
"}};",
"var fvp = oa.api.flexviewpage(conf);"
)
runjs(script)
})
}
# Run the application
shinyApp(ui = ui, server = server)
Some remarks:
shinyjs
makes using JavaScript
in R
a piece of cake. You need to call useShinyjs
somewhere in your UI
and then you can issue arbitrary JS
code via runjs
.JS
function whenever lat
and/or lng
change and moved the static part (ie the loading of the API and the css
to the UI.UI
instead of includeHTML
:tags$head(
tags$script(
type = "text/javascript",
src = "//www.outdooractive.com/alpportal/oa_head.js?proj=api-dev-oa&key=yourtest-outdoora-ctiveapi&lang=en"
),
tags$style(...)
)
JS
from outdooractive and I got response code 403
(forbidden), ie outdoor denied my request. My guess is that this is due to using the test account. For whatever funny reason hardcoding that bit in a html file and using includeHTML
seems to work (again I can simply guess, but I assume that outdooractive tries somehow to figure out whether you are using the test account just locally or already in production. And maybe the tags$script
part fails this test, while the static approach passes this test, but this is just a pure guess from my side - more importantly includeHTML
workaround works. But you should try to replace the keys by your own ones and see whether you still need the includeHTML
part or you can directly use tags$script in your
UI`):<script type="text/javascript"
src="//www.outdooractive.com/alpportal/oa_head.js?proj=api-dev-oa&key=yourtest-outdoora-ctiveapi&lang=en">
</script>
<style>
.oax .oax-cluster-marker-cont, .oax-cluster-marker-cont {
background-color: red;
}
</style>
I add a gif of how the app look here in Chrome:
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.