Skip to content

Commit cac9b55

Browse files
committed
always completely replace propery path
1 parent f9c9a81 commit cac9b55

File tree

2 files changed

+55
-27
lines changed

2 files changed

+55
-27
lines changed

R/style.R

Lines changed: 23 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -37,39 +37,35 @@
3737
#' # similar to plotly.js, you can update a particular attribute like so
3838
#' # https://github.com/plotly/plotly.js/issues/1866#issuecomment-314115744
3939
#' style(p, marker.line.color = "blue")
40+
#' # this clobbers the previously supplied marker.line.color
41+
#' style(p, marker.line = list(width = 2.5), marker.size = 10)
4042
#'
4143
style <- function(p, ..., traces = NULL) {
4244
p <- plotly_build(p)
43-
nTraces <- length(p$x$data)
44-
traces <- traces %||% seq_len(nTraces)
45-
idx <- traces > nTraces
46-
traces <- traces[!idx]
47-
if (any(idx)) warning("You've referenced non-existent traces", call. = FALSE)
48-
argz <- list(...)
49-
50-
# argument names that contain a '.' signify a "partial update"
51-
isPartialUpdate <- grepl("\\.", names(argz))
52-
# expand these special arguments to a suitable list object,
53-
# `list(marker.color = "red")`, to `list(marker = list(color = "red"))`
54-
nms <- strsplit(names(argz), "\\.")
55-
for (i in seq_along(nms)) {
56-
nm <- nms[[i]]
57-
if (length(nm) == 1) next
58-
val <- argz[[i]]
59-
for (j in seq(length(nm), 2)) {
60-
val <- setNames(list(val), nm[j])
61-
}
62-
argz[[i]] <- val
45+
n_traces <- length(p$x$data)
46+
trace_idx <- traces %||% seq_len(n_traces)
47+
if (any(trace_idx > n_traces)) {
48+
warning("You've referenced non-existent traces", call. = FALSE)
6349
}
64-
argz <- setNames(argz, unlist(lapply(nms, `[[`, 1)))
6550

66-
# perform the replacement
67-
for (i in traces) {
68-
for (j in seq_along(argz)) {
69-
attr <- names(argz)[j]
70-
p$x$data[[i]][[attr]] <- if (isPartialUpdate[j]) modify_list(p$x$data[[i]][[attr]], argz[[attr]]) else argz[[attr]]
51+
values <- list(...)
52+
paths <- strsplit(names(values), "\\.")
53+
54+
p$x$data[trace_idx] <- lapply(p$x$data[trace_idx], function(trace) {
55+
for (i in seq_along(paths)) {
56+
trace <- trace_replace(trace, paths[[i]], values[[i]])
7157
}
72-
}
58+
trace
59+
})
7360

7461
p
7562
}
63+
64+
#' @param path character vector of path elements: c("marker", "line", "size")
65+
if (length(path) == 0) return(trace)
66+
if (length(path == 1)) {
67+
trace[[path]] <- value
68+
return(trace)
69+
}
70+
trace_replace(trace[[path[1]]], path[-1], value)
71+
}

tests/testthat/test-style.R

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,35 @@ test_that("Partial update works as expected", {
2323
marker5 <- plotly_build(p5)$x$data[[1]]$marker
2424
expect_equal(marker5, modifyList(marker5, list(line = list(color = "red"))))
2525
})
26+
27+
test_that("Partial update works as expected", {
28+
p4 <- style(p1, marker.color = "red")
29+
marker4 <- plotly_build(p4)$x$data[[1]]$marker
30+
expect_equal(marker4, modifyList(marker4, list(color = "red")))
31+
32+
p5 <- style(p1, marker.line.color = "red")
33+
marker5 <- plotly_build(p5)$x$data[[1]]$marker
34+
expect_equal(marker5, modifyList(marker5, list(line = list(color = "red"))))
35+
})
36+
37+
38+
test_that("Partial update works as expected", {
39+
trace <- list(
40+
x = 1:5,
41+
y = 6:10,
42+
marker = list(line = list(color = "red", width = 20))
43+
)
44+
45+
trace_new <- trace_replace(trace, c("marker", "line"), list(width = 10))
46+
trace$marker$line <- list(width = 10)
47+
expect_equal(trace_new, trace)
48+
49+
trace <- list(
50+
x = 1:5,
51+
y = 6:10,
52+
marker = list(line = list(color = "red", width = 20))
53+
)
54+
trace_new <- trace_replace(trace, c("marker", "line", "width"), 10)
55+
trace$marker$line$width <- 10
56+
expect_equal(trace_new, trace)
57+
})

0 commit comments

Comments
 (0)