Including dynamically created files into htmlwidgets dependencies

htmlwidget

#1

Hey,

I’m working on a new version of the R package rgexf, a package that essentially creates XML files called GEXF that are used by Gephi and can also be used with some JS libraries. I’m figuring out how to include the gexf-js library with this using htmlwidgets.

The problem is that, as a difference from other JS libraries, gexf-js reads the data from a file, a GEXF file, and hence, for the library to work you need to have the GEXF file somewhere where it can be fetched (sorry if I’m not using the right wording, I’m not a JS person, I’ve just started to read about it!), which I don’t see how to do with htmlwidgets.

I understand that htmlwidgets allows me specifying the lib/ files that will be used during the creation of the widget by including them in inst/htmlwidgets/lib/gexfjs (in my case), which is working, but I have no idea how to include a dynamically created file (a GEXF in my case) in the set of files that are included with the widget.

Again, the idea is that whenever the user calls the R binding function gexfjs(), the user will be passing, say, a path to a GEXF file that he/she wants to visualize, so the widget should take that file and include it in the set of files on which it depends. Makes sense?

Thanks


#2

Makes perfect sense, but unfortunately this is not at all straightforward. I will try over the weekend to post a minimal example to get you started. I don’t expect the bit below to be all that helpful, but in case it is, I will go ahead and add.

library(htmltools)
library(jsonlite)

tf <- tempfile(fileext=".json")

cat(toJSON(mtcars), file=tf)

browsable(
  tagList(
    htmlDependency(
      name = "data",
      version = "0.1.0",
      src = c(file = file.path(dirname(tf))),
      attachment = basename(tf),
      all_files = FALSE
    )
  )
)

#3

@timelyportfolio indeed it helped! I don’t fully understand what’s going on, but I was able to do the same using an XML file (GEXF) that I wanted to include.

Just for the record, here is your code with annotations on the bits I understand :slight_smile: (mostly of course from the htmltools documentation!)

library(htmltools)
library(jsonlite)

# This is just to create a file that we need to include with the widget
tf <- tempfile(fileext=".json")
cat(toJSON(mtcars), file=tf)

browsable( # I guess it opens the website :P
  tagList( # Don't know what this does :P
    htmlDependency(      # Creates a "dependency" so the widget includes it
      name = "data",     # The 'name' of the dependency 
      version = "0.1.0", # The version of it (will create a folder: 'data-0.1.0')
      src = c(file = file.path(dirname(tf))), # Listing the files to include
      attachment = basename(tf), # The name (no path) of the file
      all_files = FALSE  # Will only include  the files specified in `attachment`
    )
  )
)

I guess that the only thing that I don’t like much about this solution is that it includes a block pointing to the file, which I really don’t need. Other than that, this is very useful! It seems to me though that such task should be more straightforward.

Thanks!

PS: Since I wasn’t getting answers on this, I exposed myself to the actual JS library and, with almost no JS experience, modified it so it would allow me to pass the data as a string which I parse using DOMparser() :).


#4

I had assumed the file was too big to send as string, which is usually my first answer, so went with this method instead. Since it seems you are following along, I’ll add this

library(htmltools)
library(jsonlite)

# This is just to create a file that we need to include with the widget
tf <- tempfile(fileext=".json")
cat(toJSON(mtcars), file=tf)

filedep <- htmlDependency(      # Creates a "dependency" so the widget includes it
  name = "data",     # The 'name' of the dependency 
  version = "0.1.0", # The version of it (will create a folder: 'data-0.1.0')
  src = c(file = file.path(dirname(tf))), # Listing the files to include
  attachment = basename(tf), # The name (no path) of the file
  all_files = FALSE  # Will only include  the files specified in `attachment`
)

# see leaflet.extras as an example of attaching dependencies to a widget
#  https://github.com/bhaskarvk/leaflet.extras/blob/master/R/leafletDependencies.R
#  htmlwidgets are a list with a dependency slot $dependencies
#  to which you can specify what else to bring along

# for fun let's assume we have a widget called hw
#   and add the file dependency
hw$dependencies <- c(
  hw$dependencies,  # anything already attached
  filedep # our file dependency
)

# also you could add the dependency as an argument in createWidget
#   https://github.com/ramnathv/htmlwidgets/blob/master/R/htmlwidgets.R#L287-L310

Then with the dependency added, we should have a link reference that contains the relative path of the file. You could use any ajax library (including jQuery) to read the file.

image

Hope this helps.