How to replace code in <head> sections of all HTML documents in a directory using R - html

I'm looking for an efficient way to modify the code between<head> </head> tags for a large number of .html documents that are all stored in the same folder.
R is mandotory since this is part of an rmarkdown classroom project and I'd like the code to be understood by students.
For my purpose, it would be sufficient to overwrite every document header with the same lines which, e.g., adjust CSS or links .js files.
I tried to do this in R using functions like readLines() and writeLines() in conjunction with regular expressions but that seems overly cumbersome. I'd like to have a more elegant and specific solution that makes use of the DOM.

I just realized, that you wanted to replace all child nodes. Here is the code to achieve that.
The script uses lapply to open each file, parse the XML code, remove all child nodes of head and adds a script element with the argument src to it.
Replace all child nodes
library(XML)
files <- list.files(full.names = T, pattern = "*.html")
lapply(files, function(f) {
content <- xmlInternalTreeParse(f, isHTML = T)
# get head node
headNode <- getNodeSet(content, path = "//head")
# remove all child nodes
do.call(removeChildren, args = list(kids = names(xmlChildren(headNode[[1]])), node = headNode[[1]]))
# create new nodes
newNode <- newXMLNode("script", attrs = list(src = "myScript.js"))
# add new nodes
addChildren(headNode[[1]], newNode)
saveXML(doc = content, file = f)
})
Append a new node
library(XML)
files <- list.files(full.names = T, pattern = "*.html")
lapply(files, function(f) {
content <- xmlInternalTreeParse(f, isHTML = T)
headNode <- getNodeSet(content, path = "//head")
newNode <- newXMLNode("script", attrs = list(src = "myScript.js"))
addChildren(headNode[[1]], newNode)
saveXML(doc = content, file = f)
})

Related

Deleting commas in R Markdown html output

I am using R Markdown to create an html file for regression results tables, which are produced by stargazer and lfe in a code chunk.
library(lfe); library(stargazer)
data <- data.frame(x = 1:10, y = rnorm(10), z = rnorm(10))
result <- stargazer(felm(y ~ x + z, data = data), type = 'html')
I create a html file win an inline code r result after the chunk above. However, a bunch of commas appear at the top of the table.
When I check the html code, I see almost every </tr> is followed by a comma.
How can I delete these commas?
Maybe not what you are looking for exactly but I am a huge fan of modelsummary. I knit to HTML to see how it looks and then usually knit to pdf. The modelsummary equivalent would look something like this
library(lfe)
library(modelsummary)
data = data.frame(x = 1:10, y = rnorm(10), z = rnorm(10))
results = felm(y ~ x + z, data = data)
modelsummary(results)
There are a lot of ways to customize it through kableExtra and other packages. The documentation is really good. Here is kind of a silly example
library(kableExtra)
modelsummary(results,
coef_map = c("x" = "Cool Treatment",
"z" = "Confounder",
"(Intercept)" = "(Intercept)")) %>%
row_spec(1, background = "#F5ABEA")

RShiny integration with google sites

I would like to be able to add interactive shiny elements into a website. My HTML skills are not up to speed to make fancy websites from scratch. Google allows you to make nice slick well functioning websites fast, using sites.google.com.
I was wondering if it is possible to add R Shiny elements into a sites.google.com site.
For example, it is possible to put
library(plotly)
trace_0 <- rnorm(100, mean = 5)
trace_1 <- rnorm(100, mean = 0)
trace_2 <- rnorm(100, mean = -5)
x <- c(1:100)
data <- data.frame(x, trace_0, trace_1, trace_2)
p <- plot_ly(data, x = ~x, y = ~trace_0, name = 'trace 0', type = 'scatter', mode = 'lines') %>%
add_trace(y = ~trace_1, name = 'trace 1', mode = 'lines+markers') %>%
add_trace(y = ~trace_2, name = 'trace 2', mode = 'markers')
into https://sites.google.com/view/shinytest ?
EDIT: I read that in Shiny you can build a 'raw' HTML UI instead of a ShinyUI (shiny.rstudio.com/articles/html-ui.html). Would it be possible to extract the HTML from an existing site (e.g. the sites.google site from the example and keep all its functionality) and start using that as a base HTML UI in which Shiny elements can be added (and thususing the server part as back-end)?

Using R and plot.ly, how to save multiples htmlwidgets to my html?

I´m starting to play with plot.ly in R and I´m amazed with the possibilities to publish my graphs directly in html using htmlwidgets.
Until now I´m unable to save multiple widgets in the same html.
I have saved multiple widgets in stand-alone htmls and than combine it by hand in the html code, but I would like to be able to do it in R.
A simple example:
#graph
graph<- ggplot(df, aes(x = Data, y=tax))+ geom_bar(stat='identity')
gg <- ggplotly(graph)
# save as HtmlWigdet
htmlwidgets::saveWidget(as.widget(gg), "Index.html")
How can I parse multiple ggplotly objects to saveWidgets?
(This is my first question here in stackoverflow, hope I did it right! Regards!)
This is the function I adapted from bits and pieces of the htmltools package to save a tag list and then return an iframe tag. You can wrap multiple htmlwidgets with htmltools::tagList, and then use this function to save the whole bunch.
save_tags <- function (tags, file, selfcontained = F, libdir = "./lib")
{
if (is.null(libdir)) {
libdir <- paste(tools::file_path_sans_ext(basename(file)),
"_files", sep = "")
}
htmltools::save_html(tags, file = file, libdir = libdir)
if (selfcontained) {
if (!htmlwidgets:::pandoc_available()) {
stop("Saving a widget with selfcontained = TRUE requires pandoc. For details see:\n",
"https://github.com/rstudio/rmarkdown/blob/master/PANDOC.md")
}
htmlwidgets:::pandoc_self_contained_html(file, file)
unlink(libdir, recursive = TRUE)
}
return(htmltools::tags$iframe(src= file, height = "400px", width = "100%", style="border:0;"))
}
What is the use-case you're after? You may want to consider adding these graphs to a Flexdashboard (which is created in R Markdown). It's been my recent goto, combined with Plotly.

