diff --git a/R/plotly.R b/R/plotly.R index 0d6e3d1a9b..b0cb454b98 100644 --- a/R/plotly.R +++ b/R/plotly.R @@ -192,6 +192,12 @@ layout <- function(p = last_plot(), ..., #' @param displayModeBar display the modebar (T, F, or 'hover') #' @param displaylogo add the plotly logo on the end of the modebar #' @param plot3dPixelRatio increase the pixel ratio for 3D plot images +#' @param mathjax If \code{FALSE}, don't attempt to include mathjax. +#' If \code{'cdn'}, mathjax will be loaded externally (meaning an internet +#' connection is needed to view the graph). If \code{'local'}, a local copy +#' of mathjax will be included. For this to work, you'll need a local copy of +#' plotly.js and set the environment variable plotly_jsdir to its location on +#' your machine. #' @author Carson Sievert #' @export @@ -201,7 +207,7 @@ config <- function(p = last_plot(), staticPlot = F, workspace = F, editable = F, autosizable = F, fillFrame = F, scrollZoom = F, doubleClick = 'reset+autosize', showTips = F, showLink = T, sendData = T, linkText = 'Edit chart', displayModeBar = 'hover', - displaylogo = T, plot3dPixelRatio = 2) { + displaylogo = T, plot3dPixelRatio = 2, mathjax = FALSE) { conf <- list( staticPlot = staticPlot, workspace = workspace, @@ -216,7 +222,8 @@ config <- function(p = last_plot(), staticPlot = F, workspace = F, editable = F, linkText = linkText, displayModeBar = displayModeBar, displaylogo = displaylogo, - plot3dPixelRatio = plot3dPixelRatio + plot3dPixelRatio = plot3dPixelRatio, + mathjax = mathjax ) p <- last_plot(p) p$config <- c(p$config, conf) diff --git a/R/print.R b/R/print.R index ff4c507d63..21db4ec657 100644 --- a/R/print.R +++ b/R/print.R @@ -49,6 +49,7 @@ as.widget <- function(x, ...) { padding = 5, browser.fill = TRUE ), + dependencies = plotly_dependencies(p), ... ) } diff --git a/R/utils.R b/R/utils.R index 7b33882c71..04f8184182 100644 --- a/R/utils.R +++ b/R/utils.R @@ -229,3 +229,92 @@ cat_profile <- function(key, value, path = "~") { message("Adding plotly_", key, " environment variable to ", r_profile) cat(snippet, file = r_profile, append = TRUE) } + + +# Needed since we can't control the order of conditional dependencies +plotly_dependencies <- function(p) { + deps <- list( + html_dependency_mathjax(p), + html_dependency_geo(p), + # TODO: build plotlyjs without d3/topojson and include separately? + html_dependency_plotly() + ) + # mathjax/geo dependencies may return NULL which can cause problems + Filter(Negate(is.null), deps) +} + +html_dependency_mathjax <- function(p) { + if (isTRUE(p$config$mathjax == "local")) { + path <- Sys.getenv("plotly_jsdir", unset = NA) + if (is.na(path)) { + stop("Local mathjax requires a local clone of the plotly.js repo \n", + "https://github.com/plotly/plotly.js \n", + "Once you have plotly.js locally, set the plotly_jsdir \n", + "environment variable with the path to plotly.js") + } else { + mj <- file.path(path, "dist", "extras", "mathjax", "MathJax.js") + if (!file.exists(mj)) stop("Couldn't locate MathJax.js") + # parse the version + mathjax <- readLines(mj) + pat <- 'MathJax.fileversion="[0-9]+.[0-9]+.[0-9]+' + ver <- regmatches(mathjax, regexpr(pat, mathjax)) + ver <- sub('"', '', strsplit(ver, "=")[[1]][2]) + dep <- htmltools::htmlDependency( + name = "mathjax", + version = ver, + src = dirname(mj), + script = c(basename(mj), "config/TeX-AMS-MML_SVG.js") + ) + return(dep) + } + } + if (isTRUE(p$config$mathjax == "cdn")) { + dep <- htmltools::htmlDependency( + name = "mathjax-cdn", + version = "1.0", + src = system.file("htmlwidgets", "lib", "mathjax", package = "plotly"), + script = "mathjax-cdn.js" + ) + return(dep) + } + return(NULL) +} + +html_dependency_geo <- function(p) { + types <- unlist(lapply(p$data, "[[", "type")) + # if there are any geo trace(s), add the geo assets dependency + if (any(grepl("geo|choropleth", types))) { + path <- Sys.getenv("plotly_jsdir", unset = NA) + if (is.na(path)) { + warning("Rendering 'geo' traces without an internet connection \n", + "requires a local clone of the plotly.js repo \n", + "https://github.com/plotly/plotly.js \n", + "Once you have plotly.js locally, set the plotly_jsdir \n", + "environment variable with the path to plotly.js") + return(NULL) + } else { + geo <- file.path(path, "dist", "plotly-geo-assets.js") + if (!file.exists(geo)) stop("Couldn't locate plotly-geo-assets.js") + dep <- htmltools::htmlDependency( + name = "plotly-geo-assets", + src = dirname(geo), + version = plotly_version(), + script = basename(geo) + ) + } + } +} + +html_dependency_plotly <- function() { + htmltools::htmlDependency( + name = "plotly.js", + src = system.file("htmlwidgets", "lib", "plotlyjs", package = "plotly"), + version = plotly_version(), + script = "plotly-latest.min.js" + ) +} + +plotly_version <- function() { + pkg <- system.file("htmlwidgets", "lib", "plotlyjs", "package.json", package = "plotly") + jsonlite::fromJSON(pkg)$version +} diff --git a/inst/htmlwidgets/lib/mathjax/mathjax-cdn.js b/inst/htmlwidgets/lib/mathjax/mathjax-cdn.js new file mode 100644 index 0000000000..a1b2281f53 --- /dev/null +++ b/inst/htmlwidgets/lib/mathjax/mathjax-cdn.js @@ -0,0 +1,6 @@ +(function () { + var script = document.createElement("script"); + script.type = "text/javascript"; + script.src = "https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_SVG"; + document.getElementsByTagName("head")[0].appendChild(script); +})(); diff --git a/inst/htmlwidgets/lib/plotlyjs/package.json b/inst/htmlwidgets/lib/plotlyjs/package.json new file mode 100644 index 0000000000..8b3b1cb104 --- /dev/null +++ b/inst/htmlwidgets/lib/plotlyjs/package.json @@ -0,0 +1,103 @@ +{ + "name": "plotly.js", + "version": "1.4.1", + "description": "The open source javascript graphing library that powers plotly", + "license": "MIT", + "main": "./src/index.js", + "webpack": "./dist/plotly.min.js", + "repository": { + "type": "git", + "url": "https://github.com/plotly/plotly.js.git" + }, + "bugs": { + "url": "https://github.com/plotly/plotly.js/issues" + }, + "author": "Plotly, Inc.", + "keywords": [ + "graphing", + "plotting", + "data", + "visualization", + "plotly" + ], + "scripts": { + "preprocess": "node tasks/preprocess.js", + "bundle": "node tasks/bundle.js", + "header": "node tasks/header.js", + "build": "npm run preprocess && npm run bundle && npm run header", + "cibuild": "node tasks/cibundle.js", + "watch": "node tasks/watch_plotly.js", + "lint": "cd src && jshint . || true", + "test-jasmine": "karma start test/jasmine/karma.conf.js", + "citest-jasmine": "karma start test/jasmine/karma.ciconf.js", + "test-image": "./tasks/test_image.sh", + "test-syntax": "node test/syntax_test.js", + "test": "npm run test-jasmine && npm test-image", + "start-test_dashboard": "node devtools/test_dashboard/server.js", + "start-image_viewer": "node devtools/image_viewer/server.js", + "baseline": "./tasks/baseline.sh", + "version": "npm run build && git add -A dist", + "postversion": "git push && git push --tags" + }, + "dependencies": { + "3d-view": "^2.0.0", + "alpha-shape": "^1.0.0", + "arraytools": "^1.0.0", + "convex-hull": "^1.0.3", + "d3": "3.5.6", + "delaunay-triangulate": "^1.1.6", + "es6-promise": "^3.0.2", + "fast-isnumeric": "^1.1.1", + "fs-extra": "^0.26.2", + "gl-error2d": "^1.0.0", + "gl-error3d": "^1.0.0", + "gl-line2d": "^1.2.1", + "gl-line3d": "^1.0.1", + "gl-mat4": "^1.1.2", + "gl-mesh3d": "^1.0.4", + "gl-plot2d": "^1.1.6", + "gl-plot3d": "^1.3.0", + "gl-scatter2d": "^1.0.5", + "gl-scatter2d-fancy": "^1.1.1", + "gl-scatter3d": "^1.0.4", + "gl-select-box": "^1.0.1", + "gl-spikes2d": "^1.0.1", + "gl-surface3d": "^1.1.0", + "mouse-change": "^1.1.1", + "mouse-wheel": "^1.0.2", + "ndarray": "^1.0.16", + "ndarray-fill": "^1.0.1", + "ndarray-homography": "^1.0.0", + "ndarray-ops": "^1.2.2", + "right-now": "^1.0.0", + "robust-orientation": "^1.1.3", + "sane-topojson": "^1.2.0", + "superscript-text": "^1.0.0", + "tinycolor2": "1.1.2", + "topojson": "^1.6.19" + }, + "devDependencies": { + "brfs": "^1.4.1", + "browserify": "^12.0.1", + "browserify-transform-tools": "^1.5.0", + "ecstatic": "^1.2.0", + "falafel": "^1.2.0", + "glob": "^6.0.1", + "jasmine-core": "^2.3.4", + "jshint": "^2.8.0", + "karma": "^0.13.15", + "karma-browserify": "^4.4.1", + "karma-chrome-launcher": "^0.2.1", + "karma-coverage": "^0.5.3", + "karma-firefox-launcher": "^0.1.6", + "karma-jasmine": "^0.3.6", + "node-sass": "^3.4.1", + "open": "0.0.5", + "prepend-file": "^1.3.0", + "prettysize": "0.0.3", + "through2": "^2.0.0", + "uglify-js": "^2.5.0", + "watchify": "^3.6.0", + "xml2js": "^0.4.15" + } +} diff --git a/inst/htmlwidgets/plotly.yaml b/inst/htmlwidgets/plotly.yaml deleted file mode 100644 index a8f8da40a9..0000000000 --- a/inst/htmlwidgets/plotly.yaml +++ /dev/null @@ -1,5 +0,0 @@ -dependencies: - - name: plotlyjs - version: 1.4.1 - src: "htmlwidgets/lib/plotlyjs" - script: plotly-latest.min.js diff --git a/inst/plotlyjs.R b/inst/plotlyjs.R index c784098879..31817fdbf5 100644 --- a/inst/plotlyjs.R +++ b/inst/plotlyjs.R @@ -8,6 +8,8 @@ p <- Sys.glob("plotly-plotly.js*/dist/plotly.min.js") file.copy(p, "inst/htmlwidgets/lib/plotlyjs/plotly-latest.min.js", overwrite = T) l <- Sys.glob("plotly-plotly.js*/LICENSE") file.copy(l, "inst/htmlwidgets/lib/plotlyjs/LICENSE", overwrite = T) +l <- Sys.glob("plotly-plotly.js*/package.json") +file.copy(l, "inst/htmlwidgets/lib/plotlyjs/package.json", overwrite = T) unlink("plotly-plotly.js*", recursive = T) # update plotly.yml with version basename(zip) diff --git a/man/config.Rd b/man/config.Rd index fd1785f8ca..d7fe141340 100644 --- a/man/config.Rd +++ b/man/config.Rd @@ -8,7 +8,7 @@ config(p = last_plot(), staticPlot = F, workspace = F, editable = F, autosizable = F, fillFrame = F, scrollZoom = F, doubleClick = "reset+autosize", showTips = F, showLink = T, sendData = T, linkText = "Edit chart", displayModeBar = "hover", - displaylogo = T, plot3dPixelRatio = 2) + displaylogo = T, plot3dPixelRatio = 2, mathjax = FALSE) } \arguments{ \item{p}{a plotly object} @@ -40,6 +40,13 @@ config(p = last_plot(), staticPlot = F, workspace = F, editable = F, \item{displaylogo}{add the plotly logo on the end of the modebar} \item{plot3dPixelRatio}{increase the pixel ratio for 3D plot images} + +\item{mathjax}{If \code{FALSE}, don't attempt to include mathjax. +If \code{'cdn'}, mathjax will be loaded externally (meaning an internet +connection is needed to view the graph). If \code{'local'}, a local copy +of mathjax will be included. For this to work, you'll need a local copy of +plotly.js and set the environment variable plotly_jsdir to its location on +your machine.} } \description{ Set the default configuration for plotly diff --git a/vignettes/intro.Rmd b/vignettes/intro.Rmd index 3400f16af0..823005c278 100644 --- a/vignettes/intro.Rmd +++ b/vignettes/intro.Rmd @@ -36,7 +36,7 @@ You can manually add a trace to an existing plot with `add_trace()`. In that cas ```{r} m <- loess(unemploy / pop ~ as.numeric(date), data = economics) p <- plot_ly(economics, x = date, y = unemploy / pop, name = "raw") -add_trace(p, y = fitted(m), name = "loess") +add_trace(p, x = date, y = fitted(m), name = "loess") ``` __plotly__ was designed with a [pure, predictable, and pipeable interface](https://dl.dropboxusercontent.com/u/41902/pipe-dsls.pdf) in mind, so you can also use the `%>%` operator to create a visualization pipeline: @@ -44,7 +44,7 @@ __plotly__ was designed with a [pure, predictable, and pipeable interface](https ```{r} economics %>% plot_ly(x = date, y = unemploy / pop) %>% - add_trace(y = fitted(m)) %>% + add_trace(x = date, y = fitted(m)) %>% layout(showlegend = F) ```