├── .Rbuildignore ├── .bowerrc ├── .gitignore ├── .travis.yml ├── CONDUCT.md ├── DESCRIPTION ├── LICENSE ├── NAMESPACE ├── NEWS.md ├── R ├── annotate.r ├── axis.r ├── bar.r ├── hist.r ├── labs.r ├── legend.r ├── line.r ├── metricsgraphics-package.R ├── metricsgraphics.R ├── mjs_grid.R ├── mouseover.r ├── point.r ├── region.r └── rules.r ├── README.Rmd ├── README.html ├── README.md ├── cran-comments.md ├── gridtest.Rmd ├── gridtest.html ├── inst ├── doc │ ├── introductiontometricsgraphics.R │ ├── introductiontometricsgraphics.Rmd │ └── introductiontometricsgraphics.html └── htmlwidgets │ ├── lib │ ├── d3 │ │ ├── .bower.json │ │ ├── CONTRIBUTING.md │ │ ├── LICENSE │ │ ├── README.md │ │ ├── bower.json │ │ ├── d3.js │ │ ├── d3.min.js │ │ └── package.js │ ├── jquery │ │ ├── .bower.json │ │ ├── MIT-LICENSE.txt │ │ ├── bower.json │ │ ├── dist │ │ │ ├── jquery.js │ │ │ ├── jquery.min.js │ │ │ └── jquery.min.map │ │ └── src │ │ │ ├── ajax.js │ │ │ ├── ajax │ │ │ ├── jsonp.js │ │ │ ├── load.js │ │ │ ├── parseJSON.js │ │ │ ├── parseXML.js │ │ │ ├── script.js │ │ │ ├── var │ │ │ │ ├── nonce.js │ │ │ │ └── rquery.js │ │ │ └── xhr.js │ │ │ ├── attributes.js │ │ │ ├── attributes │ │ │ ├── attr.js │ │ │ ├── classes.js │ │ │ ├── prop.js │ │ │ ├── support.js │ │ │ └── val.js │ │ │ ├── callbacks.js │ │ │ ├── core.js │ │ │ ├── core │ │ │ ├── access.js │ │ │ ├── init.js │ │ │ ├── parseHTML.js │ │ │ ├── ready.js │ │ │ └── var │ │ │ │ └── rsingleTag.js │ │ │ ├── css.js │ │ │ ├── css │ │ │ ├── addGetHookIf.js │ │ │ ├── curCSS.js │ │ │ ├── defaultDisplay.js │ │ │ ├── hiddenVisibleSelectors.js │ │ │ ├── support.js │ │ │ ├── swap.js │ │ │ └── var │ │ │ │ ├── cssExpand.js │ │ │ │ ├── getStyles.js │ │ │ │ ├── isHidden.js │ │ │ │ ├── rmargin.js │ │ │ │ └── rnumnonpx.js │ │ │ ├── data.js │ │ │ ├── data │ │ │ ├── Data.js │ │ │ ├── accepts.js │ │ │ └── var │ │ │ │ ├── data_priv.js │ │ │ │ └── data_user.js │ │ │ ├── deferred.js │ │ │ ├── deprecated.js │ │ │ ├── dimensions.js │ │ │ ├── effects.js │ │ │ ├── effects │ │ │ ├── Tween.js │ │ │ └── animatedSelector.js │ │ │ ├── event.js │ │ │ ├── event │ │ │ ├── ajax.js │ │ │ ├── alias.js │ │ │ └── support.js │ │ │ ├── exports │ │ │ ├── amd.js │ │ │ └── global.js │ │ │ ├── intro.js │ │ │ ├── jquery.js │ │ │ ├── manipulation.js │ │ │ ├── manipulation │ │ │ ├── _evalUrl.js │ │ │ ├── support.js │ │ │ └── var │ │ │ │ └── rcheckableType.js │ │ │ ├── offset.js │ │ │ ├── outro.js │ │ │ ├── queue.js │ │ │ ├── queue │ │ │ └── delay.js │ │ │ ├── selector-native.js │ │ │ ├── selector-sizzle.js │ │ │ ├── selector.js │ │ │ ├── serialize.js │ │ │ ├── sizzle │ │ │ └── dist │ │ │ │ ├── sizzle.js │ │ │ │ ├── sizzle.min.js │ │ │ │ └── sizzle.min.map │ │ │ ├── traversing.js │ │ │ ├── traversing │ │ │ ├── findFilter.js │ │ │ └── var │ │ │ │ └── rneedsContext.js │ │ │ ├── var │ │ │ ├── arr.js │ │ │ ├── class2type.js │ │ │ ├── concat.js │ │ │ ├── hasOwn.js │ │ │ ├── indexOf.js │ │ │ ├── pnum.js │ │ │ ├── push.js │ │ │ ├── rnotwhite.js │ │ │ ├── slice.js │ │ │ ├── strundefined.js │ │ │ ├── support.js │ │ │ └── toString.js │ │ │ └── wrap.js │ └── metrics-graphics │ │ ├── .bower.json │ │ ├── HOOKS.md │ │ ├── LICENSE │ │ ├── README.md │ │ ├── bower.json │ │ └── dist │ │ ├── metricsgraphics.css │ │ ├── metricsgraphics.js │ │ ├── metricsgraphics.min.js │ │ ├── mg_regions.css │ │ └── mg_regions.js │ ├── metricsgraphics.js │ └── metricsgraphics.yaml ├── man ├── metricsgraphics-exports.Rd ├── metricsgraphics.Rd ├── metricsgraphicsOutput.Rd ├── mjs_add_baseline.Rd ├── mjs_add_confidence_band.Rd ├── mjs_add_css_rule.Rd ├── mjs_add_legend.Rd ├── mjs_add_line.Rd ├── mjs_add_marker.Rd ├── mjs_add_mouseover.Rd ├── mjs_annotate_region.Rd ├── mjs_axis_x.Rd ├── mjs_axis_y.Rd ├── mjs_bar.Rd ├── mjs_grid.Rd ├── mjs_hist.Rd ├── mjs_histogram.Rd ├── mjs_labs.Rd ├── mjs_line.Rd ├── mjs_plot.Rd ├── mjs_point.Rd └── renderMetricsgraphics.Rd ├── metricsgraphics.Rproj ├── paper.bib ├── paper.md ├── tests ├── test-all.R └── testthat │ ├── shiny.R │ ├── test-metricsgraphics.R │ ├── test.R │ ├── test.Rmd │ └── test.html └── vignettes └── introductiontometricsgraphics.Rmd /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^.*\.Rproj$ 2 | ^\.Rproj\.user$ 3 | ^\.travis\.yml$ 4 | ^.*md$ 5 | \.bower\.json 6 | \.bowerrc 7 | ^gridtest.* 8 | ^CONDUCT\.md$ 9 | ^README\.html$ 10 | ^cran-comments\.md$ 11 | ^paper\.md$ 12 | ^paper\.bib$ -------------------------------------------------------------------------------- /.bowerrc: -------------------------------------------------------------------------------- 1 | {"directory": "inst/htmlwidgets/lib"} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .Rproj.user 2 | .Rhistory 3 | .RData 4 | .Rproj 5 | src/*.o 6 | src/*.so 7 | src/*.dll 8 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | sudo: required 3 | 4 | before_install: 5 | - curl -OL http://raw.github.com/craigcitro/r-travis/master/scripts/travis-tool.sh 6 | - chmod 755 ./travis-tool.sh 7 | - ./travis-tool.sh bootstrap 8 | 9 | install: 10 | - ./travis-tool.sh install_deps 11 | 12 | script: ./travis-tool.sh run_tests 13 | 14 | on_failure: 15 | - ./travis-tool.sh dump_logs 16 | 17 | branches: 18 | except: 19 | - /-expt$/ 20 | notifications: 21 | email: 22 | on_success: change 23 | on_failure: change 24 | -------------------------------------------------------------------------------- /CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Code of Conduct 2 | 3 | As contributors and maintainers of this project, we pledge to respect all people who 4 | contribute through reporting issues, posting feature requests, updating documentation, 5 | submitting pull requests or patches, and other activities. 6 | 7 | We are committed to making participation in this project a harassment-free experience for 8 | everyone, regardless of level of experience, gender, gender identity and expression, 9 | sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion. 10 | 11 | Examples of unacceptable behavior by participants include the use of sexual language or 12 | imagery, derogatory comments or personal attacks, trolling, public or private harassment, 13 | insults, or other unprofessional conduct. 14 | 15 | Project maintainers have the right and responsibility to remove, edit, or reject comments, 16 | commits, code, wiki edits, issues, and other contributions that are not aligned to this 17 | Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed 18 | from the project team. 19 | 20 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by 21 | opening an issue or contacting one or more of the project maintainers. 22 | 23 | This Code of Conduct is adapted from the Contributor Covenant 24 | (http:contributor-covenant.org), version 1.0.0, available at 25 | http://contributor-covenant.org/version/1/0/0/ 26 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: metricsgraphics 2 | Type: Package 3 | Title: Create Interactive Charts with the JavaScript 'MetricsGraphics' Library 4 | Version: 0.9.1 5 | Date: 2016-04-24 6 | Authors@R: c( 7 | person("Bob", "Rudis", email = "bob@rudis.net", role = c("aut", "cre")), 8 | person("Ali", "Almossawi", role = c("ctb", "cph"), comment = "MetricsGraphics library"), 9 | person("Hamilton", "Ulmer", role = c("ctb", "cph"), comment = "MetricsGraphics library"), 10 | person("Mozilla", role = c("cph"), comment = "MetricsGraphics library"), 11 | person("jQuery Foundation and contributors", role = c("ctb", "cph"), comment = "jQuery library") 12 | ) 13 | Maintainer: Bob Rudis 14 | Description: Provides an 'htmlwidgets' interface to the 15 | 'MetricsGraphics.js' ('D3'-based) charting library which is geared towards 16 | displaying time-series data. Chart types include line charts, scatterplots, 17 | histograms and rudimentary bar charts. Support for laying out mutiple charts 18 | into a grid layout is also provided. All charts are interactive and many 19 | have an option for line, label and region annotations. 20 | URL: http://github.com/hrbrmstr/metricsgraphics 21 | BugReports: https://github.com/hrbrmstr/metricsgraphics/issues 22 | License: MIT + file LICENSE 23 | Suggests: 24 | testthat, 25 | RColorBrewer, 26 | ggplot2, 27 | ggplot2movies, 28 | jsonlite (>= 0.9.16), 29 | knitr (>= 1.8), 30 | shiny (>= 0.12.0), 31 | binom, 32 | dplyr, 33 | grDevices 34 | Depends: 35 | R (>= 3.0.0) 36 | Imports: 37 | magrittr, 38 | htmlwidgets, 39 | htmltools 40 | VignetteBuilder: knitr 41 | RoxygenNote: 5.0.1 42 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | YEAR: 2015 2 | COPYRIGHT HOLDER: Bob Rudis 3 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | export("%>%") 4 | export(JS) 5 | export(metricsgraphicsOutput) 6 | export(mjs_add_baseline) 7 | export(mjs_add_confidence_band) 8 | export(mjs_add_css_rule) 9 | export(mjs_add_legend) 10 | export(mjs_add_line) 11 | export(mjs_add_marker) 12 | export(mjs_add_mouseover) 13 | export(mjs_annotate_region) 14 | export(mjs_axis_x) 15 | export(mjs_axis_y) 16 | export(mjs_bar) 17 | export(mjs_grid) 18 | export(mjs_hist) 19 | export(mjs_histogram) 20 | export(mjs_labs) 21 | export(mjs_line) 22 | export(mjs_plot) 23 | export(mjs_point) 24 | export(renderMetricsgraphics) 25 | export(saveWidget) 26 | import(htmltools) 27 | importFrom(grDevices,n2mfrow) 28 | importFrom(htmlwidgets,JS) 29 | importFrom(htmlwidgets,saveWidget) 30 | importFrom(magrittr,"%>%") 31 | -------------------------------------------------------------------------------- /NEWS.md: -------------------------------------------------------------------------------- 1 | # metricsgraphics 0.9.0 2 | 3 | * updated all JS libs to latest versions (including the core Metrics Graphics library) 4 | * Incorporated the `mg-region` region annotation addon (use with `mjs_annotate_region`). 5 | * Borrowed the ability to add custom CSS rules to a chart (via `mjs_add_css_rule`) from [taucharts](http://github.com/hrbrmstr/taucharts). 6 | * Also added the ability to individually color lines without resorting to CSS (a new feature in the underlying JS lib). 7 | * Along with bare or quoted inputs, you can also now make the column names variables. 8 | * The vignette has also been updated to show more examples. 9 | * Examples that depended upon the `ggplot2::movies` data set work with the new ggplot2 which has separated out `movies` into `ggplot2movies::movies` 10 | 11 | # metricsgraphics 0.8.5 12 | 13 | * enhanced & changed some of the package functions to match MG's new javascript interface. 14 | * Added `mjs_add_confidence_band`. 15 | * Added package vignette. 16 | 17 | # metricsgraphics 0.8.0 18 | 19 | * updated `mjs_rollover` to show scatterplot example 20 | * cleaned up some of the base code & package layout for an attempt at a CRAN release. 21 | * updated MetricsGraphics.js to latest release version (2.5) 22 | 23 | # metricsgraphics 0.7.5 24 | 25 | * updated all functions that take bare inputs and made them flexible enough to take bare or quoted inputs. 26 | 27 | # metricsgraphics 0.7.0 28 | 29 | * Updated widget for MetricsGraphics 2.1.0 30 | * added `mjs_add_mouseover` and tweaked `mjs_bar`. NOTE: As the Mozilla folks said, the bar charts API is quite unstable. There won't be much effort to support them in this package until the API stabilizes a bit more. 31 | 32 | # metricsgraphics 0.6.1 33 | 34 | * Fixed bug that broke widget in new shiny/shinydashboard context 35 | 36 | # metricsgraphics 0.6.0 37 | 38 | * added `mjs_grid` for `grid.arrange`-like functionality for placing multiple charts 39 | 40 | # metricsgraphics 0.5.0 41 | 42 | added histograms (`mjs_histogram` & `mjs_hist`) -------------------------------------------------------------------------------- /R/annotate.r: -------------------------------------------------------------------------------- 1 | #' Add a confidence band to line plot 2 | #' 3 | #' If you have lower & upper points associated with your line in a data frame, 4 | #' you can specify their accessors (defaults to \code{"l"} & \code{"u"}) here 5 | #' which will result in a shaded confidence band being plotted with the line. 6 | #' 7 | #' @param mjs metricsgraphics plot object 8 | #' @param lower_accessor bare or quoted name of column to use for the lower 9 | #' bound of the confidence band 10 | #' @param upper_accessor bare or quoted name of column to use for the upper 11 | #' boudn of the confidence band 12 | #' @export 13 | #' @examples 14 | #' require(binom) 15 | #' require(dplyr) 16 | #' 17 | #' set.seed(1492) 18 | #' binom.confint(x=sample(2:30, 100, replace=TRUE), n = 100, tol = 1e-8, 19 | #' methods="bayes") %>% 20 | #' mutate(x=1:100) -> bdat 21 | #' 22 | #' bdat %>% 23 | #' mjs_plot(x=x, y=mean, width=600, height=240) %>% 24 | #' mjs_axis_x(show_secondary_x_label=FALSE, 25 | #' extended_ticks=TRUE) %>% 26 | #' mjs_line() %>% 27 | #' mjs_add_confidence_band(lower_accessor="lower", 28 | #' upper_accessor="upper") 29 | mjs_add_confidence_band <- function(mjs, lower_accessor="l", upper_accessor="u") { 30 | 31 | lower_accessor <- substitute(lower_accessor) 32 | if (inherits(lower_accessor, "name")) { 33 | lower_accessor <- as.character(lower_accessor) 34 | } 35 | 36 | upper_accessor <- substitute(upper_accessor) 37 | if (inherits(upper_accessor, "name")) { 38 | upper_accessor <- as.character(upper_accessor) 39 | } 40 | 41 | mjs$x$show_confidence_band = c(lower_accessor, upper_accessor) 42 | 43 | mjs 44 | 45 | } 46 | 47 | #' Sets a marker line/label 48 | #' 49 | #' metricsgraphics marker lines are vertical lines that identify, say, events or 50 | #' dates worth annotating. This function lets you add a marker to a plot object. 51 | #' you can add as many as you need to. 52 | #' 53 | #' @param mjs metricsgraphics plot object 54 | #' @param x_value which x value to draw the marker at 55 | #' @param label text label for the marker 56 | #' @return metricsgraphics object 57 | #' @export 58 | #' @examples 59 | #' data.frame( 60 | #' year=seq(1790, 1970, 10), 61 | #' uspop=as.numeric(uspop) 62 | #' ) %>% 63 | #' mjs_plot(x=year, y=uspop) %>% 64 | #' mjs_line() %>% 65 | #' mjs_add_marker(1850, "Something Wonderful") %>% 66 | #' mjs_add_baseline(150, "Something Awful") 67 | mjs_add_marker <- function(mjs, 68 | x_value, label) { 69 | 70 | if (class(x_value) == "Date") x_value <- format(x_value, "%Y-%m-%d") 71 | 72 | markers <- mjs$x$markers 73 | if (is.null(markers)) markers <- list() 74 | new_marker <- list() 75 | new_marker[[as.character(mjs$x$x_accessor)]] <- x_value 76 | new_marker[["label"]] <- label 77 | markers[[length(markers)+1]] <- new_marker 78 | mjs$x$markers <- markers 79 | 80 | mjs 81 | 82 | } 83 | 84 | #' Sets a baseline line/label 85 | #' 86 | #' metricsgraphics baselines are horizontal lines that may specify, say, a goal 87 | #' or target to be reached. This function lets you add baselines to a plot object. 88 | #' you can add as many as you need to. 89 | #' 90 | #' @param mjs metricsgraphics plot object 91 | #' @param y_value which y value to draw the baseline at 92 | #' @param label text label for the marker 93 | #' @return metricsgraphics object 94 | #' @export 95 | #' @examples 96 | #' data.frame( 97 | #' year=seq(1790, 1970, 10), 98 | #' uspop=as.numeric(uspop) 99 | #' ) %>% 100 | #' mjs_plot(x=year, y=uspop) %>% 101 | #' mjs_line() %>% 102 | #' mjs_add_marker(1850, "Something Wonderful") %>% 103 | #' mjs_add_baseline(150, "Something Awful") 104 | mjs_add_baseline <- function(mjs, 105 | y_value, label) { 106 | baselines <- mjs$x$baselines 107 | if (is.null(baselines)) baselines <- list() 108 | new_baseline <- list() 109 | new_baseline[["value"]] <- y_value 110 | new_baseline[["label"]] <- label 111 | baselines[[length(baselines)+1]] <- new_baseline 112 | mjs$x$baselines <- baselines 113 | mjs 114 | } -------------------------------------------------------------------------------- /R/axis.r: -------------------------------------------------------------------------------- 1 | #' Configure x axis ticks & limits 2 | #' 3 | #' @param mjs metricsgraphics plot object 4 | #' @param show display the axis? (default: \code{TRUE} - yes) 5 | #' @param xax_count tick count 6 | #' @param min_x min limit for x axis 7 | #' @param max_x max limit for x axis 8 | #' @param extended_ticks extend ticks on x axis? 9 | #' @param xax_format how to format tick labels. Currently one of "plain", "comma" 10 | #' or "date" 11 | #' @param show_secondary_x_label determines whether to show the year, or another 12 | #' unit of time in the case of smaller series, on the x-axis below 13 | #' the x-axis labels. 14 | #' @param rug show a "rug" plot next to the x axis? (default: \code{FALSE} - no) 15 | #' @note xax_format is likely to undergo a drastic change in future releases but 16 | #' support for these three formats will also likely remain. 17 | #' @export 18 | mjs_axis_x <- function(mjs, 19 | show=TRUE, 20 | xax_count=6, 21 | min_x=NULL, max_x=NULL, 22 | extended_ticks=FALSE, 23 | xax_format="plain", 24 | show_secondary_x_label=NULL, 25 | rug=FALSE) { 26 | 27 | if (!xax_format %in% c("plain", "comma", "date")) { 28 | stop("'xax_format' must be either 'plain', 'comma' or 'date'") 29 | } 30 | 31 | mjs$x$x_axis <- show 32 | mjs$x$xax_count <- xax_count 33 | mjs$x$min_x <- min_x 34 | mjs$x$max_x <- max_x 35 | mjs$x$x_extended_ticks <- extended_ticks 36 | mjs$x$show_secondary_x_label <- show_secondary_x_label 37 | mjs$x$xax_format <- xax_format 38 | mjs$x$x_rug <- rug 39 | 40 | if (xax_format == "date") { 41 | 42 | if (mjs$x$orig_posix) { 43 | 44 | mjs$x$data[,as.character(mjs$x$x_accessor)] <- 45 | format(as.POSIXct(mjs$x$data[,as.character(mjs$x$x_accessor)], 46 | origin="1970-01-01 00:00:00"), 47 | "%Y-%m-%dT%H:%M:%SZ") 48 | 49 | } else { 50 | mjs$x$data[,as.character(mjs$x$x_accessor)] <- 51 | format(as.Date(mjs$x$data[,as.character(mjs$x$x_accessor)], 52 | origin='1970-01-01'), "%Y-%m-%d") 53 | } 54 | } 55 | 56 | mjs 57 | } 58 | 59 | #' Configure y axis ticks & limits 60 | #' 61 | #' @param mjs metricsgraphics plot object 62 | #' @param show display the axis? (default: \code{TRUE} - yes) 63 | #' @param yax_count tick count 64 | #' @param min_y min limit for y axis 65 | #' @param max_y max limit for y axis 66 | #' @param extended_ticks extend ticks on y axis? 67 | #' @param y_scale_type scale for y axis; either "linear" (default) or "log" 68 | #' @param yax_units a prefix symbol to be shown alongside the y axis' labels. 69 | #' Useful for currencies, for instance. 70 | #' @param rug show a "rug" plot next to the y axis? (default: \code{FALSE} - no) 71 | #' @return metricsgraphics object 72 | #' @export 73 | mjs_axis_y <- function(mjs, 74 | show=TRUE, 75 | yax_count=5, 76 | min_y=NULL, max_y=NULL, 77 | extended_ticks=FALSE, 78 | y_scale_type="linear", 79 | yax_units="", 80 | rug=FALSE) { 81 | 82 | if (!y_scale_type %in% c("linear", "log")) { 83 | stop("'y_scale_type' must be either 'linear' or 'log'") 84 | } 85 | 86 | mjs$x$y_axis <- show 87 | mjs$x$yax_count <- yax_count 88 | mjs$x$min_y <- min_y 89 | mjs$x$max_y <- max_y 90 | mjs$x$y_extended_ticks <- extended_ticks 91 | mjs$x$y_scale_type <- y_scale_type 92 | mjs$x$yax_units <- "" 93 | mjs$x$y_rug <- rug 94 | mjs 95 | } -------------------------------------------------------------------------------- /R/bar.r: -------------------------------------------------------------------------------- 1 | #' metricsgraphics.js bar chart "geom" 2 | #' 3 | #' This function adds a bar "geom" to a metricsgraphics.js html widget. 4 | #' 5 | #' @param mjs metricsgraphics plot object 6 | #' @param bar_height width of bars 7 | #' @param binned is data already binned? (default: \code{TRUE} - yes) 8 | #' @return metricsgraphics object 9 | #' @note metricsgraphics.js currently has "meh" support for bar charts 10 | #' @export 11 | #' @examples 12 | #' data.frame(year=seq(1790, 1970, 10), 13 | #' uspop=as.numeric(uspop)) %>% 14 | #' mjs_plot(x=year, y=uspop, width=300, height=400) %>% 15 | #' mjs_bar() 16 | #' 17 | mjs_bar <- function(mjs, 18 | bar_height=20, binned=TRUE) { 19 | mjs$x$data[, mjs$x$y_accessor] <- as.character(mjs$x$data[, mjs$x$y_accessor]) 20 | mjs$x$chart_type <- "bar" 21 | mjs$x$bar_height <- bar_height 22 | mjs$x$binned <- binned 23 | mjs$x$geom <- "bar" 24 | mjs 25 | } 26 | -------------------------------------------------------------------------------- /R/hist.r: -------------------------------------------------------------------------------- 1 | 2 | #' Plot Histograms with MetrisGraphics 3 | #' 4 | #' Given a numeric vector or a data frame and numeric column name (bare or quoted), 5 | #' plot a histogram with the specified parameter. This function automatically a y 6 | #' axis label "Frequency" which you can override with a call to 7 | #' \code{mjs_labs}. 8 | #' 9 | #' @param mjs metricsgraphics plot object 10 | #' @param bar_margin space between bars (defaults to \code{1}) 11 | #' @param bins numbenr of bins for the histogram (\code{NULL} == let MetricsGraphcis.js library compute) 12 | #' @return metricsgraphics plot object 13 | #' @export 14 | #' @examples 15 | #' movies <- ggplot2movies::movies[sample(nrow(ggplot2movies::movies), 1000), ] 16 | #' 17 | #' mjs_plot(movies$rating) %>% mjs_histogram() 18 | #' 19 | #' mjs_plot(movies, rating) %>% 20 | #' mjs_histogram() %>% 21 | #' mjs_labs(x_label="Histogram of movie ratings") 22 | #' 23 | #' mjs_plot(movies$rating) %>% 24 | #' mjs_histogram(bins=30) 25 | #' 26 | #' mjs_plot(runif(10000)) %>% 27 | #' mjs_histogram() %>% 28 | #' mjs_labs(x_label="runif(10000)") 29 | mjs_histogram <- function(mjs, bar_margin=1, bins=NULL) { 30 | 31 | mjs$x$chart_type <- "histogram" 32 | mjs$x$bar_margin <- bar_margin 33 | mjs$x$binned <- FALSE 34 | mjs$x$bins <- bins 35 | mjs$x$y_label <- "Frequency" 36 | mjs$x$geom <- "hist" 37 | 38 | x <- as.character(mjs$x$x_accessor) 39 | 40 | if (mjs$x$binned == FALSE) { 41 | if (x != "") { 42 | mjs$x$data <- as.numeric(mjs$x$data[,x]) 43 | } else { 44 | mjs$x$data <- as.numeric(mjs$x$data) 45 | } 46 | } 47 | 48 | mjs 49 | 50 | } 51 | 52 | #' Shortcut for plotting MetricsGraphics histograms 53 | #' 54 | #' This function performs the call to \code{mjs_plot} and assumes 55 | #' \code{data} is a numeric vector. It's intended to save keystrokes 56 | #' when plotting quick histograms. This function automatically a y 57 | #' axis label "Frequency" which you can override with a call to 58 | #' \code{mjs_labs}. 59 | #' 60 | #' @param data numeric vector 61 | #' @param bins number of bins for the histogram (\code{NULL} == let MetricsGraphcis.js library compute) 62 | #' @param bar_margin space between bars (defaults to \code{1}) 63 | #' @return metricsgraphics object 64 | #' @export 65 | #' @examples 66 | #' bimod <- c(rnorm(1000, 0, 1), rnorm(1000, 3, 1)) 67 | #' 68 | #' mjs_plot(bimod) %>% mjs_histogram() 69 | #' bimod %>% mjs_hist() 70 | #' 71 | #' mjs_plot(bimod) %>% mjs_histogram(bins=30) 72 | #' bimod %>% mjs_hist(30) 73 | mjs_hist <- function(data, bins=NULL, bar_margin=1) { 74 | mjs_plot(data) %>% 75 | mjs_histogram(bins=bins, bar_margin=bar_margin) %>% 76 | mjs_labs(y_label="Frequency") 77 | } 78 | -------------------------------------------------------------------------------- /R/labs.r: -------------------------------------------------------------------------------- 1 | #' Configure axis labels & plot description 2 | #' 3 | #' @param mjs metricsgraphics object 4 | #' @param x_label label for x asis 5 | #' @param y_label label for y axis 6 | #' @export 7 | #' @return metricsgraphics object 8 | #' @examples 9 | #' mtcars %>% 10 | #' mjs_plot(x=wt, y=mpg, width=400, height=300) %>% 11 | #' mjs_point(color_accessor=carb, size_accessor=carb) %>% 12 | #' mjs_labs(x="Weight of Car", y="Miles per Gallon") 13 | #' 14 | mjs_labs <- function(mjs, 15 | x_label=NULL, y_label=NULL) { 16 | mjs$x$x_label <- x_label 17 | mjs$x$y_label <- y_label 18 | mjs 19 | } 20 | -------------------------------------------------------------------------------- /R/legend.r: -------------------------------------------------------------------------------- 1 | #' Adds a legend to a metricsgraphics chart 2 | #' 3 | #' @param mjs metricsgraphics plot object 4 | #' @param legend character vector of labels for the legend 5 | #' @param inline \code{TRUE} if you want line labes to the right of the chart 6 | #' vs in a legend block (experimental) 7 | #' @export 8 | #' @return metricsgraphics object 9 | #' @examples 10 | #' set.seed(1492) 11 | #' stocks <- data.frame( 12 | #' time = as.Date('2009-01-01') + 0:9, 13 | #' X = rnorm(10, 0, 1), 14 | #' Y = rnorm(10, 0, 2), 15 | #' Z = rnorm(10, 0, 4)) 16 | #' 17 | #' stocks %>% 18 | #' mjs_plot(x=time, y=X) %>% 19 | #' mjs_line() %>% 20 | #' mjs_add_line(Y) %>% 21 | #' mjs_add_line(Z) %>% 22 | #' mjs_axis_x(xax_format="date") %>% 23 | #' mjs_add_legend(legend=c("X", "Y", "Z")) 24 | mjs_add_legend <- function(mjs, legend, inline=FALSE) { 25 | mjs$x$legend <- legend 26 | if (!inline) mjs$x$legend_target <- sprintf("#%s-legend", mjs$elementId) 27 | mjs 28 | } 29 | -------------------------------------------------------------------------------- /R/line.r: -------------------------------------------------------------------------------- 1 | #' metricsgraphics.js linechart "geom" 2 | #' 3 | #' This function adds a line "geom" to a metricsgraphics.js html widget. 4 | #' 5 | #' @param mjs metricsgraphics plot object 6 | #' @param area fill in area under line? (default: \code{FALSE} - no) 7 | #' @param animate_on_load animate the drawing of the plot on page load? (default: \code{FALSE} - no) 8 | #' @param color line color (hex string or valid HTML color string). Use \code{NULL} (the default) 9 | #' to use the default Metrics Graphics colors or if you plan on controlling the colors with CSS. 10 | #' @param interpolate the interpolation function to use when rendering lines. 11 | #' possible values: ("cardinal", "linear", "linear-closed", "step", "step-before", 12 | #' "step-after", "basis", "basis-open", "basis-closed", "bundle", "cardinal-open", 13 | #' "cardinal-closed", "monotone", "basic") 14 | #' @return metricsgraphics object 15 | #' @note If you plan on using cusom colors, all lines must have a color value or the result is 16 | #' non-deterministic. 17 | #' @export 18 | #' @examples 19 | #' data.frame(year=seq(1790, 1970, 10), 20 | #' uspop=as.numeric(uspop)) %>% 21 | #' mjs_plot(x=year, y=uspop) %>% 22 | #' mjs_line() 23 | #' 24 | mjs_line <- function(mjs, 25 | area=FALSE, animate_on_load=FALSE, 26 | color=NULL, 27 | interpolate="cardinal") { 28 | 29 | if(!interpolate %in% c("cardinal", "linear", "linear-closed", "step", 30 | "step-before", "step-after", "basis", "basis-open", 31 | "basis-closed", "bundle", "cardinal-open", 32 | "cardinal-closed", "monotone", "basic")) { 33 | stop("'interpolate' must be a valid value") 34 | } 35 | 36 | 37 | mjs$x$area <- area 38 | mjs$x$animate_on_load <- animate_on_load 39 | mjs$x$geom <- "line" 40 | mjs$x$color <- color 41 | mjs$x$colors <- color 42 | mjs$x$interpolate <- interpolate 43 | mjs 44 | } 45 | 46 | #' Add a new line to a metricsgraphics.js linechart "geom" 47 | #' 48 | #' This function adds a line to an existing \code{mjs_line} "geom". Specify 49 | #' the bare or quoted name of the column to use in \code{y_accessor} and it will be added 50 | #' to the plot. 51 | #' 52 | #' @note You must have called \code{mjs_line} first before adding additional columns. If you plan on 53 | #' using cusom colors, all lines must have a color value or the result is non-deterministic. 54 | #' @param mjs metricsgraphics plot object 55 | #' @param y_accessor bare or quoted name of column to add to the existing line plot 56 | #' @param color line color. Use \code{NULL} (the default) to use default Metrics Graphics colors 57 | #' or if you plan on using CSS to control the colors. 58 | #' @return metricsgraphics object 59 | #' @export 60 | #' @examples 61 | #' set.seed(1492) 62 | #' stocks <- data.frame( 63 | #' time = as.Date('2009-01-01') + 0:9, 64 | #' X = rnorm(10, 0, 1), 65 | #' Y = rnorm(10, 0, 2), 66 | #' Z = rnorm(10, 0, 4)) 67 | #' 68 | #' stocks %>% 69 | #' mjs_plot(x=time, y=X) %>% 70 | #' mjs_line() %>% 71 | #' mjs_add_line(Y) %>% 72 | #' mjs_add_line(Z) %>% 73 | #' mjs_axis_x(xax_format="date") 74 | mjs_add_line <- function(mjs, y_accessor, color=NULL) { 75 | 76 | y_accessor <- substitute(y_accessor) 77 | if (inherits(y_accessor, "name")) { y_accessor <- as.character(y_accessor) } 78 | 79 | multi_line <- mjs$x$multi_line 80 | if (is.null(multi_line)) multi_line <- list() 81 | new_line <- y_accessor 82 | multi_line <- c(multi_line, new_line) 83 | mjs$x$multi_line <- multi_line 84 | mjs$x$color <- NULL 85 | if (!is.null(color)) { mjs$x$colors <- c(mjs$x$colors, color) } 86 | mjs 87 | 88 | } 89 | -------------------------------------------------------------------------------- /R/metricsgraphics-package.R: -------------------------------------------------------------------------------- 1 | #' An \code{htmlwidget} interface to the 2 | #' \href{http://metricsgraphicsjs.org/}{MetricsGraphics.js} D3 chart library 3 | #' @name metricsgraphics 4 | #' @docType package 5 | #' @author Bob Rudis (@@hrbrmstr) 6 | #' @import htmltools 7 | NULL 8 | 9 | #' metricsgraphics exported operators 10 | #' 11 | #' The following functions are imported and then re-exported 12 | #' from the dygraphs package to enable use of the magrittr 13 | #' pipe operator with no additional library calls 14 | #' 15 | #' @name metricsgraphics-exports 16 | NULL 17 | 18 | #' @importFrom magrittr %>% 19 | #' @name %>% 20 | #' @export 21 | #' @rdname metricsgraphics-exports 22 | NULL 23 | 24 | #' @importFrom htmlwidgets JS 25 | #' @name JS 26 | #' @export 27 | #' @rdname metricsgraphics-exports 28 | NULL 29 | 30 | #' @importFrom htmlwidgets saveWidget 31 | #' @name saveWidget 32 | #' @export 33 | #' @rdname metricsgraphics-exports 34 | NULL 35 | -------------------------------------------------------------------------------- /R/mjs_grid.R: -------------------------------------------------------------------------------- 1 | #' Lays out metricsgraphics widgets into a "grid", similar to 2 | #' \code{grid.arrange} from \code{gridExtra} 3 | #' 4 | #' @param ... either individual \code{metricsgraphics} objects or a mixture of 5 | #' individual \code{metricsgraphics} objects 6 | #' and \code{list}s of \code{metricsgrahics} objects. 7 | #' @param ncol how many columns in the grid 8 | #' @param nrow how many rows in the grid 9 | #' @param widths widths of the cells per row 10 | #' @return \code{htmltools} tag with wrapped \code{metricsgraphics} objects suitable 11 | #' for knitting with \code{echo=FALSE} & \code{results="asis"} or 12 | #' rendering in Viewer with \code{html_print} 13 | #' @note \code{mjs_grid} does not work in a Shiny context 14 | #' @importFrom grDevices n2mfrow 15 | #' @export 16 | mjs_grid <- function(..., ncol=1, nrow=1, widths=1) { 17 | 18 | input_list <- as.list(substitute(list(...)))[-1L] 19 | 20 | params <- list() 21 | 22 | for (i in 1:length(input_list)) { 23 | x <- eval.parent(input_list[[i]]) 24 | if (any(class(x) == "list")) { 25 | for (j in 1:length(x)) { 26 | y <- eval(x[[j]]) 27 | params[[length(params)+1]] <- y 28 | } 29 | } else { 30 | params[[length(params)+1]] <- x 31 | } 32 | } 33 | 34 | if(!all(sapply(params, function(x) { 35 | inherits(x, c("metricsgraphics", "htmlwidget")) 36 | }))) { 37 | stop("All parameters must be metricsgraphics objects") 38 | } 39 | 40 | if (ncol == 1 & nrow == 1) { 41 | nm <- n2mfrow(length(params)) 42 | nrow <- nm[1] 43 | ncol <- nm[2] 44 | } 45 | 46 | if (length(widths) < ncol) widths <- rep(1/ncol, ncol) 47 | 48 | if (length(input_list) > ncol*nrow) { 49 | stop("Number of metricsgraphics objects > available grid slots") 50 | } 51 | 52 | max_width <- "100%" 53 | 54 | GRID <- TABLE(lapply(seq(1, nrow*ncol, ncol), function(idx){ 55 | TR(width="100%", style="width:100%", lapply(seq(idx, idx+ncol-1, 1), function(cell) { 56 | 57 | cell_val <- try(eval(params[[cell]]), silent=TRUE) 58 | if (!inherits(cell_val, c("metricsgraphics", "htmlwidget"))) { 59 | cell_val <- HTML("   ") 60 | } 61 | 62 | TD(style=sprintf("width:%3.2f%%", 100*widths[cell-idx+1]), 63 | width=sprintf("%3.2f%%", 100*widths[cell-idx+1]), 64 | cell_val) 65 | })) 66 | }), style=sprintf("width:%s", max_width), width=max_width) 67 | 68 | return(GRID) 69 | 70 | } 71 | 72 | TABLE <- tags$table <- function(...) tag("table", list(...)) 73 | TR <- tags$tr <- function(...) tag("tr", list(...)) 74 | TD <- tags$td <- function(...) tag("td", list(...)) 75 | -------------------------------------------------------------------------------- /R/mouseover.r: -------------------------------------------------------------------------------- 1 | #' Adds a custom rollover to a metricsgraphics chart 2 | #' 3 | #' MetricsGraphics charts allow for \href{https://github.com/mozilla/metrics-graphics/wiki/Graphic#mouseover}{custom rollovers}. 4 | #' \code{mjs_add_mouseover} lets you add a custom rollover to a metricsgraphics object. You must be 5 | #' familiar with javascript and D3 idioms since you are supplying a javascript function as 6 | #' a parameter.\cr 7 | #' \cr 8 | #' Since targeting is done by element id, you will need to add a special string - \code{\{\{ID\}\}} - 9 | #' to the target element selector so metricsgraphics can add the unique object identifier 10 | #' to the selector. See Examples for basic usage. 11 | #' 12 | #' @param mjs metricsgraphics plot object 13 | #' @param func text for javascript function to be used for the custom rollover. See Details for usage. 14 | #' @export 15 | #' @return metricsgraphics object 16 | #' @note you need to use \code{d.point.THING} vs \code{d.THING} when trying to add mouseovers to a 17 | #' metricsgraphics scatterplot. 18 | #' @export 19 | #' @examples 20 | #' set.seed(1492) 21 | #' dat <- data.frame(date=as.Date('2009-01-01') + 0:9, 22 | #' value=rnorm(10, 0, 2)) 23 | #' dat %>% 24 | #' mjs_plot(x=date, y=value) %>% 25 | #' mjs_line() %>% 26 | #' mjs_axis_x(xax_format = "date") %>% 27 | #' mjs_add_mouseover("function(d, i) { 28 | #' $('{{ID}} svg .mg-active-datapoint') 29 | #' .text('custom text : ' + d.date + ' ' + i); 30 | #' }") 31 | #' 32 | #' # slightly different for scatterplots 33 | #' 34 | #' dat <- data.frame(value=rnorm(n=30, mean=5, sd=1), 35 | #' value2=rnorm(n=30, mean=4, sd=1), 36 | #' test = c(rep(c('test', 'test2'), 15))) 37 | #' 38 | #' dat %>% 39 | #' mjs_plot(x = value, y = value2) %>% 40 | #' mjs_point() %>% 41 | #' mjs_add_mouseover("function(d, i) { 42 | #' $('{{ID}} svg .mg-active-datapoint') 43 | #' .text('custom text : ' + d.point.test + ' ' + i); 44 | #' }") 45 | #' 46 | mjs_add_mouseover <- function(mjs, func) { 47 | mjs$x$mouseover <- JS(gsub("\\{\\{ID\\}\\}", sprintf("%s", mjs$x$target), func)) 48 | mjs 49 | } 50 | -------------------------------------------------------------------------------- /R/point.r: -------------------------------------------------------------------------------- 1 | #' metricsgraphics.js scatterplot "geom" 2 | #' 3 | #' This function adds a point/scatterplot "geom" to a metricsgraphics.js html widget. 4 | #' 5 | #' @param mjs metricsgraphics plot object 6 | #' @param point_size the radius of the dots in the scatterplot 7 | #' @param least_squares add a least squares line? (default: \code{FALSE} - no) 8 | #' @param size_accessor bare or quoted name of a column to use to scale the size of the points 9 | #' @param color_accessor bare or quoted name of a column to use to scale the color of the points 10 | #' @param color_type specifies whether the color scale is quantitative or qualitative. 11 | #' By setting this option to "\code{category}", you can color the points according to some 12 | #' other discrete value 13 | #' @param size_range specifies the range of point sizes, when point sizes are mapped to data 14 | #' @param x_rug show a "rug" plot next to the x axis? (default: \code{FALSE} - no) 15 | #' @param y_rug show a "rug" plot next to the y axis? (default: \code{FALSE} - no) 16 | #' @param color_range the range of colors, used to color different groups of points. 17 | #' @return metricsgraphics object 18 | #' @export 19 | #' @examples 20 | #' mtcars %>% 21 | #' mjs_plot(x=wt, y=mpg, width=400, height=300) %>% 22 | #' mjs_point(least_squares=TRUE) 23 | #' 24 | mjs_point <- function(mjs, 25 | point_size=2.5, 26 | least_squares=FALSE, 27 | size_accessor=NULL, 28 | color_accessor=NULL, 29 | color_type="number", 30 | color_range=c('blue', 'red'), 31 | size_range=c(1, 5), 32 | x_rug=FALSE, 33 | y_rug=FALSE) { 34 | 35 | if (!color_type %in% c("category", "number")) { 36 | stop("'color_type' must be either 'category' or 'number'") 37 | } 38 | 39 | mjs$x$chart_type <- "point" 40 | mjs$x$point_size <- point_size 41 | mjs$x$least_squares<- least_squares 42 | mjs$x$x_rug <- x_rug 43 | mjs$x$y_rug <- y_rug 44 | if (class(substitute(size_accessor)) != "NULL") { 45 | size_accessor <- substitute(size_accessor) 46 | if (inherits(size_accessor, "name")) { size_accessor <- as.character(size_accessor) } 47 | mjs$x$size_accessor <- size_accessor 48 | } 49 | if (class(substitute(color_accessor)) != "NULL") { 50 | color_accessor <- substitute(color_accessor) 51 | if (inherits(color_accessor, "name")) { color_accessor <- as.character(color_accessor) } 52 | mjs$x$color_accessor <- color_accessor 53 | } 54 | mjs$x$color_type <- color_type 55 | mjs$x$color_range <- color_range 56 | mjs$x$size_range <- size_range 57 | mjs$x$geom <- "point" 58 | mjs 59 | } 60 | -------------------------------------------------------------------------------- /R/region.r: -------------------------------------------------------------------------------- 1 | #' Region annotations for line charts [EXPERIMENTAL] 2 | #' 3 | #' This function uses the \href{https://github.com/senseyeio/mg-regions}{mg-regions} 4 | #' plugin to enable region highlighting with an optional label. 5 | #' 6 | #' This function is also experimental and relies on the plugin maintainer to 7 | #' continue support for it. You should be well-versed in CSS to use this function 8 | #' properly. 9 | #' 10 | #' @param mjs metricsgraphics object 11 | #' @param x_start start point on x axis for region annotation 12 | #' @param x_end end point on x axis for region annotation 13 | #' @param label text label for annotation (leave \code{NULL}) for no label 14 | #' @param css_class CSS class to apply (see References link for more information) 15 | #' @export 16 | #' @return metricsgraphics object 17 | #' @references \url{https://github.com/senseyeio/mg-regions} 18 | #' @examples 19 | #' data.frame(year=seq(1790, 1970, 10), 20 | #' uspop=as.numeric(uspop)) %>% 21 | #' mjs_plot(x=year, y=uspop, title="Population Chart") %>% 22 | #' mjs_line() %>% 23 | #' mjs_annotate_region(1850, 1900, "Bad stuff") %>% 24 | #' mjs_annotate_region(1810, 1830, "Stuff") 25 | #' 26 | #' set.seed(1492) 27 | #' stocks <- data.frame( 28 | #' time = as.Date('2009-01-01') + (365 * 0:9), 29 | #' X = rnorm(10, 0, 1), 30 | #' Y = rnorm(10, 0, 2), 31 | #' Z = rnorm(10, 0, 4)) 32 | #' 33 | #' stocks %>% 34 | #' mjs_plot(x=time, y=X) %>% 35 | #' mjs_line() %>% 36 | #' mjs_axis_x(xax_format="date") %>% 37 | #' mjs_annotate_region("2013-01-01", "2016-01-01", "Crazy times") 38 | #' 39 | #' ## custom region color 40 | #' stocks %>% 41 | #' mjs_plot(x=time, y=X) %>% 42 | #' mjs_line() %>% 43 | #' mjs_axis_x(xax_format="date") %>% 44 | #' mjs_add_css_rule("{{ID}} .blk { fill:black }") %>% 45 | #' mjs_annotate_region("2013-01-01", "2016-01-01", "Crazy times", "blk") 46 | mjs_annotate_region <- function(mjs, x_start=NULL, x_end=NULL, 47 | label=NULL, css_class=NULL) { 48 | 49 | reg <- list(c(x_start, x_end), label, css_class) 50 | names(reg) <- c(mjs$x$x_accessor, "label", "class") 51 | mjs$x$regions[[length(mjs$x$regions)+1]] <- reg 52 | mjs 53 | 54 | } 55 | -------------------------------------------------------------------------------- /R/rules.r: -------------------------------------------------------------------------------- 1 | #' Add a CSS rule to the rendered htmlwidget 2 | #' 3 | #' This function will add a CSS rule to a widget-created 4 | #' DOM stylesheet. \code{rule} should be a valid CSS rule as you 5 | #' would enter in a \code{} block. No checking is done 6 | #' to ensure validity. 7 | #' 8 | #' Use \code{\{\{ID\}\}} (followed by a space) to target the CSS rule 9 | #' just to the widget vs the whole DOM. 10 | #' 11 | #' Vectorized over \code{rule} 12 | #' 13 | #' @param mjs metricsgraphics plot object 14 | #' @param rule character vector of CSS rule(s) to add to the widget DOM 15 | #' @param warn show warnings for global CSS rules? (default: \code{TRUE}) 16 | #' @return metricsgraphics plot object 17 | #' @note This is for expert use only. You need to know quite a bit about the visualization 18 | #' and target DOM to effectively use this function. CSS rules without the \code{\{\{ID\}\}} 19 | #' are applied to the entire DOM. 20 | #' @export 21 | #' @examples 22 | #' set.seed(1492) 23 | #' stocks <- data.frame( 24 | #' time = as.Date('2009-01-01') + (365 * 0:9), 25 | #' X = rnorm(10, 0, 1), 26 | #' Y = rnorm(10, 0, 2), 27 | #' Z = rnorm(10, 0, 4)) 28 | #' 29 | #' stocks %>% 30 | #' mjs_plot(x=time, y=X) %>% 31 | #' mjs_line() %>% 32 | #' mjs_axis_x(xax_format="date") %>% 33 | #' mjs_add_css_rule("{{ID}} .blk { fill:black }") %>% 34 | #' mjs_annotate_region("2013-01-01", "2016-01-01", "Crazy times", "blk") 35 | mjs_add_css_rule <- function(mjs, rule, warn=TRUE) { 36 | 37 | # if any of the CSS statements in 'rule' do not have {{ID}} targets, warn the user 38 | if (warn) { 39 | if (!any(grepl("\\{\\{ID\\}\\}", rule))) { 40 | message("NOTE: CSS rules without {{ID}} are applied to the entire DOM.") 41 | } 42 | } 43 | mjs$x$forCSS <- c(mjs$x$forCSS, rule) 44 | mjs 45 | } 46 | -------------------------------------------------------------------------------- /cran-comments.md: -------------------------------------------------------------------------------- 1 | ## Why the need for an update? 2 | * 0.8.5 used ggplot2::movies which is now ggplot2movies::movies 3 | * Updated to latest javascript libraries 4 | * Added a region annotation plugin 5 | * Added region annotations, support for custom CSS styles and custom line colors 6 | 7 | ## Test environments 8 | * local OS X install (devel & release) 9 | * ubuntu 12.04 (on travis-ci), R 3.2.3 10 | * win-builder (devel and release) 11 | 12 | ## R CMD check results 13 | There were no ERRORs or WARNINGs or NOTEs. 14 | 15 | -------------------------------------------------------------------------------- /gridtest.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "mjs_grid" 3 | author: '@hrbrmstr' 4 | date: "February 1, 2015" 5 | output: 6 | html_document: 7 | toc: false 8 | --- 9 | 10 | ```{r echo=FALSE} 11 | suppressPackageStartupMessages(library(metricsgraphics)) 12 | suppressPackageStartupMessages(library(htmltools)) 13 | suppressPackageStartupMessages(library(dplyr)) 14 | ``` 15 | 16 | ```{r eval=FALSE} 17 | library(metricsgraphics) 18 | library(htmltools) 19 | library(dplyr) 20 | ``` 21 | 22 | ```{r} 23 | plots <- lapply(1:7, function(x) { 24 | mjs_plot(rnorm(10000, mean=x/2, sd=x), width="300px", height="300px", linked=TRUE) %>% 25 | mjs_histogram(bar_margin=2) %>% 26 | mjs_labs(x_label=sprintf("Plot %d", x)) 27 | }) 28 | 29 | moar_plots <- lapply(1:7, function(x) { 30 | mjs_plot(rbeta(10000, x, x), width="300px", height="300px", linked=TRUE) %>% 31 | mjs_histogram(bar_margin=2) %>% 32 | mjs_labs(x_label=sprintf("Plot %d", x)) 33 | }) 34 | ``` 35 | 36 | ```{r eval=FALSE} 37 | mjs_grid(plots) 38 | ``` 39 | 40 | ```{r echo=FALSE, results="asis"} 41 | mjs_grid(plots) 42 | ``` 43 | 44 | ```{r eval=FALSE} 45 | mjs_grid(moar_plots, nrow=4, ncol=3, widths=c(rep(0.33, 3))) 46 | ``` 47 | 48 | ```{r echo=FALSE, results="asis"} 49 | mjs_grid(moar_plots, nrow=4, ncol=3, widths=c(rep(0.33, 3))) 50 | ``` 51 | 52 | ```{r} 53 | tips <- reshape2::tips 54 | a <- tips %>% 55 | mutate(percent=tip/total_bill, 56 | day=factor(day, levels=c("Thur", "Fri", "Sat", "Sun"), ordered=TRUE)) %>% 57 | group_by(sex, day) %>% 58 | do( plot={ x_label <- sprintf("Total Bill (%s)", unique(.$sex)) 59 | y_label <- sprintf("Tip %% (%s)", unique(.$day)) 60 | mjs_plot(., x=total_bill, y=percent, width="250px", height="250px", left=100) %>% 61 | mjs_point() %>% 62 | mjs_labs(x_label=x_label, y_label=y_label) }) 63 | ``` 64 | 65 | ```{r eval=FALSE} 66 | mjs_grid(a$plot, ncol=4, nrow=2, widths=c(rep(0.5, 2))) 67 | ``` 68 | 69 | ```{r echo=FALSE, results="asis"} 70 | mjs_grid(a$plot, ncol=4, nrow=2, widths=c(rep(0.5, 2))) 71 | ``` 72 | 73 | ```{r} 74 | tips <- reshape2::tips 75 | a <- tips %>% 76 | mutate(percent=tip/total_bill, 77 | day=factor(day, levels=c("Thur", "Fri", "Sat", "Sun"), ordered=TRUE)) %>% 78 | group_by(day) %>% 79 | do( plot={ day_label <- unique(.$day) 80 | mjs_plot(., x=total_bill, y=percent, width="350px", height="350px", left=100) %>% 81 | mjs_point(color_accessor=sex, color_type="category") %>% 82 | mjs_labs(x_label=sprintf("Total Bill (%s)", day_label), y_label="Tip %") }) 83 | ``` 84 | 85 | ```{r eval=FALSE} 86 | mjs_grid(a$plot, ncol=2, nrow=2, widths=c(0.5, 0.5)) 87 | ``` 88 | 89 | ```{r echo=FALSE, results="asis"} 90 | mjs_grid(a$plot, ncol=2, nrow=2, widths=c(0.5, 0.5)) 91 | ``` 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /inst/htmlwidgets/lib/d3/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "d3", 3 | "version": "3.5.3", 4 | "main": "d3.js", 5 | "scripts": [ 6 | "d3.js" 7 | ], 8 | "ignore": [ 9 | ".DS_Store", 10 | ".git", 11 | ".gitignore", 12 | ".npmignore", 13 | ".spmignore", 14 | ".travis.yml", 15 | "Makefile", 16 | "bin", 17 | "component.json", 18 | "composer.json", 19 | "index.js", 20 | "lib", 21 | "node_modules", 22 | "package.json", 23 | "src", 24 | "test" 25 | ], 26 | "homepage": "https://github.com/mbostock/d3", 27 | "_release": "3.5.3", 28 | "_resolution": { 29 | "type": "version", 30 | "tag": "v3.5.3", 31 | "commit": "ac59002a6229317a684743f26c3b4b55fc25b569" 32 | }, 33 | "_source": "git://github.com/mbostock/d3.git", 34 | "_target": ">=3.4.8", 35 | "_originalSource": "d3" 36 | } -------------------------------------------------------------------------------- /inst/htmlwidgets/lib/d3/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | **Important:** these GitHub issues are for *bug reports and feature requests only*. Please use [StackOverflow](http://stackoverflow.com/questions/tagged/d3.js) or the [d3-js Google group](https://groups.google.com/d/forum/d3-js) for general help. 4 | 5 | If you’re looking for ways to contribute, please [peruse open issues](https://github.com/mbostock/d3/issues?milestone=&page=1&state=open). The icebox is a good place to find ideas that are not currently in development. If you already have an idea, please check past issues to see whether your idea or a similar one was previously discussed. 6 | 7 | Before submitting a pull request, consider implementing a live example first, say using [bl.ocks.org](http://bl.ocks.org). Real-world use cases go a long way to demonstrating the usefulness of a proposed feature. The more complex a feature’s implementation, the more usefulness it should provide. Share your demo using the #d3js tag on Twitter or by sending it to the [d3-js Google group](https://groups.google.com/d/forum/d3-js). 8 | 9 | If your proposed feature does not involve changing core functionality, consider submitting it instead as a [D3 plugin](https://github.com/d3/d3-plugins). New core features should be for general use, whereas plugins are suitable for more specialized use cases. When in doubt, it’s easier to start with a plugin before “graduating” to core. 10 | 11 | To contribute new documentation or add examples to the gallery, just [edit the Wiki](https://github.com/mbostock/d3/wiki)! 12 | 13 | ## How to Submit a Pull Request 14 | 15 | 1. Click the “Fork” button to create your personal fork of the D3 repository. 16 | 17 | 2. After cloning your fork of the D3 repository in the terminal, run `npm install` to install D3’s dependencies. 18 | 19 | 3. Create a new branch for your new feature. For example: `git checkout -b my-awesome-feature`. A dedicated branch for your pull request means you can develop multiple features at the same time, and ensures that your pull request is stable even if you later decide to develop an unrelated feature. 20 | 21 | 4. The `d3.js` and `d3.min.js` files are built from source files in the `src` directory. _Do not edit `d3.js` directly._ Instead, edit the source files, and then run `make` to build the generated files. 22 | 23 | 5. Use `make test` to run tests and verify your changes. If you are adding a new feature, you should add new tests! If you are changing existing functionality, make sure the existing tests run, or update them as appropriate. 24 | 25 | 6. Sign D3’s [Individual Contributor License Agreement](https://docs.google.com/forms/d/1CzjdBKtDuA8WeuFJinadx956xLQ4Xriv7-oDvXnZMaI/viewform). Unless you are submitting a trivial patch (such as fixing a typo), this form is needed to verify that you are able to contribute. 26 | 27 | 7. Submit your pull request, and good luck! 28 | -------------------------------------------------------------------------------- /inst/htmlwidgets/lib/d3/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010-2015, Michael Bostock 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * The name Michael Bostock may not be used to endorse or promote products 15 | derived from this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | DISCLAIMED. IN NO EVENT SHALL MICHAEL BOSTOCK BE LIABLE FOR ANY DIRECT, 21 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 22 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 24 | OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 25 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 26 | EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | -------------------------------------------------------------------------------- /inst/htmlwidgets/lib/d3/README.md: -------------------------------------------------------------------------------- 1 | # Data-Driven Documents 2 | 3 | 4 | 5 | **D3.js** is a JavaScript library for manipulating documents based on data. **D3** helps you bring data to life using HTML, SVG, and CSS. **D3** emphasizes web standards and combines powerful visualization components with a data-driven approach to DOM manipulation, giving you the full capabilities of modern browsers without tying yourself to a proprietary framework. 6 | 7 | Want to learn more? [See the wiki.](https://github.com/mbostock/d3/wiki) 8 | 9 | For examples, [see the gallery](https://github.com/mbostock/d3/wiki/Gallery) and [mbostock’s bl.ocks](http://bl.ocks.org/mbostock). 10 | -------------------------------------------------------------------------------- /inst/htmlwidgets/lib/d3/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "d3", 3 | "main": "d3.js", 4 | "scripts": [ 5 | "d3.js" 6 | ], 7 | "ignore": [ 8 | ".DS_Store", 9 | ".git", 10 | ".gitignore", 11 | ".npmignore", 12 | ".spmignore", 13 | ".travis.yml", 14 | "Makefile", 15 | "bin", 16 | "component.json", 17 | "composer.json", 18 | "index.js", 19 | "lib", 20 | "node_modules", 21 | "package.json", 22 | "src", 23 | "test" 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /inst/htmlwidgets/lib/d3/package.js: -------------------------------------------------------------------------------- 1 | // Package metadata for Meteor.js. 2 | 3 | Package.describe({ 4 | name: "d3js:d3", // http://atmospherejs.com/d3js/d3 5 | summary: "D3 (official): A JavaScript visualization library for HTML and SVG.", 6 | version: "3.5.12", 7 | git: "https://github.com/mbostock/d3.git" 8 | }); 9 | 10 | Package.onUse(function(api) { 11 | api.versionsFrom(["METEOR@1.0"]); 12 | api.addFiles("d3.js", "client"); 13 | }); 14 | -------------------------------------------------------------------------------- /inst/htmlwidgets/lib/jquery/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery", 3 | "version": "2.1.3", 4 | "main": "dist/jquery.js", 5 | "license": "MIT", 6 | "ignore": [ 7 | "**/.*", 8 | "build", 9 | "speed", 10 | "test", 11 | "*.md", 12 | "AUTHORS.txt", 13 | "Gruntfile.js", 14 | "package.json" 15 | ], 16 | "devDependencies": { 17 | "sizzle": "2.1.1-jquery.2.1.2", 18 | "requirejs": "2.1.10", 19 | "qunit": "1.14.0", 20 | "sinon": "1.8.1" 21 | }, 22 | "keywords": [ 23 | "jquery", 24 | "javascript", 25 | "library" 26 | ], 27 | "homepage": "https://github.com/jquery/jquery", 28 | "_release": "2.1.3", 29 | "_resolution": { 30 | "type": "version", 31 | "tag": "2.1.3", 32 | "commit": "8f2a9d9272d6ed7f32d3a484740ab342c02541e0" 33 | }, 34 | "_source": "git://github.com/jquery/jquery.git", 35 | "_target": ">=1.11.1", 36 | "_originalSource": "jquery" 37 | } -------------------------------------------------------------------------------- /inst/htmlwidgets/lib/jquery/MIT-LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright 2014 jQuery Foundation and other contributors 2 | http://jquery.com/ 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining 5 | a copy of this software and associated documentation files (the 6 | "Software"), to deal in the Software without restriction, including 7 | without limitation the rights to use, copy, modify, merge, publish, 8 | distribute, sublicense, and/or sell copies of the Software, and to 9 | permit persons to whom the Software is furnished to do so, subject to 10 | the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /inst/htmlwidgets/lib/jquery/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery", 3 | "version": "2.1.4", 4 | "main": "dist/jquery.js", 5 | "license": "MIT", 6 | "ignore": [ 7 | "**/.*", 8 | "build", 9 | "dist/cdn", 10 | "speed", 11 | "test", 12 | "*.md", 13 | "AUTHORS.txt", 14 | "Gruntfile.js", 15 | "package.json" 16 | ], 17 | "devDependencies": { 18 | "sizzle": "2.1.1-jquery.2.1.2", 19 | "requirejs": "2.1.10", 20 | "qunit": "1.14.0", 21 | "sinon": "1.8.1" 22 | }, 23 | "keywords": [ 24 | "jquery", 25 | "javascript", 26 | "library" 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /inst/htmlwidgets/lib/jquery/src/ajax/jsonp.js: -------------------------------------------------------------------------------- 1 | define([ 2 | "../core", 3 | "./var/nonce", 4 | "./var/rquery", 5 | "../ajax" 6 | ], function( jQuery, nonce, rquery ) { 7 | 8 | var oldCallbacks = [], 9 | rjsonp = /(=)\?(?=&|$)|\?\?/; 10 | 11 | // Default jsonp settings 12 | jQuery.ajaxSetup({ 13 | jsonp: "callback", 14 | jsonpCallback: function() { 15 | var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) ); 16 | this[ callback ] = true; 17 | return callback; 18 | } 19 | }); 20 | 21 | // Detect, normalize options and install callbacks for jsonp requests 22 | jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) { 23 | 24 | var callbackName, overwritten, responseContainer, 25 | jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ? 26 | "url" : 27 | typeof s.data === "string" && !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") && rjsonp.test( s.data ) && "data" 28 | ); 29 | 30 | // Handle iff the expected data type is "jsonp" or we have a parameter to set 31 | if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) { 32 | 33 | // Get callback name, remembering preexisting value associated with it 34 | callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ? 35 | s.jsonpCallback() : 36 | s.jsonpCallback; 37 | 38 | // Insert callback into url or form data 39 | if ( jsonProp ) { 40 | s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName ); 41 | } else if ( s.jsonp !== false ) { 42 | s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName; 43 | } 44 | 45 | // Use data converter to retrieve json after script execution 46 | s.converters["script json"] = function() { 47 | if ( !responseContainer ) { 48 | jQuery.error( callbackName + " was not called" ); 49 | } 50 | return responseContainer[ 0 ]; 51 | }; 52 | 53 | // force json dataType 54 | s.dataTypes[ 0 ] = "json"; 55 | 56 | // Install callback 57 | overwritten = window[ callbackName ]; 58 | window[ callbackName ] = function() { 59 | responseContainer = arguments; 60 | }; 61 | 62 | // Clean-up function (fires after converters) 63 | jqXHR.always(function() { 64 | // Restore preexisting value 65 | window[ callbackName ] = overwritten; 66 | 67 | // Save back as free 68 | if ( s[ callbackName ] ) { 69 | // make sure that re-using the options doesn't screw things around 70 | s.jsonpCallback = originalSettings.jsonpCallback; 71 | 72 | // save the callback name for future use 73 | oldCallbacks.push( callbackName ); 74 | } 75 | 76 | // Call if it was a function and we have a response 77 | if ( responseContainer && jQuery.isFunction( overwritten ) ) { 78 | overwritten( responseContainer[ 0 ] ); 79 | } 80 | 81 | responseContainer = overwritten = undefined; 82 | }); 83 | 84 | // Delegate to script 85 | return "script"; 86 | } 87 | }); 88 | 89 | }); 90 | -------------------------------------------------------------------------------- /inst/htmlwidgets/lib/jquery/src/ajax/load.js: -------------------------------------------------------------------------------- 1 | define([ 2 | "../core", 3 | "../core/parseHTML", 4 | "../ajax", 5 | "../traversing", 6 | "../manipulation", 7 | "../selector", 8 | // Optional event/alias dependency 9 | "../event/alias" 10 | ], function( jQuery ) { 11 | 12 | // Keep a copy of the old load method 13 | var _load = jQuery.fn.load; 14 | 15 | /** 16 | * Load a url into a page 17 | */ 18 | jQuery.fn.load = function( url, params, callback ) { 19 | if ( typeof url !== "string" && _load ) { 20 | return _load.apply( this, arguments ); 21 | } 22 | 23 | var selector, type, response, 24 | self = this, 25 | off = url.indexOf(" "); 26 | 27 | if ( off >= 0 ) { 28 | selector = jQuery.trim( url.slice( off ) ); 29 | url = url.slice( 0, off ); 30 | } 31 | 32 | // If it's a function 33 | if ( jQuery.isFunction( params ) ) { 34 | 35 | // We assume that it's the callback 36 | callback = params; 37 | params = undefined; 38 | 39 | // Otherwise, build a param string 40 | } else if ( params && typeof params === "object" ) { 41 | type = "POST"; 42 | } 43 | 44 | // If we have elements to modify, make the request 45 | if ( self.length > 0 ) { 46 | jQuery.ajax({ 47 | url: url, 48 | 49 | // if "type" variable is undefined, then "GET" method will be used 50 | type: type, 51 | dataType: "html", 52 | data: params 53 | }).done(function( responseText ) { 54 | 55 | // Save response for use in complete callback 56 | response = arguments; 57 | 58 | self.html( selector ? 59 | 60 | // If a selector was specified, locate the right elements in a dummy div 61 | // Exclude scripts to avoid IE 'Permission Denied' errors 62 | jQuery("
").append( jQuery.parseHTML( responseText ) ).find( selector ) : 63 | 64 | // Otherwise use the full result 65 | responseText ); 66 | 67 | }).complete( callback && function( jqXHR, status ) { 68 | self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] ); 69 | }); 70 | } 71 | 72 | return this; 73 | }; 74 | 75 | }); 76 | -------------------------------------------------------------------------------- /inst/htmlwidgets/lib/jquery/src/ajax/parseJSON.js: -------------------------------------------------------------------------------- 1 | define([ 2 | "../core" 3 | ], function( jQuery ) { 4 | 5 | // Support: Android 2.3 6 | // Workaround failure to string-cast null input 7 | jQuery.parseJSON = function( data ) { 8 | return JSON.parse( data + "" ); 9 | }; 10 | 11 | return jQuery.parseJSON; 12 | 13 | }); 14 | -------------------------------------------------------------------------------- /inst/htmlwidgets/lib/jquery/src/ajax/parseXML.js: -------------------------------------------------------------------------------- 1 | define([ 2 | "../core" 3 | ], function( jQuery ) { 4 | 5 | // Cross-browser xml parsing 6 | jQuery.parseXML = function( data ) { 7 | var xml, tmp; 8 | if ( !data || typeof data !== "string" ) { 9 | return null; 10 | } 11 | 12 | // Support: IE9 13 | try { 14 | tmp = new DOMParser(); 15 | xml = tmp.parseFromString( data, "text/xml" ); 16 | } catch ( e ) { 17 | xml = undefined; 18 | } 19 | 20 | if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) { 21 | jQuery.error( "Invalid XML: " + data ); 22 | } 23 | return xml; 24 | }; 25 | 26 | return jQuery.parseXML; 27 | 28 | }); 29 | -------------------------------------------------------------------------------- /inst/htmlwidgets/lib/jquery/src/ajax/script.js: -------------------------------------------------------------------------------- 1 | define([ 2 | "../core", 3 | "../ajax" 4 | ], function( jQuery ) { 5 | 6 | // Install script dataType 7 | jQuery.ajaxSetup({ 8 | accepts: { 9 | script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript" 10 | }, 11 | contents: { 12 | script: /(?:java|ecma)script/ 13 | }, 14 | converters: { 15 | "text script": function( text ) { 16 | jQuery.globalEval( text ); 17 | return text; 18 | } 19 | } 20 | }); 21 | 22 | // Handle cache's special case and crossDomain 23 | jQuery.ajaxPrefilter( "script", function( s ) { 24 | if ( s.cache === undefined ) { 25 | s.cache = false; 26 | } 27 | if ( s.crossDomain ) { 28 | s.type = "GET"; 29 | } 30 | }); 31 | 32 | // Bind script tag hack transport 33 | jQuery.ajaxTransport( "script", function( s ) { 34 | // This transport only deals with cross domain requests 35 | if ( s.crossDomain ) { 36 | var script, callback; 37 | return { 38 | send: function( _, complete ) { 39 | script = jQuery("