Edit map with "R for leaflet"

I have a script which allows me to generate a map with with "R for leaflet" :
library(htmlwidgets)
library(raster)
library(leaflet)
# PATHS TO INPUT / OUTPUT FILES
projectPath = "path"
#imgPath = paste(projectPath,"data/cea.tif", sep = "")
#imgPath = paste(projectPath,"data/o41078a1.tif", sep = "") # bigger than standard max size (15431804 bytes is greater than maximum 4194304 bytes)
imgPath = paste(projectPath,"/test.tif", sep = "")
outPath = paste(projectPath, "/leaflethtmlgen.html", sep="")
# load raster image file
r <- raster(imgPath)
# reproject the image, if necessary
#crs(r) <- sp::CRS("+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs")
# color palette, which is interpolated ?
pal <- colorNumeric(c("#FF0000", "#666666", "#FFFFFF"), values(r),
na.color = "transparent")
# create the leaflet widget
m <- leaflet() %>%
addTiles() %>%
addRasterImage(r, colors=pal, opacity = 0.9, maxBytes = 123123123) %>%
addLegend(pal = pal, values = values(r), title = "Test")
# save the generated widget to html
# contains the leaflet widget AND the image.
saveWidget(m, file = outPath, selfcontained = FALSE, libdir = 'leafletwidget_libs')
My problem is that this is generating a html file and I need this map to be dyanamic. For example, when a user click on some html button which is not integrate on the map, I want to add a rectangle on the map. Any solutions would be welcome...
Leaflet itself does not provide the interactive functionality you are looking for. One solution is to use shiny, which is a web application framework for R. From simple R code, it generates a web page, and runs R on the server-side to respond to user interaction. It is well documented, has a gallery of examples, and a tutorial to get new users started.
It works well with leaflet. One of the examples on the shiny web site uses it, and also includes a link to the source code.
Update
Actually, if simple showing/hiding of elements is enough, leaflet alone will suffice with the use of groups. From the question it's not very clear how dynamic you need it to be.

Generate an HTML report based on user interactions in shiny

I have a shiny application that allows my user to explore a dataset. The idea is that the user explores the dataset, and any interesting things the user finds he will share with his client via email. I don't know in advance how many things the user will find interesting. So, next to each table or chart I have an "add this item to the report" button, which isolates the current view and adds it to a reactiveValues list.
Now, what I want to do is the following:
Loop through all the items in the reactiveValues list,
Generate some explanatory text describing the item (This text should preferably be formatted HTML/markdown, rather than code comments)
Display the item
Capture the output of this loop as HTML
Display this HTML in Shiny as a preview
write this HTML to a file
knitr seems to do exactly the reverse of what I want - where knitr allows me to add interactive shiny components in an otherwise static document, I want to generate HTML in shiny (maybe using knitr, I don't know) based on static values the user has created.
I've constructed a minimum not-working example below to try to indicate what I would like to do. It doesn't work, it's just for demonstration purposes.
ui = shinyUI(fluidPage(
title = "Report generator",
sidebarLayout(
sidebarPanel(textInput("numberinput","Add a number", value = 5),
actionButton("addthischart", "Add the current chart to the report")),
mainPanel(plotOutput("numberplot"),
htmlOutput("report"))
)
))
server = shinyServer(function(input, output, session){
#ensure I can plot
library(ggplot2)
#make a holder for my stored data
values = reactiveValues()
values$Report = list()
#generate the plot
myplot = reactive({
df = data.frame(x = 1:input$numberinput, y = (1:input$numberinput)^2)
p = ggplot(df, aes(x = x, y = y)) + geom_line()
return(p)
})
#display the plot
output$numberplot = renderPlot(myplot())
# when the user clicks a button, add the current plot to the report
observeEvent(input$addthischart,{
chart = isolate(myplot)
isolate(values$Report <- c(values$Report,list(chart)))
})
#make the report
myreport = eventReactive(input$addthischart,{
reporthtml = character()
if(length(values$Report)>0){
for(i in 1:length(values$Report)){
explanatorytext = tags$h3(paste(" Now please direct your attention to plot number",i,"\n"))
chart = values$Report[[i]]()
theplot = HTML(chart) # this does not work - this is the crux of my question - what should i do here?
reporthtml = c(reporthtml, explanatorytext, theplot)
# ideally, at this point, the output would be an HTML file that includes some header text, as well as a plot
# I made this example to show what I hoped would work. Clearly, it does not work. I'm asking for advice on an alternative approach.
}
}
return(reporthtml)
})
# display the report
output$report = renderUI({
myreport()
})
})
runApp(list(ui = ui, server = server))
You could capture the HTML of your page using html2canvas and then save the captured portion of the DOM as a image using this answer, this way your client can embed this in any HTML document without worrying about the origin of the page contents