Skip to content

Commit 458dfd9

Browse files
authored
Merge pull request #1178 from ropensci/v1.32.0
Bump plotly.js version
2 parents 6cc7370 + d0384b3 commit 458dfd9

18 files changed

+114
-179
lines changed

NEWS.md

+4-2
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,16 @@
22

33
## NEW FEATURES & IMPROVEMENTS
44

5+
* Upgraded to plotly.js v1.33.1. A _huge_ amount of features and improvements have been made since v1.29.2 (i.e., the version included in the last CRAN release of the R package - v4.7.1). Highlights include a complete re-write of `scattergl` to make it nearly feature complete with `scatter`, localization of text rendering (i.e., international translations), and two new trace types (`violin` & `table`). Read more about the v1.32.0 release [here](https://codeburst.io/notes-from-the-latest-plotly-js-release-b035a5b43e21) and the complete list of changes [here](https://github.com/plotly/plotly.js/releases).
6+
* The selection mode can now switch from 'transient' to 'persistent' by holding the 'shift' key. It's still possible to _force_ persistent selection by setting `persistent = TRUE` in `highlight()`, but `persistent = FALSE` (the default) is now recommended since it allows one to switch between [persistent/transient selection](https://plotly-book.cpsievert.me/linking-views-without-shiny.html#transient-versus-persistent-selection) in the browser, rather than at the command line.
7+
58
## CHANGES
69

710
* The `elementId` field is no longer populated, which fixes the "Ignoring explicitly provided widget ID" warning in shiny applications (see #985).
8-
* Upgraded to plotly.js v1.31.2 -- https://github.com/plotly/plotly.js/releases/tag/v1.31.2
911

1012
## BUG FIXES
1113

12-
Fixed algorithm for coercing the proposed layout to the plot schema (see #1156).
14+
* Fixed algorithm for coercing the proposed layout to the plot schema (see #1156).
1315

1416
# 4.7.1
1517

R/ggplotly.R

+7-5
Original file line numberDiff line numberDiff line change
@@ -46,18 +46,20 @@
4646
#' # linked scatterplot brushing
4747
#' library(crosstalk)
4848
#' d <- SharedData$new(mtcars)
49-
#' subplot(
50-
#' qplot(data = d, x = mpg, y = wt),
51-
#' qplot(data = d, x = mpg, y = vs)
52-
#' )
49+
#' qplot(data = d, x = mpg, y = wt) %>%
50+
#' subplot(qplot(data = d, x = mpg, y = vs)) %>%
51+
#' layout(title = "Click and drag to select points") %>%
52+
#' highlight("plotly_selected")
53+
#'
5354
#'
5455
#' # more brushing (i.e. highlighting) examples
5556
#' demo("crosstalk-highlight-ggplotly", package = "plotly")
5657
#'
5758
#' # client-side linked brushing in a scatterplot matrix
5859
#' SharedData$new(iris) %>%
5960
#' GGally::ggpairs(aes(colour = Species), columns = 1:4) %>%
60-
#' ggplotly(tooltip = c("x", "y", "colour"))
61+
#' ggplotly(tooltip = c("x", "y", "colour")) %>%
62+
#' highlight("plotly_selected")
6163
#' }
6264
#'
6365
ggplotly <- function(p = ggplot2::last_plot(), width = NULL, height = NULL,

R/highlight.R

+18-11
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,10 @@
2828
#' (i.e., clicking the home button in the modebar) or whenever the height/width
2929
#' of the plot changes.
3030
#' }
31-
#' @param persistent should selections persist (i.e., accumulate)?
31+
#' @param persistent should selections persist (i.e., accumulate)? We often
32+
#' refer to the default (`FALSE`) as a 'transient' selection mode;
33+
#' which is recommended, because one may switch from 'transient' to
34+
#' 'persistent' selection by holding the shift key.
3235
#' @param dynamic should a widget for changing selection colors be included?
3336
#' @param color character string of color(s) to use for
3437
#' highlighting selections. See [toRGB()] for valid color
@@ -41,6 +44,7 @@
4144
#' @param opacityDim a number between 0 and 1 used to reduce the
4245
#' opacity of non-selected traces (by multiplying with the existing opacity).
4346
#' @param selected attributes of the selection, see [attrs_selected()].
47+
#' @param unselected attributes of the non-selected marks, see [attrs_unselected()].
4448
#' @param ... currently not supported.
4549
#' @export
4650
#' @author Carson Sievert
@@ -56,13 +60,11 @@
5660
#' d <- SharedData$new(txhousing, ~city)
5761
#' p <- ggplot(d, aes(date, median, group = city)) + geom_line()
5862
#' gg <- ggplotly(p, tooltip = "city")
59-
#' highlight(gg, persistent = TRUE, dynamic = TRUE)
63+
#' highlight(gg, dynamic = TRUE)
6064
#'
6165
#' # supply custom colors to the brush
6266
#' cols <- toRGB(RColorBrewer::brewer.pal(3, "Dark2"), 0.5)
63-
#' highlight(
64-
#' gg, on = "plotly_hover", color = cols, persistent = TRUE, dynamic = TRUE
65-
#' )
67+
#' highlight(gg, on = "plotly_hover", color = cols, dynamic = TRUE)
6668
#'
6769
#' # Use attrs_selected() for complete control over the selection appearance
6870
#' # note any relevant colors you specify here should override the color argument
@@ -72,10 +74,7 @@
7274
#' marker = list(symbol = "x")
7375
#' )
7476
#'
75-
#' highlight(
76-
#' layout(gg, showlegend = TRUE),
77-
#' selected = s, persistent = TRUE
78-
#' )
77+
#' highlight(layout(gg, showlegend = TRUE), selected = s)
7978
#'
8079

8180
highlight <- function(p, on = "plotly_click", off,
@@ -102,12 +101,12 @@ highlight <- function(p, on = "plotly_click", off,
102101
stop("opacityDim must be between 0 and 1", call. = FALSE)
103102
}
104103
if (dynamic && length(color) < 2) {
105-
message("Adding more colors to the selection color palette")
104+
message("Adding more colors to the selection color palette.")
106105
color <- c(color, RColorBrewer::brewer.pal(4, "Set1"))
107106
}
108107
if (!dynamic && length(color) > 1) {
109108
warning(
110-
"Can only use a single color for selections when dynamic=FALSE",
109+
"Can only use a single color for selections when `dynamic = FALSE`.",
111110
call. = FALSE
112111
)
113112
color <- color[1]
@@ -137,6 +136,14 @@ highlight <- function(p, on = "plotly_click", off,
137136
off <- default(off_default %||% "plotly_relayout")
138137
}
139138

139+
if (isTRUE(persistent)) {
140+
message(
141+
"We recommend setting `persistent` to `FALSE` (the default) because ",
142+
"persistent selection mode can now be used by holding the shift key ",
143+
"(while triggering the `on` event)."
144+
)
145+
}
146+
140147
# main (non-plotly.js) spec passed along to HTMLwidgets.renderValue()
141148
p$x$highlight <- list(
142149
# NULL may be used to disable on/off events

R/plotly.R

+1-1
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,7 @@ typedArrayPolyfill <- function() {
373373
# and bundle size at print time.
374374
plotlyMainBundle <- function() {
375375
htmltools::htmlDependency(
376-
"plotlyjs", "1.31.2.9000",
376+
"plotlyjs", "1.33.1",
377377
src = depPath("plotlyjs"),
378378
script = "plotly-latest.min.js",
379379
stylesheet = "plotly-htmlwidgets.css"

R/sysdata.rda

4.64 KB
Binary file not shown.

R/utils.R

-6
Original file line numberDiff line numberDiff line change
@@ -267,12 +267,6 @@ supply_defaults <- function(p) {
267267
supply_highlight_attrs <- function(p) {
268268
# set "global" options via crosstalk variable
269269
p$x$highlight <- p$x$highlight %||% highlight_defaults()
270-
p <- htmlwidgets::onRender(
271-
p, sprintf(
272-
"function(el, x) { var ctConfig = crosstalk.var('plotlyCrosstalkOpts').set(%s); }",
273-
to_JSON(p$x$highlight)
274-
)
275-
)
276270

277271
# defaults are now populated, allowing us to populate some other
278272
# attributes such as the selectize widget definition

demo/crosstalk-highlight-binned-target-a.R

+14-5
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,24 @@ library(crosstalk)
33
library(plotly)
44

55
d <- SharedData$new(mpg)
6-
dots <- plot_ly(d, color = ~class, x = ~displ, y = ~cyl)
7-
boxs <- plot_ly(d, color = ~class, x = ~class, y = ~cty) %>% add_boxplot()
8-
bars <- plot_ly(d, x = ~class, color = ~class)
6+
dots <- plot_ly(d, colors = "Set1", color = ~class, x = ~displ, y = ~cyl) %>%
7+
layout(
8+
xaxis = list(title = "Engine displacement"),
9+
yaxis = list(title = "Number of cylinders")
10+
)
11+
boxs <- plot_ly(d, colors = "Set1", color = ~class, x = ~class, y = ~cty) %>%
12+
add_boxplot() %>%
13+
layout(
14+
xaxis = list(title = ""),
15+
yaxis = list(title = "Miles per gallon (city)")
16+
)
17+
bars <- plot_ly(d, colors = "Set1", x = ~class, color = ~class)
918

1019
subplot(dots, boxs, titleX = TRUE, titleY = TRUE) %>%
1120
subplot(bars, nrows = 2, titleX = TRUE, titleY = TRUE) %>%
1221
layout(
13-
title = "Click and drag on scatterplot",
22+
title = "Dynamic 2-way ANOVA (clik & drag on scatterplot)",
1423
barmode = "overlay",
1524
showlegend = FALSE
1625
) %>%
17-
highlight("plotly_selected")
26+
highlight("plotly_selected", opacityDim = 0.6)

demo/crosstalk-highlight-binned-target-c.R

+1-4
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,4 @@ p2 <- plot_ly(tx, x = ~median, color = I("black")) %>%
1010

1111
subplot(gg1, p2, titleX = TRUE, titleY = TRUE) %>%
1212
layout(barmode = "overlay") %>%
13-
highlight(
14-
dynamic = TRUE, persistent = TRUE,
15-
selected = attrs_selected(opacity = 0.3)
16-
)
13+
highlight(dynamic = TRUE, selected = attrs_selected(opacity = 0.3))

demo/crosstalk-highlight-epl-2.R

-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ gg <- ggplotly(p, width = 1050, height = 600, tooltip = "team")
3737

3838
highlight(
3939
gg,
40-
persistent = TRUE,
4140
dynamic = TRUE,
4241
selectize = TRUE,
4342
color = RColorBrewer::brewer.pal(12, "Paired")

demo/crosstalk-highlight-ggplotly.R

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ d <- SharedData$new(txhousing, ~city, "Select a city")
66
p <- ggplot(d, aes(date, median, group = city)) + geom_line()
77
ggplotly(p, tooltip = "city") %>%
88
layout(title = "Click on a line to highlight a year") %>%
9-
highlight(dynamic = TRUE, selectize = TRUE, persistent = TRUE)
9+
highlight(dynamic = TRUE, selectize = TRUE)
1010

1111
# crosstalk keys are automatically added to the group aesthetic...
1212
# if you want to avoid adding the key to group for a layer,

demo/crosstalk-highlight-intro.R

+5-5
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,9 @@ p %>%
4646

4747
# By default, all selections are transient, meaning prior selections are
4848
# removed from the selection set before new selections are added. To prevent
49-
# prior selections from being removed, simply set the persistent argument to
50-
# `TRUE`.
51-
highlight(p, on = "plotly_hover", persistent = TRUE)
49+
# prior selections from being removed, hold down the shift key while triggering
50+
# the event
51+
highlight(p, on = "plotly_hover")
5252

5353
# Sometimes its useful to compare two or more different selection sets.
5454
# For example, how do patients with a high response on visit 1 compare to those
@@ -57,10 +57,10 @@ highlight(p, on = "plotly_hover", persistent = TRUE)
5757
# a colourpicker htmlwidget (@colourpicker) will appear just above the plotly
5858
# visualization. At any given time, the value of this widget controls the
5959
# color of new selection(s).
60-
highlight(p, on = "plotly_hover", persistent = TRUE, dynamic = TRUE)
60+
highlight(p, on = "plotly_hover", dynamic = TRUE)
6161

6262
# By default, the colourpicker widget uses colors from the "Set1"
6363
# colour brewer palette (@RColorBrewer), but any set of valid R colors can
6464
# be supplied to the color argument.
6565
colors <- RColorBrewer::brewer.pal(4, "Dark2")
66-
highlight(p, on = "plotly_hover", color = colors, dynamic = TRUE, persistent = TRUE)
66+
highlight(p, on = "plotly_hover", color = colors, dynamic = TRUE)

demo/crosstalk-highlight-leaflet.R

+1-3
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@ library(crosstalk)
55
library(htmltools)
66

77
# leaflet should respect these "global" highlight() options
8-
options(
9-
opacityDim = 1, persistent = TRUE
10-
)
8+
options(opacityDim = 0.5)
119

1210
sd <- SharedData$new(quakes)
1311

demo/crosstalk-highlight-pipeline.R

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,4 @@ p2 <- base %>%
2424
subplot(p1, p2, titleX = TRUE, widths = c(0.3, 0.7)) %>%
2525
layout(margin = list(l = 120)) %>%
2626
hide_legend() %>%
27-
highlight(dynamic = TRUE, persistent = TRUE, selectize = TRUE)
27+
highlight(dynamic = TRUE, selectize = TRUE)

inst/htmlwidgets/lib/plotlyjs/plotly-latest.min.js

+3-76
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

inst/htmlwidgets/plotly.js

+41-43
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,36 @@ HTMLWidgets.widget({
1616
},
1717

1818
renderValue: function(el, x, instance) {
19+
20+
/*
21+
/ 'inform the world' about highlighting options this is so other
22+
/ crosstalk libraries have a chance to respond to special settings
23+
/ such as persistent selection.
24+
/ AFAIK, leaflet is the only library with such intergration
25+
/ https://github.com/rstudio/leaflet/pull/346/files#diff-ad0c2d51ce5fdf8c90c7395b102f4265R154
26+
*/
27+
var ctConfig = crosstalk.var('plotlyCrosstalkOpts').set(x.highlight);
1928

2029
if (typeof(window) !== "undefined") {
2130
// make sure plots don't get created outside the network (for on-prem)
2231
window.PLOTLYENV = window.PLOTLYENV || {};
2332
window.PLOTLYENV.BASE_URL = x.base_url;
33+
34+
// Enable persistent selection when shift key is down
35+
// https://stackoverflow.com/questions/1828613/check-if-a-key-is-down
36+
var persistOnShift = function(e) {
37+
if (!e) window.event;
38+
if (e.shiftKey) {
39+
x.highlight.persistent = true;
40+
} else {
41+
x.highlight.persistent = false;
42+
}
43+
};
44+
45+
// Only relevant if we haven't forced persistent mode at command line
46+
if (!x.highlight.persistent) {
47+
window.onmousemove = persistOnShift;
48+
}
2449
}
2550

2651
var graphDiv = document.getElementById(el.id);
@@ -431,15 +456,7 @@ HTMLWidgets.widget({
431456
}
432457
});
433458
}
434-
435-
436-
437-
438-
439-
440-
441-
442-
}
459+
} // end of selectionChange
443460

444461
} // end of renderValue
445462
}); // end of widget definition
@@ -551,9 +568,6 @@ TraceManager.prototype.updateSelection = function(group, keys) {
551568
var selectionColour = crosstalk.group(group).var("plotlySelectionColour").get() ||
552569
this.highlight.color[0];
553570

554-
// selection brush attributes
555-
var selectAttrs = Object.keys(this.highlight.selected);
556-
557571
for (var i = 0; i < this.origData.length; i++) {
558572
// TODO: try using Lib.extendFlat() as done in
559573
// https://github.com/plotly/plotly.js/pull/1136
@@ -570,50 +584,31 @@ TraceManager.prototype.updateSelection = function(group, keys) {
570584
if (!trace._isSimpleKey) {
571585
trace = subsetArrayAttrs(trace, matches);
572586
}
573-
// Apply selection brush attributes (supplied from R)
574-
// TODO: it would be neat to have a dropdown to dynamically specify these
575-
for (var j = 0; j < selectAttrs.length; j++) {
576-
var attr = selectAttrs[j];
577-
trace[attr] = this.highlight.selected[attr];
578-
}
587+
// reach into the full trace object so we can properly reflect the
588+
// selection attributes in every view
589+
var d = this.gd._fullData[i];
590+
591+
/*
592+
/ Recursively inherit selection attributes from various sources,
593+
/ in order of preference:
594+
/ (1) official plotly.js selected attribute
595+
/ (2) highlight(selected = attrs_selected(...))
596+
*/
597+
// TODO: it would be neat to have a dropdown to dynamically specify these!
598+
$.extend(true, trace, this.highlight.selected, d.selected);
579599

580600
// if it is defined, override color with the "dynamic brush color""
581-
// TODO: DRY this up
582-
var d = this.gd._fullData[i];
583601
if (d.marker) {
584602
trace.marker = trace.marker || {};
585603
trace.marker.color = selectionColour || trace.marker.color || d.marker.color;
586-
587-
// adopt any user-defined styling for the selection
588-
var selected = this.highlight.selected.marker || {};
589-
var attrs = Object.keys(selected);
590-
for (var j = 0; j < attrs.length; j++) {
591-
trace.marker[attrs[j]] = selected[attrs[j]];
592-
}
593604
}
594-
595605
if (d.line) {
596606
trace.line = trace.line || {};
597607
trace.line.color = selectionColour || trace.line.color || d.line.color;
598-
599-
// adopt any user-defined styling for the selection
600-
var selected = this.highlight.selected.line || {};
601-
var attrs = Object.keys(selected);
602-
for (var j = 0; j < attrs.length; j++) {
603-
trace.line[attrs[j]] = selected[attrs[j]];
604-
}
605608
}
606-
607609
if (d.textfont) {
608610
trace.textfont = trace.textfont || {};
609611
trace.textfont.color = selectionColour || trace.textfont.color || d.textfont.color;
610-
611-
// adopt any user-defined styling for the selection
612-
var selected = this.highlight.selected.textfont || {};
613-
var attrs = Object.keys(selected);
614-
for (var j = 0; j < attrs.length; j++) {
615-
trace.textfont[attrs[j]] = selected[attrs[j]];
616-
}
617612
}
618613
// attach a sensible name/legendgroup
619614
trace.name = trace.name || keys.join("<br />");
@@ -712,6 +707,9 @@ TraceManager.prototype.updateSelection = function(group, keys) {
712707

713708
if (tracesToDim.length > 0) {
714709
Plotly.restyle(this.gd, {"opacity": opacities}, tracesToDim);
710+
// this is an unfortunate consequence of the selected/unselected API
711+
// https://codepen.io/cpsievert/pen/opOawp
712+
Plotly.restyle(this.gd, {"unselected": {"marker": {"opacity": 1}}});
715713
}
716714

717715
}

inst/plotlyjs.R

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
library(httr)
22
# download latest GitHub release
3-
# for a particular version: `zip <- "https://github.com/plotly/plotly.js/archive/v1.25.0.zip"`
3+
# for a particular version: `zip <- "https://github.com/plotly/plotly.js/archive/v1.33.1.zip"`
44
x <- GET('https://api.github.com/repos/plotly/plotly.js/releases/latest')
55
zip <- content(x)$zipball_url
66
tmp <- tempfile(fileext = ".zip")

0 commit comments

Comments
 (0)