[med-svn] [r-cran-scatterd3] 01/06: New upstream version 0.8+dfsg

Andreas Tille tille at debian.org
Wed Nov 30 09:56:30 UTC 2016


This is an automated email from the git hooks/post-receive script.

tille pushed a commit to branch master
in repository r-cran-scatterd3.

commit 9570f92f59f6c03cbd3745929424b71e7519f005
Author: Andreas Tille <tille at debian.org>
Date:   Wed Nov 30 10:51:37 2016 +0100

    New upstream version 0.8+dfsg
---
 DESCRIPTION                           |   8 +-
 MD5                                   |  32 +++---
 NEWS                                  |  11 ++
 R/scatterD3.R                         |  34 ++++++-
 README.md                             |   2 +-
 build/vignette.rds                    | Bin 223 -> 224 bytes
 inst/doc/introduction.R               |  28 ++++-
 inst/doc/introduction.Rmd             |  76 ++++++++++++--
 inst/doc/introduction.html            | 187 ++++++++++++++++++++--------------
 inst/htmlwidgets/lib/d3/LICENSE       |  26 +++++
 inst/htmlwidgets/scatterD3-exports.js |  10 +-
 inst/htmlwidgets/scatterD3-labels.js  |  38 +++++--
 inst/htmlwidgets/scatterD3-setup.js   |  25 +++--
 inst/htmlwidgets/scatterD3.css        |  99 +++++++++++++++---
 inst/htmlwidgets/scatterD3.js         | 110 +++++++++++++++++---
 man/scatterD3.Rd                      |  37 ++++---
 vignettes/introduction.Rmd            |  76 ++++++++++++--
 17 files changed, 623 insertions(+), 176 deletions(-)

diff --git a/DESCRIPTION b/DESCRIPTION
index 9ce6b26..b5da09f 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -1,8 +1,8 @@
 Package: scatterD3
 Type: Package
 Title: D3 JavaScript Scatterplot from R
-Version: 0.7
-Date: 2016-10-26
+Version: 0.8
+Date: 2016-11-18
 Authors at R: c(
     person(
       "Julien", "Barnier",
@@ -43,7 +43,7 @@ Imports: htmlwidgets, digest, ellipse
 Suggests: knitr, rmarkdown
 RoxygenNote: 5.0.1
 NeedsCompilation: no
-Packaged: 2016-10-26 14:09:26 UTC; julien
+Packaged: 2016-11-18 10:33:01 UTC; julien
 Author: Julien Barnier [aut, cre],
   Kent Russell [aut, ctb],
   Mike Bostock [aut, cph] (d3.js library, http://d3js.org),
@@ -51,4 +51,4 @@ Author: Julien Barnier [aut, cre],
   Speros Kokenes [aut, cph] (d3-lasso-plugin library,
     https://github.com/skokenes/D3-Lasso-Plugin)
 Repository: CRAN
-Date/Publication: 2016-10-26 18:13:27
+Date/Publication: 2016-11-18 12:43:19
diff --git a/MD5 b/MD5
index 58fa0f4..5780f0e 100644
--- a/MD5
+++ b/MD5
@@ -1,18 +1,18 @@
-2bcb5b6b0eb20b5bc2f61f1ac4dfa3f6 *DESCRIPTION
+cbe9d46eba15a2c9beeb5d888ccdfa1d *DESCRIPTION
 6175be66a588675cfcc631efac40bccb *NAMESPACE
-3f2bbe9c8bae51d0166d1b11a3a82fc7 *NEWS
+6c9fdb0c6ea9825b433f27bda8bee9e2 *NEWS
 cceffe7465fc66364cdfb8c78319bcb7 *R/scatterD3-Rd.R
-3c316b369e378f9678d6a2e0ac3909d0 *R/scatterD3.R
-166ebf80e55dc8700409ac1b784a6672 *README.md
-269ab1b5eb2eba8f29cacdee5504e66c *build/vignette.rds
-93120ed46baccae9234c9b3306ca2f68 *inst/doc/introduction.R
-dcc7b4cc9a357e0d3c9de4f4bc6d08b0 *inst/doc/introduction.Rmd
-d0ef5daebc371a6978bfdb137a1601eb *inst/doc/introduction.html
-9a43e3ae9eeb6821b99b41158d0b08cd *inst/htmlwidgets/lib/LICENSE
+875b76191753b22ff96619a5a28de4f4 *R/scatterD3.R
+b3589f000251b12fadfe9afa71c68e81 *README.md
+3c5e3d328882205bbbfd78289f64fdd2 *build/vignette.rds
+18138c9193acd2d7e7368066d1e0d16d *inst/doc/introduction.R
+6347e6601d6e70a934431480c698d468 *inst/doc/introduction.Rmd
+0d512c39911af5765a41a9b52ee69292 *inst/doc/introduction.html
 59827795b5ab14a5edc7e6bf8744cef7 *inst/htmlwidgets/lib/d3-lasso-plugin/LICENSE
 95f5a84cb5c61c5abb84da94f8c87b2c *inst/htmlwidgets/lib/d3-lasso-plugin/README.md
 ef54456443f8077b51e73565ef195f96 *inst/htmlwidgets/lib/d3-lasso-plugin/lasso.css
 b5abd75e65309ad41d8d2648d57889c0 *inst/htmlwidgets/lib/d3-lasso-plugin/lasso.js
+9a43e3ae9eeb6821b99b41158d0b08cd *inst/htmlwidgets/lib/d3/LICENSE
 a8d4667973aca44596df48c617bca8a7 *inst/htmlwidgets/lib/d3/d3-4.2.6.min.js
 45e82b5ddf03af6e8393b0ea25ce2a16 *inst/htmlwidgets/lib/d3/d3-array.v1.min.js
 74c3a3a01c70eee2a2532289a06e017a *inst/htmlwidgets/lib/d3/d3-axis.v1.min.js
@@ -35,16 +35,16 @@ ebd16393d06ae1d06545d20ad28a3536 *inst/htmlwidgets/lib/d3/d3-timer.v1.min.js
 98049707cdc14f18f4111d489618bed6 *inst/htmlwidgets/scatterD3-axes.js
 6109b680c252f86e7388d74cd793e5f2 *inst/htmlwidgets/scatterD3-dots.js
 fc0b93862a3ce9472d9b4473cb7775bf *inst/htmlwidgets/scatterD3-ellipses.js
-712d86fcf3622b6cda7b7736ba87036a *inst/htmlwidgets/scatterD3-exports.js
-cef211b739ec3f110ce6f91951b0c77f *inst/htmlwidgets/scatterD3-labels.js
+fb5bed0f205bf2e139ffef27db48a869 *inst/htmlwidgets/scatterD3-exports.js
+927d8a22264ddfefbbc6dbd32d723c55 *inst/htmlwidgets/scatterD3-labels.js
 824f0e4e0ef43e1c66a7130f4a2ee2e5 *inst/htmlwidgets/scatterD3-lasso.js
 fcb449b2588e423278ff9a5c6a4f4e30 *inst/htmlwidgets/scatterD3-legend.js
 492209fcdc68ca591a15f072432c3071 *inst/htmlwidgets/scatterD3-lines.js
-d872e0e9b6d2da587d5d215c896f7847 *inst/htmlwidgets/scatterD3-setup.js
+857a56ed9025052841459ba598b93a78 *inst/htmlwidgets/scatterD3-setup.js
 479d82da539716c35e8a17a320136601 *inst/htmlwidgets/scatterD3-utils.js
-43634992a6de72436671f4c03658f777 *inst/htmlwidgets/scatterD3.css
-e8ed0f24fa1e1a02724fb40290c76405 *inst/htmlwidgets/scatterD3.js
+5911a356340a999932d56c7521fe9ced *inst/htmlwidgets/scatterD3.css
+9c8fd09e6b45b439d2fa668a16267e5e *inst/htmlwidgets/scatterD3.js
 dee4ef6434928b083890f389fed71af4 *inst/htmlwidgets/scatterD3.yaml
 12229f19d7fb5d246373d4a3e633534b *man/scatterD3-shiny.Rd
-1bda725eb66976c5fa6b3e14756ec544 *man/scatterD3.Rd
-dcc7b4cc9a357e0d3c9de4f4bc6d08b0 *vignettes/introduction.Rmd
+e2fdc4511a075587b3d253749c4bcd2b *man/scatterD3.Rd
+6347e6601d6e70a934431480c698d468 *vignettes/introduction.Rmd
diff --git a/NEWS b/NEWS
index c2f8d57..d9be8b0 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,14 @@
+scatterD3 0.8
+------------------------------------------------------
+
+* New "caption" argument to add a toggable caption to the plot
+* New "x_log" and "y_log" arguments for x and y logarithmic scales
+* New argument `labels_positions`, allows to import a previously saved labels positions file
+* Toggle "export labels position" visibility when labels change
+* Bugfix : incoherent data on mouseover after data updating
+* Bugfix : unable to export SVG when text contains non-Latin1 characters
+
+
 scatterD3 0.7
 ------------------------------------------------------
 
diff --git a/R/scatterD3.R b/R/scatterD3.R
index 454bd95..9be3094 100644
--- a/R/scatterD3.R
+++ b/R/scatterD3.R
@@ -5,10 +5,15 @@
 #' @param data default dataset to use for plot.
 #' @param x numerical vector of x values, or variable name if data is not NULL
 #' @param y numerical vector of y values, or variable name if data is not NULL
+#' @param x_log if TRUE, set x scale as logarithmic
+#' @param y_log if TRUE, set y scale as logarithmic
 #' @param lab optional character vector of text labels, or variable name if
 #'     data is not NULL
 #' @param point_size points size. Ignored if size_var is not NULL.
 #' @param labels_size text labels size
+#' @param labels_positions A data frame, as created by the
+#'     "Export labels positions" menu entry, giving each label x and y
+#'     position.
 #' @param point_opacity points opacity, as an integer (same opacity for all
 #'     points) or a vector of integers, or variable name if data is not NULL
 #' @param fixed force a 1:1 aspect ratio
@@ -82,6 +87,9 @@
 #' @param legend_width legend area width, in pixels. Set to 0 to disable
 #'     legend completely.
 #' @param left_margin margin on the left of the plot, in pixels
+#' @param caption caption to be displayed when clicking on the corresponding
+#'     icon. Either a character string, or a list with title, subtitle and
+#'     text elements.
 #' @param width figure width, computed when displayed
 #' @param height figure height, computed when displayed
 #'
@@ -107,7 +115,9 @@
 #' @export
 
 scatterD3 <- function(x, y, data = NULL, lab = NULL,
+                      x_log = FALSE, y_log = FALSE,
                       point_size = 64, labels_size = 10,
+                      labels_positions = NULL,
                       point_opacity = 1,
                       hover_size = 1,
                       hover_opacity = NULL,
@@ -148,7 +158,8 @@ scatterD3 <- function(x, y, data = NULL, lab = NULL,
                                          intercept = c(0, 0),
                                          stroke_dasharray = c(5,5)),
                       axes_font_size = "100%",
-                      legend_font_size = "100%") {
+                      legend_font_size = "100%",
+                      caption = NULL) {
 
     ## Variable names as default labels
     if (is.null(xlab)) xlab <- deparse(substitute(x))
@@ -188,6 +199,18 @@ scatterD3 <- function(x, y, data = NULL, lab = NULL,
     x_categorical <- is.factor(x) || !is.numeric(x)
     y_categorical <- is.factor(y) || !is.numeric(y)
 
+    ## No negative values and no 0 lines if logarithmic scales
+    if (x_log) {
+        if (any(x <= 0))
+            stop("Logarithmic scale and negative values in x")
+        lines <- lines[!(lines$slope == 0 & lines$intercept == 0),]
+    }
+    if (y_log) {
+        if (any(y <= 0))
+            stop("Logarithmic scale and negative values in y")
+        lines <- lines[!(lines$slope == Inf & lines$intercept == 0),]
+    }
+    
     ## colors can be named
     ##  we'll need to convert named vector to a named list
     ##  for the JSON conversion
@@ -204,6 +227,11 @@ scatterD3 <- function(x, y, data = NULL, lab = NULL,
         }
     }
 
+    ## If caption is a character string, convert it to a list
+    if (is.character(caption)) {
+        caption <- list(text = caption)
+    }
+    
     ## data element
     data <- data.frame(x = x, y = y)
     if (!is.null(lab)) data <- cbind(data, lab = lab)
@@ -286,7 +314,10 @@ scatterD3 <- function(x, y, data = NULL, lab = NULL,
 
     ## create a list that contains the settings
     settings <- list(
+        x_log = x_log,
+        y_log = y_log,
         labels_size = labels_size,
+        labels_positions = labels_positions,
         point_size = point_size,
         point_opacity = point_opacity,
         hover_size = hover_size,
@@ -332,6 +363,7 @@ scatterD3 <- function(x, y, data = NULL, lab = NULL,
         transitions = transitions,
         axes_font_size = axes_font_size,
         legend_font_size = legend_font_size,
+        caption = caption,
         lines = lines,
         hashes = hashes
     )
diff --git a/README.md b/README.md
index 4ce994c..728bc95 100644
--- a/README.md
+++ b/README.md
@@ -14,7 +14,7 @@ Here is a small preview of what you will get :
 
 Take a look at
 the
-[visual guide](https://rawgit.com/juba/scatterD3/master/vignettes%2Fintroduction.html#open-urls-when-clicking-points) for
+[visual guide](https://rawgit.com/juba/scatterD3/master/vignettes/introduction.html) for
 a list of features and examples. You can also test it live with
 the [sample shiny app](http://data.nozav.org/app/scatterD3/).
 
diff --git a/build/vignette.rds b/build/vignette.rds
index 90fbe7d..73a6d81 100644
Binary files a/build/vignette.rds and b/build/vignette.rds differ
diff --git a/inst/doc/introduction.R b/inst/doc/introduction.R
index 9eda912..e97f73d 100644
--- a/inst/doc/introduction.R
+++ b/inst/doc/introduction.R
@@ -66,6 +66,10 @@ scatterD3(data = mtcars, x = wt, y = mpg, fixed = TRUE,
                              stroke_width = 1,
                              stroke_dasharray = 5))
 
+## ----log_scales----------------------------------------------------------
+scatterD3(data = mtcars, x = wt, y = mpg, col_var = cyl,
+          x_log = TRUE, y_log = TRUE)
+
 ## ----axis_limits---------------------------------------------------------
 scatterD3(data = mtcars, x = wt, y = mpg, xlim=c(0,10), ylim=c(10,35))
 
@@ -79,6 +83,20 @@ scatterD3(data = mtcars, x = wt, y = mpg, col_var = cyl,
           axes_font_size = "120%",
           legend_font_size = "14px")
 
+## ----cust_left_margin----------------------------------------------------
+scatterD3(data = mtcars, x = wt, y = mpg, col_var = cyl,
+          left_margin = 80)
+
+## ----caption_character---------------------------------------------------
+scatterD3(data = mtcars, x = wt, y = mpg, col_var = cyl,
+          caption = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam aliquam egestas pretium. Donec auctor semper vestibulum. Phasellus in tempor lacus. Maecenas vehicula, ipsum id malesuada placerat, diam lorem aliquet lectus, non lacinia quam leo quis eros.")
+
+## ----caption_list--------------------------------------------------------
+scatterD3(data = mtcars, x = wt, y = mpg, col_var = cyl,
+          caption = list(title = "Caption title",
+                         subtitle = "Caption subtitle",
+                         text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam aliquam egestas pretium. Donec auctor semper vestibulum. Phasellus in tempor lacus. Maecenas vehicula, ipsum id malesuada placerat, diam lorem aliquet lectus, non lacinia quam leo quis eros."))
+
 ## ----cust_tooltips-------------------------------------------------------
 tooltips <- paste("This is an incredible <strong>", rownames(mtcars),"</strong><br />with ", 
                   mtcars$cyl, "cylinders !")
@@ -133,15 +151,19 @@ scatterD3(data = mtcars,
 mtcars$names <- rownames(mtcars)
 scatterD3(data = mtcars, x = wt, y = mpg, lab = names)
 
+## ----labels_export_scatterD3, eval = FALSE-------------------------------
+#  labels <- read.csv("scatterD3_labels.csv")
+#  scatterD3(data = mtcars, x = wt, y = mpg, lab = names, labels_positions = labels)
+
 ## ----labels_export_ggplot2, eval = FALSE---------------------------------
 #  labels <- read.csv("scatterD3_labels.csv")
 #  library(ggplot2)
 #  ggplot() +
 #    geom_point(data = mtcars, aes(x=wt, y=mpg)) +
 #    geom_text(data = labels,
-#              aes(x = scatterD3_label_x,
-#                  y = scatterD3_label_y,
-#                  label = scatterD3_label))
+#              aes(x = lab_x,
+#                  y = lab_y,
+#                  label = lab))
 
 ## ----cust_arrows---------------------------------------------------------
 scatterD3(x = c(1, 0.9, 0.7, 0.2, -0.4, -0.5), xlab = "x",
diff --git a/inst/doc/introduction.Rmd b/inst/doc/introduction.Rmd
index 5354a6d..a1aa254 100644
--- a/inst/doc/introduction.Rmd
+++ b/inst/doc/introduction.Rmd
@@ -169,7 +169,16 @@ scatterD3(data = mtcars, x = wt, y = mpg, fixed = TRUE,
 ```
 
 
-## Axis limits
+## Scales, axes and legend
+
+The `x_log` and `y_log` arguments allow to use logarithmic scales on the `x`
+and `y` values. Note that there must not be any value inferior or equal to
+zero in this case :
+
+```{r log_scales}
+scatterD3(data = mtcars, x = wt, y = mpg, col_var = cyl,
+          x_log = TRUE, y_log = TRUE)
+```
 
 You can manually specify the `x` or `y` axis limits with the `xlim` and `ylim` arguments :
 
@@ -177,9 +186,6 @@ You can manually specify the `x` or `y` axis limits with the `xlim` and `ylim` a
 scatterD3(data = mtcars, x = wt, y = mpg, xlim=c(0,10), ylim=c(10,35))
 ```
 
-
-## Axes and legend customization
-
 You can customize the value of the axes and legend labels with `xlab`, `ylab`, `col_lab`, `symbol_lab` and `size_lab` :
 
 ```{r cust_labels}
@@ -200,6 +206,36 @@ scatterD3(data = mtcars, x = wt, y = mpg, col_var = cyl,
 
 You can provide any CSS compatible value, wether a fixed size such as `2em` or a relative one like `95%`.
 
+If the left plot margin is not big enough and your y axis labels are
+truncated, you can adjust it with the `left_margin` argument :
+
+```{r cust_left_margin}
+scatterD3(data = mtcars, x = wt, y = mpg, col_var = cyl,
+          left_margin = 80)
+```
+
+## Caption
+
+You can add an optional caption to your plot, which will be shown when
+clicking on a "info sign" icon in the top right of your plot.
+
+To do so, use the `caption` argument with either a single character string :
+
+```{r caption_character}
+scatterD3(data = mtcars, x = wt, y = mpg, col_var = cyl,
+          caption = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam aliquam egestas pretium. Donec auctor semper vestibulum. Phasellus in tempor lacus. Maecenas vehicula, ipsum id malesuada placerat, diam lorem aliquet lectus, non lacinia quam leo quis eros.")
+```
+
+Or a list with the `title`, `subtitle` and `text` elements :
+
+```{r caption_list}
+scatterD3(data = mtcars, x = wt, y = mpg, col_var = cyl,
+          caption = list(title = "Caption title",
+                         subtitle = "Caption subtitle",
+                         text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam aliquam egestas pretium. Donec auctor semper vestibulum. Phasellus in tempor lacus. Maecenas vehicula, ipsum id malesuada placerat, diam lorem aliquet lectus, non lacinia quam leo quis eros."))
+```
+
+
 
 ## Custom tooltips
 
@@ -286,7 +322,7 @@ Ellipses are computed by the  `ellipse.default()` function of the [ellipse packa
 
 ## Gear menu
 
-The "gear menu" is a small menu which can be displayed by clocking on the "gear" icon on the top-right corner of the plot. It allows to reset the zoom, export the current graph to SVG, and toggle lasso selection.
+The "gear menu" is a small menu which can be displayed by clicking on the "gear" icon on the top-right corner of the plot. It allows to reset the zoom, export the current graph to SVG, and toggle lasso selection.
 
 It is displayed by default, but you can hide it with the `menu = FALSE` argument.
 
@@ -329,7 +365,17 @@ mtcars$names <- rownames(mtcars)
 scatterD3(data = mtcars, x = wt, y = mpg, lab = names)
 ```
 
-You can then open the menu and select *Export labels positions* to save them into a CSV file. If you want to use these positions in another plot, you can do something like that :
+You can then open the menu and select *Export labels positions* to save them
+into a CSV file. If you want to reuse these positions, you can use the
+`labels_positions` argument from `scatterD3` :
+
+```{r labels_export_scatterD3, eval = FALSE}
+labels <- read.csv("scatterD3_labels.csv")
+scatterD3(data = mtcars, x = wt, y = mpg, lab = names, labels_positions = labels)
+```
+
+You can also use this file to reuse coordinates in a plot from a different
+package. The following example should work with `ggplot2` :
 
 ```{r labels_export_ggplot2, eval = FALSE}
 labels <- read.csv("scatterD3_labels.csv")
@@ -337,9 +383,9 @@ library(ggplot2)
 ggplot() +
   geom_point(data = mtcars, aes(x=wt, y=mpg)) +
   geom_text(data = labels,
-            aes(x = scatterD3_label_x,
-                y = scatterD3_label_y,
-                label = scatterD3_label))
+            aes(x = lab_x,
+                y = lab_y,
+                label = lab))
 ```
 
 
@@ -384,3 +430,15 @@ If you are not happy with these ids, you can specify their names yourself with t
 
 The
 [sample scatterD3 shiny app](http://data.nozav.org/app/scatterD3/) allows you to see the different features described here. You can [check its source code on GitHub](https://github.com/juba/scatterD3_shiny_app) for a better understanding of the different arguments.
+
+## Known problems
+
+Due to a lack of support of the `download` attribute in RStudio's interface, two problems may occur when exporting a plot to SVG, or labels positions to CSV :
+
+- the file name suggested in the file save dialog is the data URI. You have to replace it with the name of your choice, and the correct extension (`.svg` or `.csv`).
+
+- when replacing an existing file, if the data to be saved are shorter than the file, it seems that RStudio will just replace the beginning of the file with the new data, but keep existing file content at the end. A workaround is either to always save to a new file, or open the plot in a modern browser before exporting.
+
+
+
+
diff --git a/inst/doc/introduction.html b/inst/doc/introduction.html
index 1675d27..e66cd07 100644
--- a/inst/doc/introduction.html
+++ b/inst/doc/introduction.html
@@ -12,11 +12,11 @@
 
 <meta name="author" content="Julien Barnier" />
 
-<meta name="date" content="2016-10-26" />
+<meta name="date" content="2016-11-18" />
 
 <title>scatterD3 : a Visual Guide</title>
 
-<script src="data:application/x-javascript;base64,KGZ1bmN0aW9uKCkgewogIC8vIElmIHdpbmRvdy5IVE1MV2lkZ2V0cyBpcyBhbHJlYWR5IGRlZmluZWQsIHRoZW4gdXNlIGl0OyBvdGhlcndpc2UgY3JlYXRlIGEKICAvLyBuZXcgb2JqZWN0LiBUaGlzIGFsbG93cyBwcmVjZWRpbmcgY29kZSB0byBzZXQgb3B0aW9ucyB0aGF0IGFmZmVjdCB0aGUKICAvLyBpbml0aWFsaXphdGlvbiBwcm9jZXNzICh0aG91Z2ggbm9uZSBjdXJyZW50bHkgZXhpc3QpLgogIHdpbmRvdy5IVE1MV2lkZ2V0cyA9IHdpbmRvdy5IVE1MV2lkZ2V0cyB8fCB7fTsKCiAgLy8gU2VlIGlmIHdlJ3JlIHJ1bm5pbmcgaW4gYSB2aWV3ZXIgcGFuZS4gSWYgbm90LCB3ZS [...]
+<script src="data:application/x-javascript;base64,KGZ1bmN0aW9uKCkgewogIC8vIElmIHdpbmRvdy5IVE1MV2lkZ2V0cyBpcyBhbHJlYWR5IGRlZmluZWQsIHRoZW4gdXNlIGl0OyBvdGhlcndpc2UgY3JlYXRlIGEKICAvLyBuZXcgb2JqZWN0LiBUaGlzIGFsbG93cyBwcmVjZWRpbmcgY29kZSB0byBzZXQgb3B0aW9ucyB0aGF0IGFmZmVjdCB0aGUKICAvLyBpbml0aWFsaXphdGlvbiBwcm9jZXNzICh0aG91Z2ggbm9uZSBjdXJyZW50bHkgZXhpc3QpLgogIHdpbmRvdy5IVE1MV2lkZ2V0cyA9IHdpbmRvdy5IVE1MV2lkZ2V0cyB8fCB7fTsKCiAgLy8gU2VlIGlmIHdlJ3JlIHJ1bm5pbmcgaW4gYSB2aWV3ZXIgcGFuZS4gSWYgbm90LCB3ZS [...]
 <script src="data:application/x-javascript;base64,Ly8gaHR0cHM6Ly9kM2pzLm9yZy9kMy1jb2xvci8gVmVyc2lvbiAxLjAuMS4gQ29weXJpZ2h0IDIwMTYgTWlrZSBCb3N0b2NrLgohZnVuY3Rpb24odCxlKXsib2JqZWN0Ij09dHlwZW9mIGV4cG9ydHMmJiJ1bmRlZmluZWQiIT10eXBlb2YgbW9kdWxlP2UoZXhwb3J0cyk6ImZ1bmN0aW9uIj09dHlwZW9mIGRlZmluZSYmZGVmaW5lLmFtZD9kZWZpbmUoWyJleHBvcnRzIl0sZSk6ZSh0LmQzPXQuZDN8fHt9KX0odGhpcyxmdW5jdGlvbih0KXsidXNlIHN0cmljdCI7ZnVuY3Rpb24gZSh0LGUsbil7dC5wcm90b3R5cGU9ZS5wcm90b3R5cGU9bixuLmNvbnN0cnVjdG9yPXR9ZnVuY3Rpb24gbi [...]
 <script src="data:application/x-javascript;base64,Ly8gaHR0cHM6Ly9kM2pzLm9yZy9kMy1hcnJheS8gVmVyc2lvbiAxLjAuMS4gQ29weXJpZ2h0IDIwMTYgTWlrZSBCb3N0b2NrLgohZnVuY3Rpb24obixyKXsib2JqZWN0Ij09dHlwZW9mIGV4cG9ydHMmJiJ1bmRlZmluZWQiIT10eXBlb2YgbW9kdWxlP3IoZXhwb3J0cyk6ImZ1bmN0aW9uIj09dHlwZW9mIGRlZmluZSYmZGVmaW5lLmFtZD9kZWZpbmUoWyJleHBvcnRzIl0scik6cihuLmQzPW4uZDN8fHt9KX0odGhpcyxmdW5jdGlvbihuKXsidXNlIHN0cmljdCI7ZnVuY3Rpb24gcihuLHIpe3JldHVybiBuPHI/LTE6bj5yPzE6bj49cj8wOk5hTn1mdW5jdGlvbiB0KG4pe3JldHVybiAxPT [...]
 <script src="data:application/x-javascript;base64,Ly8gaHR0cHM6Ly9kM2pzLm9yZy9kMy1jb2xsZWN0aW9uLyBWZXJzaW9uIDEuMC4xLiBDb3B5cmlnaHQgMjAxNiBNaWtlIEJvc3RvY2suCiFmdW5jdGlvbihuLHQpeyJvYmplY3QiPT10eXBlb2YgZXhwb3J0cyYmInVuZGVmaW5lZCIhPXR5cGVvZiBtb2R1bGU/dChleHBvcnRzKToiZnVuY3Rpb24iPT10eXBlb2YgZGVmaW5lJiZkZWZpbmUuYW1kP2RlZmluZShbImV4cG9ydHMiXSx0KTp0KG4uZDM9bi5kM3x8e30pfSh0aGlzLGZ1bmN0aW9uKG4peyJ1c2Ugc3RyaWN0IjtmdW5jdGlvbiB0KCl7fWZ1bmN0aW9uIGUobixlKXt2YXIgcj1uZXcgdDtpZihuIGluc3RhbmNlb2YgdCluLmVhY2 [...]
@@ -36,19 +36,19 @@
 <script src="data:application/x-javascript;base64,Ly8gaHR0cHM6Ly9kM2pzLm9yZy9kMy16b29tLyBWZXJzaW9uIDEuMC4zLiBDb3B5cmlnaHQgMjAxNiBNaWtlIEJvc3RvY2suCiFmdW5jdGlvbih0LGUpeyJvYmplY3QiPT10eXBlb2YgZXhwb3J0cyYmInVuZGVmaW5lZCIhPXR5cGVvZiBtb2R1bGU/ZShleHBvcnRzLHJlcXVpcmUoImQzLWRpc3BhdGNoIikscmVxdWlyZSgiZDMtZHJhZyIpLHJlcXVpcmUoImQzLWludGVycG9sYXRlIikscmVxdWlyZSgiZDMtc2VsZWN0aW9uIikscmVxdWlyZSgiZDMtdHJhbnNpdGlvbiIpKToiZnVuY3Rpb24iPT10eXBlb2YgZGVmaW5lJiZkZWZpbmUuYW1kP2RlZmluZShbImV4cG9ydHMiLCJkMy1kaX [...]
 <link href="data:text/css;charset=utf-8,%2Elasso%20path%20%7B%0Astroke%3A%20rgb%2880%2C80%2C80%29%3B%0Astroke%2Dwidth%3A%202px%3B%0A%7D%0A%2Elasso%20%2Edrawn%20%7B%0Afill%3A%20%23CCCCCC%3B%0Afill%2Dopacity%3A%20%2E15%20%3B%0A%7D%0A%2Elasso%20%2Eloop%5Fclose%20%7B%0Afill%3A%20none%3B%0Astroke%2Ddasharray%3A%204%2C4%3B%0A%7D%0A%2Elasso%20%2Eorigin%20%7B%0Afill%3A%20%233399FF%3B%0Afill%2Dopacity%3A%20%2E5%3B%0A%7D%0A%2EscatterD3%20%2Enot%2Dpossible%2Dlasso%20%7B%0Afill%3A%20rgb%28150%2C150% [...]
 <script src="data:application/x-javascript;base64,ZDMubGFzc28gPSBmdW5jdGlvbigpIHsKCiAgICB2YXIgaXRlbXMgPSBudWxsLAogICAgICAgIGNsb3NlUGF0aERpc3RhbmNlID0gNzUsCiAgICAgICAgY2xvc2VQYXRoU2VsZWN0ID0gdHJ1ZSwKICAgICAgICBpc1BhdGhDbG9zZWQgPSBmYWxzZSwKICAgICAgICBob3ZlclNlbGVjdCA9IHRydWUsCiAgICAgICAgcG9pbnRzID0gW10sCiAgICAgICAgYXJlYSA9IG51bGwsCiAgICAgICAgb24gPSB7c3RhcnQ6ZnVuY3Rpb24oKXt9LCBkcmF3OiBmdW5jdGlvbigpe30sIGVuZDogZnVuY3Rpb24oKXt9fTsKCiAgICBmdW5jdGlvbiBsYXNzbyhzZWxlY3Rpb24pIHsKCiAgICAgICAgLy8gdG [...]
-<link href="data:text/css;charset=utf-8,%2EscatterD3%2Dtooltip%20%7B%0Aposition%3A%20absolute%3B%0Acolor%3A%20%23222%3B%0Abackground%3A%20%23fff%3B%0Apadding%3A%20%2E5em%3B%0Atext%2Dshadow%3A%20%23f5f5f5%200%201px%200%3B%0Aborder%2Dradius%3A%202px%3B%0Abox%2Dshadow%3A%200px%200px%207px%201px%20%23a6a6a6%3B%0Aopacity%3A%200%2E95%3B%0Afont%2Dfamily%3A%20Open%20Sans%2C%20Droid%20Sans%2C%20Helvetica%2C%20Verdana%2C%20sans%2Dserif%3B%0Afont%2Dsize%3A%2010px%3B%0Az%2Dindex%3A%2010%3B%0A%7D%0A% [...]
+<link href="data:text/css;charset=utf-8,%0A%2EscatterD3%2Dtooltip%20%7B%0Aposition%3A%20absolute%3B%0Acolor%3A%20%23222%3B%0Abackground%3A%20%23fff%3B%0Apadding%3A%20%2E5em%3B%0Atext%2Dshadow%3A%20%23f5f5f5%200%201px%200%3B%0Aborder%2Dradius%3A%202px%3B%0Abox%2Dshadow%3A%200px%200px%207px%201px%20%23a6a6a6%3B%0Aopacity%3A%200%2E95%3B%0Afont%2Dfamily%3A%20Open%20Sans%2C%20Droid%20Sans%2C%20Helvetica%2C%20Verdana%2C%20sans%2Dserif%3B%0Afont%2Dsize%3A%2010px%3B%0Az%2Dindex%3A%2010%3B%0A%7D% [...]
 <script src="data:application/x-javascript;base64,Ly8gQ2xlYW4gdmFyaWFibGVzIGxldmVscyB0byBiZSB2YWxpZCBDU1MgY2xhc3NlcwpmdW5jdGlvbiBjc3NfY2xlYW4ocykgewogICAgaWYgKHMgPT09IHVuZGVmaW5lZCkgcmV0dXJuICIiOwogICAgcmV0dXJuIHMudG9TdHJpbmcoKS5yZXBsYWNlKC9bXlx3LV0vZywgIl8iKTsKfQoKLy8gRGVmYXVsdCB0cmFuc2xhdGlvbiBmdW5jdGlvbiBmb3IgcG9pbnRzIGFuZCBsYWJlbHMKZnVuY3Rpb24gdHJhbnNsYXRpb24oZCwgc2NhbGVzKSB7CiAgICAgcmV0dXJuICJ0cmFuc2xhdGUoIiArIHNjYWxlcy54KGQueCkgKyAiLCIgKyBzY2FsZXMueShkLnkpICsgIikiOwp9CgovLyBDcmVhdG [...]
-<script src="data:application/x-javascript;base64,Ly8gQ3VzdG9tIGNvbG9yIHNjaGVtZQpmdW5jdGlvbiBjdXN0b21fc2NoZW1lMTAgKCkgewogICAgLy8gc2xpY2UoKSB0byBjcmVhdGUgYSBjb3B5CiAgICB2YXIgc2NoZW1lID0gZDMuc2NoZW1lQ2F0ZWdvcnkxMC5zbGljZSgpOwogICAgLy8gU3dpdGNoIG9yYW5nZSBhbmQgcmVkCiAgICB2YXIJdG1wID0gc2NoZW1lWzNdOwogICAgc2NoZW1lWzNdID0gc2NoZW1lWzFdOwogICAgc2NoZW1lWzFdID0gdG1wOwogICAgcmV0dXJuIHNjaGVtZTsKfQoKLy8gU2V0dXAgZGltZW5zaW9ucwpmdW5jdGlvbiBzZXR1cF9zaXplcyAod2lkdGgsIGhlaWdodCwgc2V0dGluZ3MpIHsKCiAgICB2YX [...]
+<script src="data:application/x-javascript;base64,Ly8gQ3VzdG9tIGNvbG9yIHNjaGVtZQpmdW5jdGlvbiBjdXN0b21fc2NoZW1lMTAgKCkgewogICAgLy8gc2xpY2UoKSB0byBjcmVhdGUgYSBjb3B5CiAgICB2YXIgc2NoZW1lID0gZDMuc2NoZW1lQ2F0ZWdvcnkxMC5zbGljZSgpOwogICAgLy8gU3dpdGNoIG9yYW5nZSBhbmQgcmVkCiAgICB2YXIJdG1wID0gc2NoZW1lWzNdOwogICAgc2NoZW1lWzNdID0gc2NoZW1lWzFdOwogICAgc2NoZW1lWzFdID0gdG1wOwogICAgcmV0dXJuIHNjaGVtZTsKfQoKLy8gU2V0dXAgZGltZW5zaW9ucwpmdW5jdGlvbiBzZXR1cF9zaXplcyAod2lkdGgsIGhlaWdodCwgc2V0dGluZ3MpIHsKCiAgICB2YX [...]
 <script src="data:application/x-javascript;base64,Ly8gQ3JlYXRlIGFuZCBkcmF3IHggYW5kIHkgYXhlcwpmdW5jdGlvbiBhZGRfYXhlcyhzZWxlY3Rpb24sIGRpbXMsIHNldHRpbmdzLCBzY2FsZXMpIHsKCiAgICAvLyB4IGF4aXMKICAgIHNlbGVjdGlvbi5hcHBlbmQoImciKQogICAgICAgIC5hdHRyKCJjbGFzcyIsICJ4IGF4aXMiKQogICAgICAgIC5hdHRyKCJ0cmFuc2Zvcm0iLCAidHJhbnNsYXRlKDAsIiArIGRpbXMuaGVpZ2h0ICsgIikiKQogICAgICAgIC5zdHlsZSgiZm9udC1zaXplIiwgc2V0dGluZ3MuYXhlc19mb250X3NpemUpCiAgICAgICAgLmNhbGwoc2NhbGVzLnhBeGlzKTsKCiAgICBzZWxlY3Rpb24uYXBwZW5kKCJ0ZX [...]
 <script src="data:application/x-javascript;base64,Ly8gUmV0dXJucyBkb3Qgc2l6ZSBmcm9tIGFzc29jaWF0ZWQgZGF0YQpmdW5jdGlvbiBkb3Rfc2l6ZShkYXRhLCBzZXR0aW5ncywgc2NhbGVzKSB7CiAgICB2YXIgc2l6ZSA9IHNldHRpbmdzLnBvaW50X3NpemU7CiAgICBpZiAoc2V0dGluZ3MuaGFzX3NpemVfdmFyKSB7IHNpemUgPSBzY2FsZXMuc2l6ZShkYXRhLnNpemVfdmFyKTsgfQogICAgcmV0dXJuKHNpemUpOwp9CgovLyBJbml0aWFsIGRvdCBhdHRyaWJ1dGVzCmZ1bmN0aW9uIGRvdF9pbml0IChzZWxlY3Rpb24sIHNldHRpbmdzLCBzY2FsZXMpIHsKICAgIC8vIHRvb2x0aXBzIHdoZW4gaG92ZXJpbmcgcG9pbnRzCiAgICB2YX [...]
 <script src="data:application/x-javascript;base64,CmZ1bmN0aW9uIGFkZF9hcnJvd3NfZGVmcyhzdmcsIHNldHRpbmdzLCBzY2FsZXMpIHsKICAgIC8vIDxkZWZzPgogICAgdmFyIGRlZnMgPSBzdmcuYXBwZW5kKCJkZWZzIik7CiAgICAvLyBhcnJvdyBoZWFkIG1hcmtlcnMKICAgIHNjYWxlcy5jb2xvci5yYW5nZSgpLmZvckVhY2goZnVuY3Rpb24oZCkgewogICAgICAgIGRlZnMuYXBwZW5kKCJtYXJrZXIiKQoJICAgIC5hdHRyKCJpZCIsICJhcnJvdy1oZWFkLSIgKyBzZXR0aW5ncy5odG1sX2lkICsgIi0iICsgZCkKCSAgICAuYXR0cigibWFya2VyV2lkdGgiLCAiMTAiKQoJICAgIC5hdHRyKCJtYXJrZXJIZWlnaHQiLCAiMTAiKQoJIC [...]
-<script src="data:application/x-javascript;base64,Ci8vIEluaXRpYWwgdGV4dCBsYWJlbCBhdHRyaWJ1dGVzCmZ1bmN0aW9uIGxhYmVsX2luaXQgKHNlbGVjdGlvbikgewogICAgc2VsZWN0aW9uCiAgICAgICAgLmF0dHIoInRleHQtYW5jaG9yIiwgIm1pZGRsZSIpOwp9CgovLyBDb21wdXRlIGRlZmF1bHQgdmVydGljYWwgb2Zmc2V0IGZvciBsYWJlbHMKZnVuY3Rpb24gZGVmYXVsdF9sYWJlbF9keShzaXplLCB5LCB0eXBlX3ZhcixzZXR0aW5ncykgewogICAgaWYgKHkgPCAwICYmIHR5cGVfdmFyICE9PSB1bmRlZmluZWQgJiYgdHlwZV92YXIgPT0gImFycm93IikgewogICAgICAgIHJldHVybiAoTWF0aC5zcXJ0KHNpemUpIC8gMikgKy [...]
+<script src="data:application/x-javascript;base64,Ci8vIEluaXRpYWwgdGV4dCBsYWJlbCBhdHRyaWJ1dGVzCmZ1bmN0aW9uIGxhYmVsX2luaXQgKHNlbGVjdGlvbikgewogICAgc2VsZWN0aW9uCiAgICAgICAgLmF0dHIoInRleHQtYW5jaG9yIiwgIm1pZGRsZSIpOwp9CgovLyBDb21wdXRlIGRlZmF1bHQgdmVydGljYWwgb2Zmc2V0IGZvciBsYWJlbHMKZnVuY3Rpb24gZGVmYXVsdF9sYWJlbF9keShzaXplLCB5LCB0eXBlX3ZhcixzZXR0aW5ncykgewogICAgaWYgKHkgPCAwICYmIHR5cGVfdmFyICE9PSB1bmRlZmluZWQgJiYgdHlwZV92YXIgPT0gImFycm93IikgewogICAgICAgIHJldHVybiAoTWF0aC5zcXJ0KHNpemUpIC8gMikgKy [...]
 <script src="data:application/x-javascript;base64,Ly8gWmVybyBob3Jpem9udGFsIGFuZCB2ZXJ0aWNhbCBsaW5lcwp2YXIgZHJhd19saW5lID0gZDMubGluZSgpCiAgICAueChmdW5jdGlvbihkKSB7cmV0dXJuIGQueDt9KQogICAgLnkoZnVuY3Rpb24oZCkge3JldHVybiBkLnk7fSk7CgpmdW5jdGlvbiBsaW5lX2luaXQoc2VsZWN0aW9uKSB7CiAgICBzZWxlY3Rpb24KCS5hdHRyKCJjbGFzcyIsICJsaW5lIik7CgogICAgcmV0dXJuIHNlbGVjdGlvbjsKfQoKZnVuY3Rpb24gbGluZV9mb3JtYXR0aW5nKHNlbGVjdGlvbiwgZGltcywgc2V0dGluZ3MsIHNjYWxlcykgewogICAgc2VsZWN0aW9uCgkuYXR0cigiZCIsIGZ1bmN0aW9uKGQpIH [...]
 <script src="data:application/x-javascript;base64,Ci8vIEluaXRpYWwgZWxsaXBzZSBhdHRyaWJ1dGVzCmZ1bmN0aW9uIGVsbGlwc2VfaW5pdChzZWxlY3Rpb24pIHsKICAgIHNlbGVjdGlvbgogICAgICAgIC5zdHlsZSgiZmlsbCIsICJub25lIik7Cn0KCi8vIEFwcGx5IGZvcm1hdCB0byBlbGxpcHNlCmZ1bmN0aW9uIGVsbGlwc2VfZm9ybWF0dGluZyhzZWxlY3Rpb24sIHNldHRpbmdzLCBzY2FsZXMpIHsKCiAgICAvLyBFbGxpcHNlcyBwYXRoIGZ1bmN0aW9uCiAgICB2YXIgZWxsaXBzZUZ1bmMgPSBkMy5saW5lKCkKICAgICAgICAueChmdW5jdGlvbihkKSB7IHJldHVybiBzY2FsZXMueChkLngpOyB9KQogICAgICAgIC55KGZ1bmN0aW [...]
 <script src="data:application/x-javascript;base64,Ly8gRm9ybWF0IGxlZ2VuZCBsYWJlbApmdW5jdGlvbiBsZWdlbmRfbGFiZWxfZm9ybWF0dGluZyAoc2VsZWN0aW9uKSB7CiAgICBzZWxlY3Rpb24KICAgICAgICAuc3R5bGUoInRleHQtYW5jaG9yIiwgImJlZ2lubmluZyIpCiAgICAgICAgLnN0eWxlKCJmaWxsIiwgIiMwMDAiKQogICAgICAgIC5zdHlsZSgiZm9udC13ZWlnaHQiLCAiYm9sZCIpOwp9CgovLyBDcmVhdGUgY29sb3IgbGVnZW5kCmZ1bmN0aW9uIGFkZF9jb2xvcl9sZWdlbmQoc3ZnLCBkaW1zLCBzZXR0aW5ncywgc2NhbGVzLCBkdXJhdGlvbikgewoKICAgIC8vIERlZmF1bHQgdHJhbnNpdGlvbiBkdXJhdGlvbiB0byAwCi [...]
 <script src="data:application/x-javascript;base64,Ly8gTGFzc28gZnVuY3Rpb25zIHRvIGV4ZWN1dGUgd2hpbGUgbGFzc29pbmcKdmFyIGxhc3NvX3N0YXJ0ID0gZnVuY3Rpb24obGFzc28pIHsKICAgIGxhc3NvLml0ZW1zKCkKICAgICAgICAuZWFjaChmdW5jdGlvbihkKXsKCSAgICBpZiAoZDMuc2VsZWN0KHRoaXMpLmNsYXNzZWQoJ2RvdCcpKSB7CiAgICAgICAgICAgICAgICBkLnNjYXR0ZXJEM19sYXNzb19kb3Rfc3Ryb2tlID0gZC5zY2F0dGVyRDNfbGFzc29fZG90X3N0cm9rZSA/IGQuc2NhdHRlckQzX2xhc3NvX2RvdF9zdHJva2UgOiBkMy5zZWxlY3QodGhpcykuc3R5bGUoInN0cm9rZSIpOwogICAgICAgICAgICAgICAgZC5zY2 [...]
-<script src="data:application/x-javascript;base64,Ly8gRXhwb3J0IHRvIFNWRyBmdW5jdGlvbgpmdW5jdGlvbiBleHBvcnRfc3ZnKHNlbCwgc3ZnLCBzZXR0aW5ncykgewogICAgdmFyIHN2Z19jb250ZW50ID0gc3ZnCiAgICAgICAgLmF0dHIoInhtbG5zIiwgImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIikKICAgICAgICAuYXR0cigidmVyc2lvbiIsIDEuMSkKICAgICAgICAubm9kZSgpLnBhcmVudE5vZGUuaW5uZXJIVE1MOwogICAgLy8gRGlydHkgZGlydHkgZGlydHkuLi4KICAgIHZhciB0bXAgPSBzdmdfY29udGVudC5yZXBsYWNlKC88ZyBjbGFzcz0iZ2Vhci1tZW51W1xzXFNdKj88XC9nPi8sICcnKTsKICAgIHZhciBzdmdfY2 [...]
-<script src="data:application/x-javascript;base64,ZnVuY3Rpb24gc2NhdHRlckQzKCkgewoKICAgIHZhciB3aWR0aCA9IDYwMCwgLy8gZGVmYXVsdCB3aWR0aAoJaGVpZ2h0ID0gNjAwLCAvLyBkZWZhdWx0IGhlaWdodAoJZGltcyA9IHt9LAoJc2V0dGluZ3MgPSB7fSwKCXNjYWxlcyA9IHt9LAoJZGF0YSA9IFtdLAoJc3ZnLAoJem9vbSwgZHJhZzsKICAgIAogICAgLy8gWm9vbSBiZWhhdmlvcgogICAgem9vbSA9IGQzLnpvb20oKQogICAgICAgIC5zY2FsZUV4dGVudChbMCwgMzJdKQogICAgICAgIC5vbigiem9vbSIsIHpvb21lZCk7CiAgICAKICAgIC8vIFpvb20gZnVuY3Rpb24KICAgIGZ1bmN0aW9uIHpvb21lZChyZXNldCkgewoJdm [...]
+<script src="data:application/x-javascript;base64,Ly8gRXhwb3J0IHRvIFNWRyBmdW5jdGlvbgpmdW5jdGlvbiBleHBvcnRfc3ZnKHNlbCwgc3ZnLCBzZXR0aW5ncykgewogICAgdmFyIHN2Z19jb250ZW50ID0gc3ZnCiAgICAgICAgLmF0dHIoInhtbG5zIiwgImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIikKICAgICAgICAuYXR0cigidmVyc2lvbiIsIDEuMSkKICAgICAgICAubm9kZSgpLnBhcmVudE5vZGUuaW5uZXJIVE1MOwogICAgLy8gRGlydHkgZGlydHkgZGlydHkuLi4KICAgIHN2Z19jb250ZW50ID0gc3ZnX2NvbnRlbnQucmVwbGFjZSgvPGcgY2xhc3M9ImdlYXItbWVudVtcc1xTXSo/PFwvZz4vLCAnJyk7CiAgICBzdmdfY2 [...]
+<script src="data:application/x-javascript;base64,ZnVuY3Rpb24gc2NhdHRlckQzKCkgewoKICAgIHZhciB3aWR0aCA9IDYwMCwgLy8gZGVmYXVsdCB3aWR0aAoJaGVpZ2h0ID0gNjAwLCAvLyBkZWZhdWx0IGhlaWdodAoJZGltcyA9IHt9LAoJc2V0dGluZ3MgPSB7fSwKCXNjYWxlcyA9IHt9LAoJZGF0YSA9IFtdLAoJc3ZnLAoJem9vbSwgZHJhZzsKICAgIAogICAgLy8gWm9vbSBiZWhhdmlvcgogICAgem9vbSA9IGQzLnpvb20oKQogICAgICAgIC5zY2FsZUV4dGVudChbMCwgMzJdKQogICAgICAgIC5vbigiem9vbSIsIHpvb21lZCk7CiAgICAKICAgIC8vIFpvb20gZnVuY3Rpb24KICAgIGZ1bmN0aW9uIHpvb21lZChyZXNldCkgewoJdm [...]
 
 
 <style type="text/css">code{white-space: pre;}</style>
@@ -103,7 +103,7 @@ code > span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Inf
 
 <h1 class="title toc-ignore">scatterD3 : a Visual Guide</h1>
 <h4 class="author"><em>Julien Barnier</em></h4>
-<h4 class="date"><em>2016-10-26</em></h4>
+<h4 class="date"><em>2016-11-18</em></h4>
 
 
 <div id="TOC">
@@ -113,8 +113,8 @@ code > span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Inf
 <li><a href="#point-labels">Point labels</a></li>
 <li><a href="#mapping-colors-symbols-size-and-opacity-to-variables">Mapping colors, symbols, size and opacity to variables</a></li>
 <li><a href="#adding-lines">Adding lines</a></li>
-<li><a href="#axis-limits">Axis limits</a></li>
-<li><a href="#axes-and-legend-customization">Axes and legend customization</a></li>
+<li><a href="#scales-axes-and-legend">Scales, axes and legend</a></li>
+<li><a href="#caption">Caption</a></li>
 <li><a href="#custom-tooltips">Custom tooltips</a></li>
 <li><a href="#open-urls-when-clicking-points">Open URLs when clicking points</a></li>
 <li><a href="#javascript-callback-on-clicking-point">JavaScript callback on clicking point</a></li>
@@ -129,6 +129,7 @@ code > span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Inf
 <li><a href="#additional-controls-reset-zoom-and-svg-export">Additional controls : Reset zoom and SVG export</a></li>
 <li><a href="#sample-app-and-source-code">Sample app and source code</a></li>
 </ul></li>
+<li><a href="#known-problems">Known problems</a></li>
 </ul>
 </div>
 
@@ -140,8 +141,8 @@ code > span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Inf
 <span class="kw">scatterD3</span>(<span class="dt">x =</span> mtcars$wt, <span class="dt">y =</span> mtcars$mpg)</code></pre></div>
 <p>You can pass data arguments as vectors, like above, but you can also give a data frame as <code>data</code> argument and then provide variable names which will be evaluated inside this data frame :</p>
 <div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r"><span class="kw">scatterD3</span>(<span class="dt">data =</span> mtcars , <span class="dt">x =</span> wt, <span class="dt">y =</span> mpg)</code></pre></div>
-<div id="htmlwidget-97e605cda599963ecc3c" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
-<script type="application/json" data-for="htmlwidget-97e605cda599963ecc3c">{"x":{"data":{"x":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,4.07,3.73,3.78,5.25,5.424,5.345,2.2,1.615,1.835,2.465,3.52,3.435,3.84,3.845,1.935,2.14,1.513,3.17,2.77,3.57,2.78],"y":[21,21,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,16.4,17.3,15.2,10.4,10.4,14.7,32.4,30.4,33.9,21.5,15.5,15.2,13.3,19.2,27.3,26,30.4,15.8,19.7,15,21.4],"key_var":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,2 [...]
+<div id="htmlwidget-703b8c0f3ab2d110741f" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
+<script type="application/json" data-for="htmlwidget-703b8c0f3ab2d110741f">{"x":{"data":{"x":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,4.07,3.73,3.78,5.25,5.424,5.345,2.2,1.615,1.835,2.465,3.52,3.435,3.84,3.845,1.935,2.14,1.513,3.17,2.77,3.57,2.78],"y":[21,21,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,16.4,17.3,15.2,10.4,10.4,14.7,32.4,30.4,33.9,21.5,15.5,15.2,13.3,19.2,27.3,26,30.4,15.8,19.7,15,21.4],"key_var":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,2 [...]
 <p>This will display a simple visualization with the given variables as <code>x</code> and <code>y</code> axis. There are several interactive features directly available :</p>
 <ul>
 <li>you can zoom in and out with the mouse wheel while the mouse cursor is on the plot</li>
@@ -152,63 +153,63 @@ code > span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Inf
 <div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r"><span class="kw">scatterD3</span>(<span class="dt">data =</span> mtcars, <span class="dt">x =</span> wt, <span class="dt">y =</span> mpg, 
           <span class="dt">point_size =</span> <span class="dv">35</span>, <span class="dt">point_opacity =</span> <span class="fl">0.5</span>, <span class="dt">fixed =</span> <span class="ot">TRUE</span>,
           <span class="dt">colors =</span> <span class="st">"#A94175"</span>)</code></pre></div>
-<div id="htmlwidget-9fed3d6c3c41a8f07967" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
-<script type="application/json" data-for="htmlwidget-9fed3d6c3c41a8f07967">{"x":{"data":{"x":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,4.07,3.73,3.78,5.25,5.424,5.345,2.2,1.615,1.835,2.465,3.52,3.435,3.84,3.845,1.935,2.14,1.513,3.17,2.77,3.57,2.78],"y":[21,21,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,16.4,17.3,15.2,10.4,10.4,14.7,32.4,30.4,33.9,21.5,15.5,15.2,13.3,19.2,27.3,26,30.4,15.8,19.7,15,21.4],"key_var":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,2 [...]
+<div id="htmlwidget-a2c888a4ffcdb19fe8a2" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
+<script type="application/json" data-for="htmlwidget-a2c888a4ffcdb19fe8a2">{"x":{"data":{"x":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,4.07,3.73,3.78,5.25,5.424,5.345,2.2,1.615,1.835,2.465,3.52,3.435,3.84,3.845,1.935,2.14,1.513,3.17,2.77,3.57,2.78],"y":[21,21,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,16.4,17.3,15.2,10.4,10.4,14.7,32.4,30.4,33.9,21.5,15.5,15.2,13.3,19.2,27.3,26,30.4,15.8,19.7,15,21.4],"key_var":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,2 [...]
 <p>You can change size and opacity of points when hovering with the <code>hover_size</code> and <code>hover_opacity</code> settings :</p>
 <div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r"><span class="kw">scatterD3</span>(<span class="dt">data =</span> mtcars, <span class="dt">x =</span> wt, <span class="dt">y =</span> mpg, 
           <span class="dt">point_size =</span> <span class="dv">100</span>, <span class="dt">point_opacity =</span> <span class="fl">0.5</span>,
           <span class="dt">hover_size =</span> <span class="dv">4</span>, <span class="dt">hover_opacity =</span> <span class="dv">1</span>)</code></pre></div>
-<div id="htmlwidget-0dbd9c3b49d8a00b2be6" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
-<script type="application/json" data-for="htmlwidget-0dbd9c3b49d8a00b2be6">{"x":{"data":{"x":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,4.07,3.73,3.78,5.25,5.424,5.345,2.2,1.615,1.835,2.465,3.52,3.435,3.84,3.845,1.935,2.14,1.513,3.17,2.77,3.57,2.78],"y":[21,21,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,16.4,17.3,15.2,10.4,10.4,14.7,32.4,30.4,33.9,21.5,15.5,15.2,13.3,19.2,27.3,26,30.4,15.8,19.7,15,21.4],"key_var":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,2 [...]
+<div id="htmlwidget-6c204a10a4e6388428e6" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
+<script type="application/json" data-for="htmlwidget-6c204a10a4e6388428e6">{"x":{"data":{"x":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,4.07,3.73,3.78,5.25,5.424,5.345,2.2,1.615,1.835,2.465,3.52,3.435,3.84,3.845,1.935,2.14,1.513,3.17,2.77,3.57,2.78],"y":[21,21,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,16.4,17.3,15.2,10.4,10.4,14.7,32.4,30.4,33.9,21.5,15.5,15.2,13.3,19.2,27.3,26,30.4,15.8,19.7,15,21.4],"key_var":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,2 [...]
 </div>
 <div id="categorical-x-and-y" class="section level2">
 <h2>Categorical <code>x</code> and <code>y</code></h2>
 <p>If the <code>x</code> or <code>y</code> variable is not numeric or is a factor, then an ordinal scale is used for the corresponding axis. Note that zooming is then not possible along this axis.</p>
 <div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r">mtcars$cyl_fac <-<span class="st"> </span><span class="kw">paste</span>(mtcars$cyl, <span class="st">"cylinders"</span>)
 <span class="kw">scatterD3</span>(<span class="dt">data =</span> mtcars, <span class="dt">x =</span> cyl_fac, <span class="dt">y =</span> mpg)</code></pre></div>
-<div id="htmlwidget-07842fabc3cfc03a40a5" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
-<script type="application/json" data-for="htmlwidget-07842fabc3cfc03a40a5">{"x":{"data":{"x":["6 cylinders","6 cylinders","4 cylinders","6 cylinders","8 cylinders","6 cylinders","8 cylinders","4 cylinders","4 cylinders","6 cylinders","6 cylinders","8 cylinders","8 cylinders","8 cylinders","8 cylinders","8 cylinders","8 cylinders","4 cylinders","4 cylinders","4 cylinders","4 cylinders","8 cylinders","8 cylinders","8 cylinders","8 cylinders","4 cylinders","4 cylinders","4 cylinders","8 cyl [...]
+<div id="htmlwidget-e1465ff6a39f8ef8fa03" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
+<script type="application/json" data-for="htmlwidget-e1465ff6a39f8ef8fa03">{"x":{"data":{"x":["6 cylinders","6 cylinders","4 cylinders","6 cylinders","8 cylinders","6 cylinders","8 cylinders","4 cylinders","4 cylinders","6 cylinders","6 cylinders","8 cylinders","8 cylinders","8 cylinders","8 cylinders","8 cylinders","8 cylinders","4 cylinders","4 cylinders","4 cylinders","4 cylinders","8 cylinders","8 cylinders","8 cylinders","8 cylinders","4 cylinders","4 cylinders","4 cylinders","8 cyl [...]
 <p>You can use the <code>left_margin</code> argument when using a categorical <code>y</code> variable if the axis labels are not entirely visible :</p>
 <div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r"><span class="kw">scatterD3</span>(<span class="dt">data =</span> mtcars, <span class="dt">x =</span> wt, <span class="dt">y =</span> cyl_fac, <span class="dt">left_margin =</span> <span class="dv">80</span>)</code></pre></div>
-<div id="htmlwidget-8b19f92c4992b727c4c6" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
-<script type="application/json" data-for="htmlwidget-8b19f92c4992b727c4c6">{"x":{"data":{"x":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,4.07,3.73,3.78,5.25,5.424,5.345,2.2,1.615,1.835,2.465,3.52,3.435,3.84,3.845,1.935,2.14,1.513,3.17,2.77,3.57,2.78],"y":["6 cylinders","6 cylinders","4 cylinders","6 cylinders","8 cylinders","6 cylinders","8 cylinders","4 cylinders","4 cylinders","6 cylinders","6 cylinders","8 cylinders","8 cylinders","8 cylinders","8 cylinders","8 cylinders [...]
+<div id="htmlwidget-e88238fb16bfc947768b" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
+<script type="application/json" data-for="htmlwidget-e88238fb16bfc947768b">{"x":{"data":{"x":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,4.07,3.73,3.78,5.25,5.424,5.345,2.2,1.615,1.835,2.465,3.52,3.435,3.84,3.845,1.935,2.14,1.513,3.17,2.77,3.57,2.78],"y":["6 cylinders","6 cylinders","4 cylinders","6 cylinders","8 cylinders","6 cylinders","8 cylinders","4 cylinders","4 cylinders","6 cylinders","6 cylinders","8 cylinders","8 cylinders","8 cylinders","8 cylinders","8 cylinders [...]
 </div>
 <div id="point-labels" class="section level2">
 <h2>Point labels</h2>
 <p>You can add text labels to the points by passing a character vector to the <code>lab</code> parameter. Labels size are controlled by the <code>labels_size</code> parameter.</p>
 <div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r">mtcars$names <-<span class="st"> </span><span class="kw">rownames</span>(mtcars)
 <span class="kw">scatterD3</span>(<span class="dt">data =</span> mtcars, <span class="dt">x =</span> wt, <span class="dt">y =</span> mpg, <span class="dt">lab =</span> names, <span class="dt">labels_size =</span> <span class="dv">9</span>)</code></pre></div>
-<div id="htmlwidget-e82e27f5e0990187761d" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
-<script type="application/json" data-for="htmlwidget-e82e27f5e0990187761d">{"x":{"data":{"x":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,4.07,3.73,3.78,5.25,5.424,5.345,2.2,1.615,1.835,2.465,3.52,3.435,3.84,3.845,1.935,2.14,1.513,3.17,2.77,3.57,2.78],"y":[21,21,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,16.4,17.3,15.2,10.4,10.4,14.7,32.4,30.4,33.9,21.5,15.5,15.2,13.3,19.2,27.3,26,30.4,15.8,19.7,15,21.4],"lab":["Mazda RX4","Mazda RX4 Wag","Datsun 710","Hornet 4 Drive","Hor [...]
+<div id="htmlwidget-bff9f98b87a1119d24eb" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
+<script type="application/json" data-for="htmlwidget-bff9f98b87a1119d24eb">{"x":{"data":{"x":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,4.07,3.73,3.78,5.25,5.424,5.345,2.2,1.615,1.835,2.465,3.52,3.435,3.84,3.845,1.935,2.14,1.513,3.17,2.77,3.57,2.78],"y":[21,21,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,16.4,17.3,15.2,10.4,10.4,14.7,32.4,30.4,33.9,21.5,15.5,15.2,13.3,19.2,27.3,26,30.4,15.8,19.7,15,21.4],"lab":["Mazda RX4","Mazda RX4 Wag","Datsun 710","Hornet 4 Drive","Hor [...]
 <p>Note that text labels are fully movable : click and drag a label with your mouse to place it where you want. Custom positions are preserved while zooming/panning.</p>
 </div>
 <div id="mapping-colors-symbols-size-and-opacity-to-variables" class="section level2">
 <h2>Mapping colors, symbols, size and opacity to variables</h2>
 <p>By passing vectors to the <code>col_var</code> and/or <code>symbol_var</code> arguments, you can map points colors and symbols to other variables.</p>
 <div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r"><span class="kw">scatterD3</span>(<span class="dt">data =</span> mtcars, <span class="dt">x =</span> wt, <span class="dt">y =</span> mpg, <span class="dt">col_var =</span> cyl, <span class="dt">symbol_var =</span> gear)</code></pre></div>
-<div id="htmlwidget-af7e736b76ec6afa06a7" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
-<script type="application/json" data-for="htmlwidget-af7e736b76ec6afa06a7">{"x":{"data":{"x":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,4.07,3.73,3.78,5.25,5.424,5.345,2.2,1.615,1.835,2.465,3.52,3.435,3.84,3.845,1.935,2.14,1.513,3.17,2.77,3.57,2.78],"y":[21,21,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,16.4,17.3,15.2,10.4,10.4,14.7,32.4,30.4,33.9,21.5,15.5,15.2,13.3,19.2,27.3,26,30.4,15.8,19.7,15,21.4],"col_var":["6","6","4","6","8","6","8","4","4","6","6","8","8","8","8 [...]
+<div id="htmlwidget-701852bd55373d6ce33d" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
+<script type="application/json" data-for="htmlwidget-701852bd55373d6ce33d">{"x":{"data":{"x":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,4.07,3.73,3.78,5.25,5.424,5.345,2.2,1.615,1.835,2.465,3.52,3.435,3.84,3.845,1.935,2.14,1.513,3.17,2.77,3.57,2.78],"y":[21,21,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,16.4,17.3,15.2,10.4,10.4,14.7,32.4,30.4,33.9,21.5,15.5,15.2,13.3,19.2,27.3,26,30.4,15.8,19.7,15,21.4],"col_var":["6","6","4","6","8","6","8","4","4","6","6","8","8","8","8 [...]
 <p>A legend is then automatically added. You can manually specify its width with the <code>legend_width</code> argument. Use <code>legend_width = 0</code> to disable it entirely.</p>
 <p>Note that when hovering over a legend item with your mouse, the corresponding points are highlighted. Also note that the mapped variables values are automatically added to the default tooltips.</p>
 <p>You can also map symbol sizes with a variable with the <code>size_var</code> argument. <code>size_range</code> allows to customize the sizes range :</p>
 <div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r"><span class="kw">scatterD3</span>(<span class="dt">data =</span> mtcars, <span class="dt">x =</span> wt, <span class="dt">y =</span> mpg, <span class="dt">col_var =</span> cyl, <span class="dt">size_var =</span> hp, 
           <span class="dt">size_range =</span> <span class="kw">c</span>(<span class="dv">10</span>,<span class="dv">1000</span>), <span class="dt">point_opacity =</span> <span class="fl">0.7</span>)</code></pre></div>
-<div id="htmlwidget-f4953e626a1dec16fe8a" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
-<script type="application/json" data-for="htmlwidget-f4953e626a1dec16fe8a">{"x":{"data":{"x":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,4.07,3.73,3.78,5.25,5.424,5.345,2.2,1.615,1.835,2.465,3.52,3.435,3.84,3.845,1.935,2.14,1.513,3.17,2.77,3.57,2.78],"y":[21,21,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,16.4,17.3,15.2,10.4,10.4,14.7,32.4,30.4,33.9,21.5,15.5,15.2,13.3,19.2,27.3,26,30.4,15.8,19.7,15,21.4],"col_var":["6","6","4","6","8","6","8","4","4","6","6","8","8","8","8 [...]
+<div id="htmlwidget-97368a497d84738b1cad" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
+<script type="application/json" data-for="htmlwidget-97368a497d84738b1cad">{"x":{"data":{"x":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,4.07,3.73,3.78,5.25,5.424,5.345,2.2,1.615,1.835,2.465,3.52,3.435,3.84,3.845,1.935,2.14,1.513,3.17,2.77,3.57,2.78],"y":[21,21,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,16.4,17.3,15.2,10.4,10.4,14.7,32.4,30.4,33.9,21.5,15.5,15.2,13.3,19.2,27.3,26,30.4,15.8,19.7,15,21.4],"col_var":["6","6","4","6","8","6","8","4","4","6","6","8","8","8","8 [...]
 <p>You can specify custom colors by passing a vector of hexadecimal strings to the <code>colors</code> argument. If the vector is named, then the colors will be associated with their names within <code>col_var</code>.</p>
 <div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r"><span class="kw">scatterD3</span>(<span class="dt">data =</span> mtcars, <span class="dt">x =</span> wt, <span class="dt">y =</span> mpg, <span class="dt">col_var =</span> cyl,
           <span class="dt">colors =</span> <span class="kw">c</span>(<span class="st">"4"</span> =<span class="st"> "#ECD078"</span>, <span class="st">"8"</span> =<span class="st"> "#C02942"</span>, <span class="st">"6"</span> =<span class="st"> "#53777A"</span>))</code></pre></div>
-<div id="htmlwidget-ea7d3194480fe1183a2d" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
-<script type="application/json" data-for="htmlwidget-ea7d3194480fe1183a2d">{"x":{"data":{"x":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,4.07,3.73,3.78,5.25,5.424,5.345,2.2,1.615,1.835,2.465,3.52,3.435,3.84,3.845,1.935,2.14,1.513,3.17,2.77,3.57,2.78],"y":[21,21,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,16.4,17.3,15.2,10.4,10.4,14.7,32.4,30.4,33.9,21.5,15.5,15.2,13.3,19.2,27.3,26,30.4,15.8,19.7,15,21.4],"col_var":["6","6","4","6","8","6","8","4","4","6","6","8","8","8","8 [...]
+<div id="htmlwidget-fc4c30d2b1e3d0df5824" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
+<script type="application/json" data-for="htmlwidget-fc4c30d2b1e3d0df5824">{"x":{"data":{"x":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,4.07,3.73,3.78,5.25,5.424,5.345,2.2,1.615,1.835,2.465,3.52,3.435,3.84,3.845,1.935,2.14,1.513,3.17,2.77,3.57,2.78],"y":[21,21,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,16.4,17.3,15.2,10.4,10.4,14.7,32.4,30.4,33.9,21.5,15.5,15.2,13.3,19.2,27.3,26,30.4,15.8,19.7,15,21.4],"col_var":["6","6","4","6","8","6","8","4","4","6","6","8","8","8","8 [...]
 <p>If <code>col_var</code> is numeric, not a factor, and has more than 6 unique values, it is considered as continuous, and drawn accordingly using the Veridis d3 interpolator.</p>
 <div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r"><span class="kw">scatterD3</span>(<span class="dt">data =</span> mtcars, <span class="dt">x =</span> wt, <span class="dt">y =</span> mpg, <span class="dt">col_var =</span> disp)</code></pre></div>
-<div id="htmlwidget-eee35bf4322787164410" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
-<script type="application/json" data-for="htmlwidget-eee35bf4322787164410">{"x":{"data":{"x":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,4.07,3.73,3.78,5.25,5.424,5.345,2.2,1.615,1.835,2.465,3.52,3.435,3.84,3.845,1.935,2.14,1.513,3.17,2.77,3.57,2.78],"y":[21,21,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,16.4,17.3,15.2,10.4,10.4,14.7,32.4,30.4,33.9,21.5,15.5,15.2,13.3,19.2,27.3,26,30.4,15.8,19.7,15,21.4],"col_var":[160,160,108,258,360,225,360,146.7,140.8,167.6,167.6,275.8, [...]
+<div id="htmlwidget-2832b7d85c279436b4b0" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
+<script type="application/json" data-for="htmlwidget-2832b7d85c279436b4b0">{"x":{"data":{"x":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,4.07,3.73,3.78,5.25,5.424,5.345,2.2,1.615,1.835,2.465,3.52,3.435,3.84,3.845,1.935,2.14,1.513,3.17,2.77,3.57,2.78],"y":[21,21,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,16.4,17.3,15.2,10.4,10.4,14.7,32.4,30.4,33.9,21.5,15.5,15.2,13.3,19.2,27.3,26,30.4,15.8,19.7,15,21.4],"col_var":[160,160,108,258,360,225,360,146.7,140.8,167.6,167.6,275.8, [...]
 <p>In this case, any <code>colors</code> argument is ignored. You can force <code>col_var</code> to be considered as continuous with <code>col_continuous = TRUE</code>.</p>
 <p>You can also use the <code>opacity_var</code> argument to map point opacity to a variable. Note that for now no legend for opacity is added, though.</p>
 <div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r"><span class="kw">scatterD3</span>(<span class="dt">data=</span>mtcars, <span class="dt">x=</span>mpg, <span class="dt">y=</span>wt, <span class="dt">opacity_var =</span> drat)</code></pre></div>
-<div id="htmlwidget-9d3dd0d3f032d7d2a100" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
-<script type="application/json" data-for="htmlwidget-9d3dd0d3f032d7d2a100">{"x":{"data":{"x":[21,21,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,16.4,17.3,15.2,10.4,10.4,14.7,32.4,30.4,33.9,21.5,15.5,15.2,13.3,19.2,27.3,26,30.4,15.8,19.7,15,21.4],"y":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,4.07,3.73,3.78,5.25,5.424,5.345,2.2,1.615,1.835,2.465,3.52,3.435,3.84,3.845,1.935,2.14,1.513,3.17,2.77,3.57,2.78],"opacity_var":[3.9,3.9,3.85,3.08,3.15,2.76,3.21,3.69,3.92,3.92,3.92,3 [...]
+<div id="htmlwidget-efc8a6eda2768c89be5d" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
+<script type="application/json" data-for="htmlwidget-efc8a6eda2768c89be5d">{"x":{"data":{"x":[21,21,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,16.4,17.3,15.2,10.4,10.4,14.7,32.4,30.4,33.9,21.5,15.5,15.2,13.3,19.2,27.3,26,30.4,15.8,19.7,15,21.4],"y":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,4.07,3.73,3.78,5.25,5.424,5.345,2.2,1.615,1.835,2.465,3.52,3.435,3.84,3.845,1.935,2.14,1.513,3.17,2.77,3.57,2.78],"opacity_var":[3.9,3.9,3.85,3.08,3.15,2.76,3.21,3.69,3.92,3.92,3.92,3 [...]
 </div>
 <div id="adding-lines" class="section level2">
 <h2>Adding lines</h2>
@@ -216,8 +217,8 @@ code > span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Inf
 <p>For example, if you want to add a 1:1 line :</p>
 <div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r"><span class="kw">scatterD3</span>(<span class="dt">data =</span> mtcars, <span class="dt">x =</span> wt, <span class="dt">y =</span> mpg, <span class="dt">fixed =</span> <span class="ot">TRUE</span>, 
           <span class="dt">lines =</span> <span class="kw">data.frame</span>(<span class="dt">slope =</span> <span class="dv">1</span>, <span class="dt">intercept =</span> <span class="dv">0</span>))</code></pre></div>
-<div id="htmlwidget-071de03c0b0b4f68b4f4" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
-<script type="application/json" data-for="htmlwidget-071de03c0b0b4f68b4f4">{"x":{"data":{"x":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,4.07,3.73,3.78,5.25,5.424,5.345,2.2,1.615,1.835,2.465,3.52,3.435,3.84,3.845,1.935,2.14,1.513,3.17,2.77,3.57,2.78],"y":[21,21,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,16.4,17.3,15.2,10.4,10.4,14.7,32.4,30.4,33.9,21.5,15.5,15.2,13.3,19.2,27.3,26,30.4,15.8,19.7,15,21.4],"key_var":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,2 [...]
+<div id="htmlwidget-382d4d4e5a0c044e2c57" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
+<script type="application/json" data-for="htmlwidget-382d4d4e5a0c044e2c57">{"x":{"data":{"x":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,4.07,3.73,3.78,5.25,5.424,5.345,2.2,1.615,1.835,2.465,3.52,3.435,3.84,3.845,1.935,2.14,1.513,3.17,2.77,3.57,2.78],"y":[21,21,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,16.4,17.3,15.2,10.4,10.4,14.7,32.4,30.4,33.9,21.5,15.5,15.2,13.3,19.2,27.3,26,30.4,15.8,19.7,15,21.4],"key_var":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,2 [...]
 <p>You can style your lines by adding <code>stroke</code>, <code>stroke_width</code> and <code>stroke_dasharray</code> columns. These columns values will be added as <a href="https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Fills_and_Strokes">corresponding styles</a> to the generated SVG line. So if you want a wide dashed red horizontal line :</p>
 <div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r"><span class="kw">scatterD3</span>(<span class="dt">data =</span> mtcars, <span class="dt">x =</span> wt, <span class="dt">y =</span> mpg, 
           <span class="dt">lines =</span> <span class="kw">data.frame</span>(<span class="dt">slope =</span> <span class="dv">0</span>, 
@@ -225,8 +226,8 @@ code > span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Inf
                              <span class="dt">stroke =</span> <span class="st">"red"</span>,
                              <span class="dt">stroke_width =</span> <span class="dv">5</span>,
                              <span class="dt">stroke_dasharray =</span> <span class="st">"10,5"</span>))</code></pre></div>
-<div id="htmlwidget-bc358db28833790c4aee" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
-<script type="application/json" data-for="htmlwidget-bc358db28833790c4aee">{"x":{"data":{"x":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,4.07,3.73,3.78,5.25,5.424,5.345,2.2,1.615,1.835,2.465,3.52,3.435,3.84,3.845,1.935,2.14,1.513,3.17,2.77,3.57,2.78],"y":[21,21,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,16.4,17.3,15.2,10.4,10.4,14.7,32.4,30.4,33.9,21.5,15.5,15.2,13.3,19.2,27.3,26,30.4,15.8,19.7,15,21.4],"key_var":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,2 [...]
+<div id="htmlwidget-70fb569e8ff52e0c1dd0" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
+<script type="application/json" data-for="htmlwidget-70fb569e8ff52e0c1dd0">{"x":{"data":{"x":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,4.07,3.73,3.78,5.25,5.424,5.345,2.2,1.615,1.835,2.465,3.52,3.435,3.84,3.845,1.935,2.14,1.513,3.17,2.77,3.57,2.78],"y":[21,21,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,16.4,17.3,15.2,10.4,10.4,14.7,32.4,30.4,33.9,21.5,15.5,15.2,13.3,19.2,27.3,26,30.4,15.8,19.7,15,21.4],"key_var":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,2 [...]
 <p>If you want to draw a vertical line, pass the <code>Inf</code> value to <code>slope</code>. The value of <code>intercept</code> is then interpreted as the intercept along the x axis.</p>
 <p>By default, if no <code>lines</code> argument is provided two dashed horizontal and vertical lines are drawn through the origin, which is equivalent to :</p>
 <div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r"><span class="kw">scatterD3</span>(<span class="dt">data =</span> mtcars, <span class="dt">x =</span> wt, <span class="dt">y =</span> mpg, <span class="dt">fixed =</span> <span class="ot">TRUE</span>, 
@@ -235,32 +236,55 @@ code > span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Inf
                              <span class="dt">stroke =</span> <span class="st">"#000"</span>,
                              <span class="dt">stroke_width =</span> <span class="dv">1</span>,
                              <span class="dt">stroke_dasharray =</span> <span class="dv">5</span>))</code></pre></div>
-<div id="htmlwidget-70706f9e21dff2932d03" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
-<script type="application/json" data-for="htmlwidget-70706f9e21dff2932d03">{"x":{"data":{"x":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,4.07,3.73,3.78,5.25,5.424,5.345,2.2,1.615,1.835,2.465,3.52,3.435,3.84,3.845,1.935,2.14,1.513,3.17,2.77,3.57,2.78],"y":[21,21,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,16.4,17.3,15.2,10.4,10.4,14.7,32.4,30.4,33.9,21.5,15.5,15.2,13.3,19.2,27.3,26,30.4,15.8,19.7,15,21.4],"key_var":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,2 [...]
+<div id="htmlwidget-cace3a8a9e346c939f27" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
+<script type="application/json" data-for="htmlwidget-cace3a8a9e346c939f27">{"x":{"data":{"x":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,4.07,3.73,3.78,5.25,5.424,5.345,2.2,1.615,1.835,2.465,3.52,3.435,3.84,3.845,1.935,2.14,1.513,3.17,2.77,3.57,2.78],"y":[21,21,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,16.4,17.3,15.2,10.4,10.4,14.7,32.4,30.4,33.9,21.5,15.5,15.2,13.3,19.2,27.3,26,30.4,15.8,19.7,15,21.4],"key_var":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,2 [...]
 </div>
-<div id="axis-limits" class="section level2">
-<h2>Axis limits</h2>
+<div id="scales-axes-and-legend" class="section level2">
+<h2>Scales, axes and legend</h2>
+<p>The <code>x_log</code> and <code>y_log</code> arguments allow to use logarithmic scales on the <code>x</code> and <code>y</code> values. Note that there must not be any value inferior or equal to zero in this case :</p>
+<div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r"><span class="kw">scatterD3</span>(<span class="dt">data =</span> mtcars, <span class="dt">x =</span> wt, <span class="dt">y =</span> mpg, <span class="dt">col_var =</span> cyl,
+          <span class="dt">x_log =</span> <span class="ot">TRUE</span>, <span class="dt">y_log =</span> <span class="ot">TRUE</span>)</code></pre></div>
+<div id="htmlwidget-bed2281d0713c82c5742" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
+<script type="application/json" data-for="htmlwidget-bed2281d0713c82c5742">{"x":{"data":{"x":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,4.07,3.73,3.78,5.25,5.424,5.345,2.2,1.615,1.835,2.465,3.52,3.435,3.84,3.845,1.935,2.14,1.513,3.17,2.77,3.57,2.78],"y":[21,21,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,16.4,17.3,15.2,10.4,10.4,14.7,32.4,30.4,33.9,21.5,15.5,15.2,13.3,19.2,27.3,26,30.4,15.8,19.7,15,21.4],"col_var":["6","6","4","6","8","6","8","4","4","6","6","8","8","8","8 [...]
 <p>You can manually specify the <code>x</code> or <code>y</code> axis limits with the <code>xlim</code> and <code>ylim</code> arguments :</p>
 <div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r"><span class="kw">scatterD3</span>(<span class="dt">data =</span> mtcars, <span class="dt">x =</span> wt, <span class="dt">y =</span> mpg, <span class="dt">xlim=</span><span class="kw">c</span>(<span class="dv">0</span>,<span class="dv">10</span>), <span class="dt">ylim=</span><span class="kw">c</span>(<span class="dv">10</span>,<span class="dv">35</span>))</code></pre></div>
-<div id="htmlwidget-3af7722fc7d6ae36799c" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
-<script type="application/json" data-for="htmlwidget-3af7722fc7d6ae36799c">{"x":{"data":{"x":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,4.07,3.73,3.78,5.25,5.424,5.345,2.2,1.615,1.835,2.465,3.52,3.435,3.84,3.845,1.935,2.14,1.513,3.17,2.77,3.57,2.78],"y":[21,21,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,16.4,17.3,15.2,10.4,10.4,14.7,32.4,30.4,33.9,21.5,15.5,15.2,13.3,19.2,27.3,26,30.4,15.8,19.7,15,21.4],"key_var":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,2 [...]
-</div>
-<div id="axes-and-legend-customization" class="section level2">
-<h2>Axes and legend customization</h2>
+<div id="htmlwidget-efbf38ce11a5891892cc" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
+<script type="application/json" data-for="htmlwidget-efbf38ce11a5891892cc">{"x":{"data":{"x":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,4.07,3.73,3.78,5.25,5.424,5.345,2.2,1.615,1.835,2.465,3.52,3.435,3.84,3.845,1.935,2.14,1.513,3.17,2.77,3.57,2.78],"y":[21,21,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,16.4,17.3,15.2,10.4,10.4,14.7,32.4,30.4,33.9,21.5,15.5,15.2,13.3,19.2,27.3,26,30.4,15.8,19.7,15,21.4],"key_var":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,2 [...]
 <p>You can customize the value of the axes and legend labels with <code>xlab</code>, <code>ylab</code>, <code>col_lab</code>, <code>symbol_lab</code> and <code>size_lab</code> :</p>
 <div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r"><span class="kw">scatterD3</span>(<span class="dt">data =</span> mtcars, <span class="dt">x =</span> wt, <span class="dt">y =</span> mpg, <span class="dt">col_var =</span> cyl, <span class="dt">symbol_var =</span> gear,
           <span class="dt">xlab =</span> <span class="st">"Weight"</span>, <span class="dt">ylab =</span> <span class="st">"Mpg"</span>, <span class="dt">col_lab =</span> <span class="st">"Cylinders"</span>, <span class="dt">symbol_lab =</span> <span class="st">"Gears"</span>)</code></pre></div>
-<div id="htmlwidget-d2a2c19ef89638e79bfc" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
-<script type="application/json" data-for="htmlwidget-d2a2c19ef89638e79bfc">{"x":{"data":{"x":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,4.07,3.73,3.78,5.25,5.424,5.345,2.2,1.615,1.835,2.465,3.52,3.435,3.84,3.845,1.935,2.14,1.513,3.17,2.77,3.57,2.78],"y":[21,21,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,16.4,17.3,15.2,10.4,10.4,14.7,32.4,30.4,33.9,21.5,15.5,15.2,13.3,19.2,27.3,26,30.4,15.8,19.7,15,21.4],"col_var":["6","6","4","6","8","6","8","4","4","6","6","8","8","8","8 [...]
+<div id="htmlwidget-cf4b71ae4f00208f5986" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
+<script type="application/json" data-for="htmlwidget-cf4b71ae4f00208f5986">{"x":{"data":{"x":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,4.07,3.73,3.78,5.25,5.424,5.345,2.2,1.615,1.835,2.465,3.52,3.435,3.84,3.845,1.935,2.14,1.513,3.17,2.77,3.57,2.78],"y":[21,21,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,16.4,17.3,15.2,10.4,10.4,14.7,32.4,30.4,33.9,21.5,15.5,15.2,13.3,19.2,27.3,26,30.4,15.8,19.7,15,21.4],"col_var":["6","6","4","6","8","6","8","4","4","6","6","8","8","8","8 [...]
 <p>Note that default tooltips are updated accordingly.</p>
 <p>You can also change the font size of axes and legend text with <code>axes_font_size</code> and <code>legend_font_size</code> :</p>
 <div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r"><span class="kw">scatterD3</span>(<span class="dt">data =</span> mtcars, <span class="dt">x =</span> wt, <span class="dt">y =</span> mpg, <span class="dt">col_var =</span> cyl,
           <span class="dt">xlab =</span> <span class="st">"Weight"</span>, <span class="dt">ylab =</span> <span class="st">"Mpg"</span>, 
           <span class="dt">axes_font_size =</span> <span class="st">"120%"</span>,
           <span class="dt">legend_font_size =</span> <span class="st">"14px"</span>)</code></pre></div>
-<div id="htmlwidget-c1f21846636e07e6fdb6" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
-<script type="application/json" data-for="htmlwidget-c1f21846636e07e6fdb6">{"x":{"data":{"x":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,4.07,3.73,3.78,5.25,5.424,5.345,2.2,1.615,1.835,2.465,3.52,3.435,3.84,3.845,1.935,2.14,1.513,3.17,2.77,3.57,2.78],"y":[21,21,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,16.4,17.3,15.2,10.4,10.4,14.7,32.4,30.4,33.9,21.5,15.5,15.2,13.3,19.2,27.3,26,30.4,15.8,19.7,15,21.4],"col_var":["6","6","4","6","8","6","8","4","4","6","6","8","8","8","8 [...]
+<div id="htmlwidget-ef8d768421281db44a6d" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
+<script type="application/json" data-for="htmlwidget-ef8d768421281db44a6d">{"x":{"data":{"x":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,4.07,3.73,3.78,5.25,5.424,5.345,2.2,1.615,1.835,2.465,3.52,3.435,3.84,3.845,1.935,2.14,1.513,3.17,2.77,3.57,2.78],"y":[21,21,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,16.4,17.3,15.2,10.4,10.4,14.7,32.4,30.4,33.9,21.5,15.5,15.2,13.3,19.2,27.3,26,30.4,15.8,19.7,15,21.4],"col_var":["6","6","4","6","8","6","8","4","4","6","6","8","8","8","8 [...]
 <p>You can provide any CSS compatible value, wether a fixed size such as <code>2em</code> or a relative one like <code>95%</code>.</p>
+<p>If the left plot margin is not big enough and your y axis labels are truncated, you can adjust it with the <code>left_margin</code> argument :</p>
+<div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r"><span class="kw">scatterD3</span>(<span class="dt">data =</span> mtcars, <span class="dt">x =</span> wt, <span class="dt">y =</span> mpg, <span class="dt">col_var =</span> cyl,
+          <span class="dt">left_margin =</span> <span class="dv">80</span>)</code></pre></div>
+<div id="htmlwidget-2d22ca7cb8501a5a3fcc" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
+<script type="application/json" data-for="htmlwidget-2d22ca7cb8501a5a3fcc">{"x":{"data":{"x":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,4.07,3.73,3.78,5.25,5.424,5.345,2.2,1.615,1.835,2.465,3.52,3.435,3.84,3.845,1.935,2.14,1.513,3.17,2.77,3.57,2.78],"y":[21,21,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,16.4,17.3,15.2,10.4,10.4,14.7,32.4,30.4,33.9,21.5,15.5,15.2,13.3,19.2,27.3,26,30.4,15.8,19.7,15,21.4],"col_var":["6","6","4","6","8","6","8","4","4","6","6","8","8","8","8 [...]
+</div>
+<div id="caption" class="section level2">
+<h2>Caption</h2>
+<p>You can add an optional caption to your plot, which will be shown when clicking on a “info sign” icon in the top right of your plot.</p>
+<p>To do so, use the <code>caption</code> argument with either a single character string :</p>
+<div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r"><span class="kw">scatterD3</span>(<span class="dt">data =</span> mtcars, <span class="dt">x =</span> wt, <span class="dt">y =</span> mpg, <span class="dt">col_var =</span> cyl,
+          <span class="dt">caption =</span> <span class="st">"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam aliquam egestas pretium. Donec auctor semper vestibulum. Phasellus in tempor lacus. Maecenas vehicula, ipsum id malesuada placerat, diam lorem aliquet lectus, non lacinia quam leo quis eros."</span>)</code></pre></div>
+<div id="htmlwidget-14d479001160a55a66c3" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
+<script type="application/json" data-for="htmlwidget-14d479001160a55a66c3">{"x":{"data":{"x":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,4.07,3.73,3.78,5.25,5.424,5.345,2.2,1.615,1.835,2.465,3.52,3.435,3.84,3.845,1.935,2.14,1.513,3.17,2.77,3.57,2.78],"y":[21,21,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,16.4,17.3,15.2,10.4,10.4,14.7,32.4,30.4,33.9,21.5,15.5,15.2,13.3,19.2,27.3,26,30.4,15.8,19.7,15,21.4],"col_var":["6","6","4","6","8","6","8","4","4","6","6","8","8","8","8 [...]
+<p>Or a list with the <code>title</code>, <code>subtitle</code> and <code>text</code> elements :</p>
+<div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r"><span class="kw">scatterD3</span>(<span class="dt">data =</span> mtcars, <span class="dt">x =</span> wt, <span class="dt">y =</span> mpg, <span class="dt">col_var =</span> cyl,
+          <span class="dt">caption =</span> <span class="kw">list</span>(<span class="dt">title =</span> <span class="st">"Caption title"</span>,
+                         <span class="dt">subtitle =</span> <span class="st">"Caption subtitle"</span>,
+                         <span class="dt">text =</span> <span class="st">"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam aliquam egestas pretium. Donec auctor semper vestibulum. Phasellus in tempor lacus. Maecenas vehicula, ipsum id malesuada placerat, diam lorem aliquet lectus, non lacinia quam leo quis eros."</span>))</code></pre></div>
+<div id="htmlwidget-5ac0603af9d0416b4c57" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
+<script type="application/json" data-for="htmlwidget-5ac0603af9d0416b4c57">{"x":{"data":{"x":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,4.07,3.73,3.78,5.25,5.424,5.345,2.2,1.615,1.835,2.465,3.52,3.435,3.84,3.845,1.935,2.14,1.513,3.17,2.77,3.57,2.78],"y":[21,21,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,16.4,17.3,15.2,10.4,10.4,14.7,32.4,30.4,33.9,21.5,15.5,15.2,13.3,19.2,27.3,26,30.4,15.8,19.7,15,21.4],"col_var":["6","6","4","6","8","6","8","4","4","6","6","8","8","8","8 [...]
 </div>
 <div id="custom-tooltips" class="section level2">
 <h2>Custom tooltips</h2>
@@ -268,8 +292,8 @@ code > span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Inf
 <div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r">tooltips <-<span class="st"> </span><span class="kw">paste</span>(<span class="st">"This is an incredible <strong>"</span>, <span class="kw">rownames</span>(mtcars),<span class="st">"</strong><br />with "</span>, 
                   mtcars$cyl, <span class="st">"cylinders !"</span>)
 <span class="kw">scatterD3</span>(<span class="dt">data =</span> mtcars, <span class="dt">x =</span> wt, <span class="dt">y =</span> mpg, <span class="dt">tooltip_text =</span> tooltips)</code></pre></div>
-<div id="htmlwidget-f701c3aa6e8aebac235a" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
-<script type="application/json" data-for="htmlwidget-f701c3aa6e8aebac235a">{"x":{"data":{"x":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,4.07,3.73,3.78,5.25,5.424,5.345,2.2,1.615,1.835,2.465,3.52,3.435,3.84,3.845,1.935,2.14,1.513,3.17,2.77,3.57,2.78],"y":[21,21,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,16.4,17.3,15.2,10.4,10.4,14.7,32.4,30.4,33.9,21.5,15.5,15.2,13.3,19.2,27.3,26,30.4,15.8,19.7,15,21.4],"key_var":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,2 [...]
+<div id="htmlwidget-678f7ac0cffe7f804b13" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
+<script type="application/json" data-for="htmlwidget-678f7ac0cffe7f804b13">{"x":{"data":{"x":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,4.07,3.73,3.78,5.25,5.424,5.345,2.2,1.615,1.835,2.465,3.52,3.435,3.84,3.845,1.935,2.14,1.513,3.17,2.77,3.57,2.78],"y":[21,21,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,16.4,17.3,15.2,10.4,10.4,14.7,32.4,30.4,33.9,21.5,15.5,15.2,13.3,19.2,27.3,26,30.4,15.8,19.7,15,21.4],"key_var":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,2 [...]
 <p>You can also disable tooltips entirely with <code>tooltips = FALSE</code>.</p>
 </div>
 <div id="open-urls-when-clicking-points" class="section level2">
@@ -277,8 +301,8 @@ code > span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Inf
 <p>With the <code>url_var</code> argument, you can specify a character vectors of URLs, associated to each point, and which will be opened when the point is clicked.</p>
 <div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r">mtcars$urls <-<span class="st"> </span><span class="kw">paste0</span>(<span class="st">"https://www.duckduckgo.com/?q="</span>, <span class="kw">rownames</span>(mtcars))
 <span class="kw">scatterD3</span>(<span class="dt">data =</span> mtcars, <span class="dt">x =</span> wt, <span class="dt">y =</span> mpg, <span class="dt">lab =</span> names, <span class="dt">url_var =</span> urls)</code></pre></div>
-<div id="htmlwidget-0d0f819ba07f053d5221" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
-<script type="application/json" data-for="htmlwidget-0d0f819ba07f053d5221">{"x":{"data":{"x":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,4.07,3.73,3.78,5.25,5.424,5.345,2.2,1.615,1.835,2.465,3.52,3.435,3.84,3.845,1.935,2.14,1.513,3.17,2.77,3.57,2.78],"y":[21,21,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,16.4,17.3,15.2,10.4,10.4,14.7,32.4,30.4,33.9,21.5,15.5,15.2,13.3,19.2,27.3,26,30.4,15.8,19.7,15,21.4],"lab":["Mazda RX4","Mazda RX4 Wag","Datsun 710","Hornet 4 Drive","Hor [...]
+<div id="htmlwidget-624045b2ee6edd9b3f39" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
+<script type="application/json" data-for="htmlwidget-624045b2ee6edd9b3f39">{"x":{"data":{"x":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,4.07,3.73,3.78,5.25,5.424,5.345,2.2,1.615,1.835,2.465,3.52,3.435,3.84,3.845,1.935,2.14,1.513,3.17,2.77,3.57,2.78],"y":[21,21,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,16.4,17.3,15.2,10.4,10.4,14.7,32.4,30.4,33.9,21.5,15.5,15.2,13.3,19.2,27.3,26,30.4,15.8,19.7,15,21.4],"lab":["Mazda RX4","Mazda RX4 Wag","Datsun 710","Hornet 4 Drive","Hor [...]
 <p>Note that this won’t work inside RStudio’s internal browser.</p>
 </div>
 <div id="javascript-callback-on-clicking-point" class="section level2">
@@ -288,8 +312,8 @@ code > span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Inf
    <span class="dt">click_callback =</span> <span class="st">"function(id, index) {</span>
 <span class="st">   alert('scatterplot ID: ' + id + ' - Point index: ' + index) </span>
 <span class="st">   }"</span>)</code></pre></div>
-<div id="htmlwidget-d0b58445b163a8c127f2" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
-<script type="application/json" data-for="htmlwidget-d0b58445b163a8c127f2">{"x":{"data":{"x":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,4.07,3.73,3.78,5.25,5.424,5.345,2.2,1.615,1.835,2.465,3.52,3.435,3.84,3.845,1.935,2.14,1.513,3.17,2.77,3.57,2.78],"y":[21,21,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,16.4,17.3,15.2,10.4,10.4,14.7,32.4,30.4,33.9,21.5,15.5,15.2,13.3,19.2,27.3,26,30.4,15.8,19.7,15,21.4],"key_var":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,2 [...]
+<div id="htmlwidget-3293443cb5ee9b5f3b70" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
+<script type="application/json" data-for="htmlwidget-3293443cb5ee9b5f3b70">{"x":{"data":{"x":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,4.07,3.73,3.78,5.25,5.424,5.345,2.2,1.615,1.835,2.465,3.52,3.435,3.84,3.845,1.935,2.14,1.513,3.17,2.77,3.57,2.78],"y":[21,21,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,16.4,17.3,15.2,10.4,10.4,14.7,32.4,30.4,33.9,21.5,15.5,15.2,13.3,19.2,27.3,26,30.4,15.8,19.7,15,21.4],"key_var":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,2 [...]
 <p>One usage can be to pass the index of the clicked point back to Shiny when <code>scatterD3</code> is run inside a Shiny app. The following implementation can do it by using <code>Shiny.onInputChange()</code> :</p>
 <div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r"><span class="kw">scatterD3</span>(<span class="dt">data =</span> mtcars, <span class="dt">x =</span> wt, <span class="dt">y =</span> mpg,
   <span class="dt">click_callback =</span> <span class="st">"function(id, index) {</span>
@@ -308,8 +332,8 @@ code > span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Inf
 <span class="st">    var zoom = '<strong>Zoom</strong><br />xmin = ' + xmin + '<br />xmax = ' + xmax + '<br />ymin = ' + ymin + '<br />ymax = ' + ymax;</span>
 <span class="st">    document.getElementById('zoomExample').innerHTML = zoom;</span>
 <span class="st">   }"</span>)</code></pre></div>
-<div id="htmlwidget-47f949059d47adb212fd" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
-<script type="application/json" data-for="htmlwidget-47f949059d47adb212fd">{"x":{"data":{"x":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,4.07,3.73,3.78,5.25,5.424,5.345,2.2,1.615,1.835,2.465,3.52,3.435,3.84,3.845,1.935,2.14,1.513,3.17,2.77,3.57,2.78],"y":[21,21,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,16.4,17.3,15.2,10.4,10.4,14.7,32.4,30.4,33.9,21.5,15.5,15.2,13.3,19.2,27.3,26,30.4,15.8,19.7,15,21.4],"key_var":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,2 [...]
+<div id="htmlwidget-7d47ad3906918ae86d13" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
+<script type="application/json" data-for="htmlwidget-7d47ad3906918ae86d13">{"x":{"data":{"x":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,4.07,3.73,3.78,5.25,5.424,5.345,2.2,1.615,1.835,2.465,3.52,3.435,3.84,3.845,1.935,2.14,1.513,3.17,2.77,3.57,2.78],"y":[21,21,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,16.4,17.3,15.2,10.4,10.4,14.7,32.4,30.4,33.9,21.5,15.5,15.2,13.3,19.2,27.3,26,30.4,15.8,19.7,15,21.4],"key_var":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,2 [...]
 <div id="zoomExample" style="font-size: 80%; background-color: #F9F9F9; padding: 5px; margin-left: 5em; width: 15em;">
 <strong>Zoom</strong><br /> None yet !
 </div>
@@ -318,29 +342,29 @@ code > span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Inf
 <h2>Confidence ellipses</h2>
 <p>You can draw a confidence ellipse around the points :</p>
 <div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r"><span class="kw">scatterD3</span>(<span class="dt">data =</span> mtcars, <span class="dt">x =</span> wt, <span class="dt">y =</span> mpg, <span class="dt">ellipses =</span> <span class="ot">TRUE</span>)</code></pre></div>
-<div id="htmlwidget-b8a2fa4553697669c372" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
-<script type="application/json" data-for="htmlwidget-b8a2fa4553697669c372">{"x":{"data":{"x":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,4.07,3.73,3.78,5.25,5.424,5.345,2.2,1.615,1.835,2.465,3.52,3.435,3.84,3.845,1.935,2.14,1.513,3.17,2.77,3.57,2.78],"y":[21,21,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,16.4,17.3,15.2,10.4,10.4,14.7,32.4,30.4,33.9,21.5,15.5,15.2,13.3,19.2,27.3,26,30.4,15.8,19.7,15,21.4],"key_var":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,2 [...]
+<div id="htmlwidget-d61fdbcf145e479605a9" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
+<script type="application/json" data-for="htmlwidget-d61fdbcf145e479605a9">{"x":{"data":{"x":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,4.07,3.73,3.78,5.25,5.424,5.345,2.2,1.615,1.835,2.465,3.52,3.435,3.84,3.845,1.935,2.14,1.513,3.17,2.77,3.57,2.78],"y":[21,21,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,16.4,17.3,15.2,10.4,10.4,14.7,32.4,30.4,33.9,21.5,15.5,15.2,13.3,19.2,27.3,26,30.4,15.8,19.7,15,21.4],"key_var":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,2 [...]
 <p>Or around the different groups of points defined by <code>col_var</code> :</p>
 <div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r"><span class="kw">scatterD3</span>(<span class="dt">data =</span> mtcars, <span class="dt">x =</span> wt, <span class="dt">y =</span> mpg, <span class="dt">col_var =</span> cyl, <span class="dt">ellipses =</span> <span class="ot">TRUE</span>)</code></pre></div>
-<div id="htmlwidget-6ee123d8c724af091a73" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
-<script type="application/json" data-for="htmlwidget-6ee123d8c724af091a73">{"x":{"data":{"x":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,4.07,3.73,3.78,5.25,5.424,5.345,2.2,1.615,1.835,2.465,3.52,3.435,3.84,3.845,1.935,2.14,1.513,3.17,2.77,3.57,2.78],"y":[21,21,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,16.4,17.3,15.2,10.4,10.4,14.7,32.4,30.4,33.9,21.5,15.5,15.2,13.3,19.2,27.3,26,30.4,15.8,19.7,15,21.4],"col_var":["6","6","4","6","8","6","8","4","4","6","6","8","8","8","8 [...]
+<div id="htmlwidget-008a8f724ef0cb4b645e" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
+<script type="application/json" data-for="htmlwidget-008a8f724ef0cb4b645e">{"x":{"data":{"x":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,4.07,3.73,3.78,5.25,5.424,5.345,2.2,1.615,1.835,2.465,3.52,3.435,3.84,3.845,1.935,2.14,1.513,3.17,2.77,3.57,2.78],"y":[21,21,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,16.4,17.3,15.2,10.4,10.4,14.7,32.4,30.4,33.9,21.5,15.5,15.2,13.3,19.2,27.3,26,30.4,15.8,19.7,15,21.4],"col_var":["6","6","4","6","8","6","8","4","4","6","6","8","8","8","8 [...]
 <p>Ellipses are computed by the <code>ellipse.default()</code> function of the <a href="https://cran.r-project.org/package=ellipse">ellipse package</a>. The confidence level can be changed with the <code>ellipse_level</code> argument (<code>0.95</code> by default).</p>
 </div>
 <div id="gear-menu" class="section level2">
 <h2>Gear menu</h2>
-<p>The “gear menu” is a small menu which can be displayed by clocking on the “gear” icon on the top-right corner of the plot. It allows to reset the zoom, export the current graph to SVG, and toggle lasso selection.</p>
+<p>The “gear menu” is a small menu which can be displayed by clicking on the “gear” icon on the top-right corner of the plot. It allows to reset the zoom, export the current graph to SVG, and toggle lasso selection.</p>
 <p>It is displayed by default, but you can hide it with the <code>menu = FALSE</code> argument.</p>
 <div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r"><span class="kw">scatterD3</span>(<span class="dt">data =</span> mtcars, <span class="dt">x =</span> wt, <span class="dt">y =</span> mpg, <span class="dt">menu =</span> <span class="ot">FALSE</span>)</code></pre></div>
-<div id="htmlwidget-f74d591ea9e0cc941066" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
-<script type="application/json" data-for="htmlwidget-f74d591ea9e0cc941066">{"x":{"data":{"x":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,4.07,3.73,3.78,5.25,5.424,5.345,2.2,1.615,1.835,2.465,3.52,3.435,3.84,3.845,1.935,2.14,1.513,3.17,2.77,3.57,2.78],"y":[21,21,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,16.4,17.3,15.2,10.4,10.4,14.7,32.4,30.4,33.9,21.5,15.5,15.2,13.3,19.2,27.3,26,30.4,15.8,19.7,15,21.4],"key_var":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,2 [...]
+<div id="htmlwidget-f6c733693a185c0d1880" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
+<script type="application/json" data-for="htmlwidget-f6c733693a185c0d1880">{"x":{"data":{"x":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,4.07,3.73,3.78,5.25,5.424,5.345,2.2,1.615,1.835,2.465,3.52,3.435,3.84,3.845,1.935,2.14,1.513,3.17,2.77,3.57,2.78],"y":[21,21,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,16.4,17.3,15.2,10.4,10.4,14.7,32.4,30.4,33.9,21.5,15.5,15.2,13.3,19.2,27.3,26,30.4,15.8,19.7,15,21.4],"key_var":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,2 [...]
 </div>
 <div id="lasso-selection-tool" class="section level2">
 <h2>Lasso selection tool</h2>
 <p>Thanks to the <a href="https://github.com/skokenes/D3-Lasso-Plugin">d3-lasso-plugin</a> integration made by @<a href="https://github.com/timelyportfolio">timelyportfolio</a>, you can select and highlight points with a lasso selection tool. To activate it, just add a <code>lasso = TRUE</code> argument. The tool is used by shift-clicking and dragging on the plot area (if it doesn’t activate, click on the chart first to give it focus).</p>
 <div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r">mtcars$names <-<span class="st"> </span><span class="kw">rownames</span>(mtcars)
 <span class="kw">scatterD3</span>(<span class="dt">data =</span> mtcars, <span class="dt">x =</span> wt, <span class="dt">y =</span> mpg, <span class="dt">lab =</span> names, <span class="dt">lasso =</span> <span class="ot">TRUE</span>)</code></pre></div>
-<div id="htmlwidget-7d40d1c7d9417b69b344" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
-<script type="application/json" data-for="htmlwidget-7d40d1c7d9417b69b344">{"x":{"data":{"x":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,4.07,3.73,3.78,5.25,5.424,5.345,2.2,1.615,1.835,2.465,3.52,3.435,3.84,3.845,1.935,2.14,1.513,3.17,2.77,3.57,2.78],"y":[21,21,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,16.4,17.3,15.2,10.4,10.4,14.7,32.4,30.4,33.9,21.5,15.5,15.2,13.3,19.2,27.3,26,30.4,15.8,19.7,15,21.4],"lab":["Mazda RX4","Mazda RX4 Wag","Datsun 710","Hornet 4 Drive","Hor [...]
+<div id="htmlwidget-0d8b54aafffc2e6ab4e9" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
+<script type="application/json" data-for="htmlwidget-0d8b54aafffc2e6ab4e9">{"x":{"data":{"x":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,4.07,3.73,3.78,5.25,5.424,5.345,2.2,1.615,1.835,2.465,3.52,3.435,3.84,3.845,1.935,2.14,1.513,3.17,2.77,3.57,2.78],"y":[21,21,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,16.4,17.3,15.2,10.4,10.4,14.7,32.4,30.4,33.9,21.5,15.5,15.2,13.3,19.2,27.3,26,30.4,15.8,19.7,15,21.4],"lab":["Mazda RX4","Mazda RX4 Wag","Datsun 710","Hornet 4 Drive","Hor [...]
 <p>To undo the selection, just shift-click again.</p>
 <p>You can specify a custom JavaScript callback function to be called by passing it to the <code>lasso_callback</code> argument as a character string. This function should accept a <code>sel</code> argument, which is a d3 selection of selected points.</p>
 <p>Here is an example which shows an alert with selected point labels :</p>
@@ -349,8 +373,8 @@ code > span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Inf
           <span class="dt">x =</span> wt, <span class="dt">y =</span> mpg, <span class="dt">lab =</span> names, 
           <span class="dt">lasso =</span> <span class="ot">TRUE</span>,
           <span class="dt">lasso_callback =</span> <span class="st">"function(sel) {alert(sel.data().map(function(d) {return d.lab}).join('</span><span class="ch">\\</span><span class="st">n'));}"</span>)</code></pre></div>
-<div id="htmlwidget-46c5d2d5e0dbca1886cf" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
-<script type="application/json" data-for="htmlwidget-46c5d2d5e0dbca1886cf">{"x":{"data":{"x":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,4.07,3.73,3.78,5.25,5.424,5.345,2.2,1.615,1.835,2.465,3.52,3.435,3.84,3.845,1.935,2.14,1.513,3.17,2.77,3.57,2.78],"y":[21,21,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,16.4,17.3,15.2,10.4,10.4,14.7,32.4,30.4,33.9,21.5,15.5,15.2,13.3,19.2,27.3,26,30.4,15.8,19.7,15,21.4],"lab":["Mazda RX4","Mazda RX4 Wag","Datsun 710","Hornet 4 Drive","Hor [...]
+<div id="htmlwidget-5ad89f6202ef238f828f" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
+<script type="application/json" data-for="htmlwidget-5ad89f6202ef238f828f">{"x":{"data":{"x":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,4.07,3.73,3.78,5.25,5.424,5.345,2.2,1.615,1.835,2.465,3.52,3.435,3.84,3.845,1.935,2.14,1.513,3.17,2.77,3.57,2.78],"y":[21,21,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,16.4,17.3,15.2,10.4,10.4,14.7,32.4,30.4,33.9,21.5,15.5,15.2,13.3,19.2,27.3,26,30.4,15.8,19.7,15,21.4],"lab":["Mazda RX4","Mazda RX4 Wag","Datsun 710","Hornet 4 Drive","Hor [...]
 </div>
 <div id="custom-labels-positions-export" class="section level2">
 <h2>Custom labels positions export</h2>
@@ -358,17 +382,20 @@ code > span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Inf
 <p>For example, if you change the labels placement in the following plot :</p>
 <div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r">mtcars$names <-<span class="st"> </span><span class="kw">rownames</span>(mtcars)
 <span class="kw">scatterD3</span>(<span class="dt">data =</span> mtcars, <span class="dt">x =</span> wt, <span class="dt">y =</span> mpg, <span class="dt">lab =</span> names)</code></pre></div>
-<div id="htmlwidget-c3d3dddc0a556cf097ff" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
-<script type="application/json" data-for="htmlwidget-c3d3dddc0a556cf097ff">{"x":{"data":{"x":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,4.07,3.73,3.78,5.25,5.424,5.345,2.2,1.615,1.835,2.465,3.52,3.435,3.84,3.845,1.935,2.14,1.513,3.17,2.77,3.57,2.78],"y":[21,21,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,16.4,17.3,15.2,10.4,10.4,14.7,32.4,30.4,33.9,21.5,15.5,15.2,13.3,19.2,27.3,26,30.4,15.8,19.7,15,21.4],"lab":["Mazda RX4","Mazda RX4 Wag","Datsun 710","Hornet 4 Drive","Hor [...]
-<p>You can then open the menu and select <em>Export labels positions</em> to save them into a CSV file. If you want to use these positions in another plot, you can do something like that :</p>
+<div id="htmlwidget-d57bdca4683ec0dba857" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
+<script type="application/json" data-for="htmlwidget-d57bdca4683ec0dba857">{"x":{"data":{"x":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,4.07,3.73,3.78,5.25,5.424,5.345,2.2,1.615,1.835,2.465,3.52,3.435,3.84,3.845,1.935,2.14,1.513,3.17,2.77,3.57,2.78],"y":[21,21,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,16.4,17.3,15.2,10.4,10.4,14.7,32.4,30.4,33.9,21.5,15.5,15.2,13.3,19.2,27.3,26,30.4,15.8,19.7,15,21.4],"lab":["Mazda RX4","Mazda RX4 Wag","Datsun 710","Hornet 4 Drive","Hor [...]
+<p>You can then open the menu and select <em>Export labels positions</em> to save them into a CSV file. If you want to reuse these positions, you can use the <code>labels_positions</code> argument from <code>scatterD3</code> :</p>
+<div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r">labels <-<span class="st"> </span><span class="kw">read.csv</span>(<span class="st">"scatterD3_labels.csv"</span>)
+<span class="kw">scatterD3</span>(<span class="dt">data =</span> mtcars, <span class="dt">x =</span> wt, <span class="dt">y =</span> mpg, <span class="dt">lab =</span> names, <span class="dt">labels_positions =</span> labels)</code></pre></div>
+<p>You can also use this file to reuse coordinates in a plot from a different package. The following example should work with <code>ggplot2</code> :</p>
 <div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r">labels <-<span class="st"> </span><span class="kw">read.csv</span>(<span class="st">"scatterD3_labels.csv"</span>)
 <span class="kw">library</span>(ggplot2)
 <span class="kw">ggplot</span>() +
 <span class="st">  </span><span class="kw">geom_point</span>(<span class="dt">data =</span> mtcars, <span class="kw">aes</span>(<span class="dt">x=</span>wt, <span class="dt">y=</span>mpg)) +
 <span class="st">  </span><span class="kw">geom_text</span>(<span class="dt">data =</span> labels,
-            <span class="kw">aes</span>(<span class="dt">x =</span> scatterD3_label_x,
-                <span class="dt">y =</span> scatterD3_label_y,
-                <span class="dt">label =</span> scatterD3_label))</code></pre></div>
+            <span class="kw">aes</span>(<span class="dt">x =</span> lab_x,
+                <span class="dt">y =</span> lab_y,
+                <span class="dt">label =</span> lab))</code></pre></div>
 </div>
 <div id="other-options" class="section level2">
 <h2>Other options</h2>
@@ -377,8 +404,8 @@ code > span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Inf
           <span class="dt">y =</span> <span class="kw">c</span>(<span class="dv">1</span>, <span class="fl">0.1</span>, -<span class="fl">0.5</span>, <span class="fl">0.5</span>, -<span class="fl">0.6</span>, <span class="fl">0.7</span>), <span class="dt">ylab =</span> <span class="st">"y"</span>,
           <span class="dt">lab =</span> LETTERS[<span class="dv">1</span>:<span class="dv">6</span>], <span class="dt">type_var =</span> <span class="kw">c</span>(<span class="st">"point"</span>, <span class="kw">rep</span>(<span class="st">"arrow"</span>, <span class="dv">5</span>)),
           <span class="dt">unit_circle =</span> <span class="ot">TRUE</span>, <span class="dt">fixed =</span> <span class="ot">TRUE</span>, <span class="dt">xlim =</span> <span class="kw">c</span>(-<span class="fl">1.2</span>, <span class="fl">1.2</span>))</code></pre></div>
-<div id="htmlwidget-9cac3ce23d55a34a9f68" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
-<script type="application/json" data-for="htmlwidget-9cac3ce23d55a34a9f68">{"x":{"data":{"x":[1,0.9,0.7,0.2,-0.4,-0.5],"y":[1,0.1,-0.5,0.5,-0.6,0.7],"lab":["A","B","C","D","E","F"],"type_var":["point","arrow","arrow","arrow","arrow","arrow"],"key_var":[1,2,3,4,5,6]},"settings":{"labels_size":10,"point_size":64,"point_opacity":1,"hover_size":1,"hover_opacity":null,"xlab":"x","ylab":"y","has_labels":true,"col_lab":"NULL","col_continuous":false,"colors":null,"ellipses":false,"ellipses_data" [...]
+<div id="htmlwidget-880e2a712506fc547ed2" style="width:480px;height:288px;" class="scatterD3 html-widget"></div>
+<script type="application/json" data-for="htmlwidget-880e2a712506fc547ed2">{"x":{"data":{"x":[1,0.9,0.7,0.2,-0.4,-0.5],"y":[1,0.1,-0.5,0.5,-0.6,0.7],"lab":["A","B","C","D","E","F"],"type_var":["point","arrow","arrow","arrow","arrow","arrow"],"key_var":[1,2,3,4,5,6]},"settings":{"x_log":false,"y_log":false,"labels_size":10,"labels_positions":null,"point_size":64,"point_opacity":1,"hover_size":1,"hover_opacity":null,"xlab":"x","ylab":"y","has_labels":true,"col_lab":"NULL","col_continuous": [...]
 </div>
 <div id="shiny-integration" class="section level2">
 <h2>Shiny integration</h2>
@@ -404,6 +431,14 @@ code > span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Inf
 <p>The <a href="http://data.nozav.org/app/scatterD3/">sample scatterD3 shiny app</a> allows you to see the different features described here. You can <a href="https://github.com/juba/scatterD3_shiny_app">check its source code on GitHub</a> for a better understanding of the different arguments.</p>
 </div>
 </div>
+<div id="known-problems" class="section level2">
+<h2>Known problems</h2>
+<p>Due to a lack of support of the <code>download</code> attribute in RStudio’s interface, two problems may occur when exporting a plot to SVG, or labels positions to CSV :</p>
+<ul>
+<li><p>the file name suggested in the file save dialog is the data URI. You have to replace it with the name of your choice, and the correct extension (<code>.svg</code> or <code>.csv</code>).</p></li>
+<li><p>when replacing an existing file, if the data to be saved are shorter than the file, it seems that RStudio will just replace the beginning of the file with the new data, but keep existing file content at the end. A workaround is either to always save to a new file, or open the plot in a modern browser before exporting.</p></li>
+</ul>
+</div>
 
 
 
diff --git a/inst/htmlwidgets/lib/d3/LICENSE b/inst/htmlwidgets/lib/d3/LICENSE
new file mode 100644
index 0000000..f27c7e6
--- /dev/null
+++ b/inst/htmlwidgets/lib/d3/LICENSE
@@ -0,0 +1,26 @@
+Copyright (c) 2010-2015, Michael Bostock
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+  list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+
+* The name Michael Bostock may not be used to endorse or promote products
+  derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL MICHAEL BOSTOCK BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/inst/htmlwidgets/scatterD3-exports.js b/inst/htmlwidgets/scatterD3-exports.js
index 6a47f46..8fcfc4f 100644
--- a/inst/htmlwidgets/scatterD3-exports.js
+++ b/inst/htmlwidgets/scatterD3-exports.js
@@ -5,9 +5,11 @@ function export_svg(sel, svg, settings) {
         .attr("version", 1.1)
         .node().parentNode.innerHTML;
     // Dirty dirty dirty...
-    var tmp = svg_content.replace(/<g class="gear-menu[\s\S]*?<\/g>/, '');
-    var svg_content2 = tmp.replace(/<ul class="scatterD3-menu[\s\S]*?<\/ul>/, '');
-    var image_data = "data:image/octet-stream;base64," + window.btoa(svg_content2);
+    svg_content = svg_content.replace(/<g class="gear-menu[\s\S]*?<\/g>/, '');
+    svg_content = svg_content.replace(/<ul class="scatterD3-menu[\s\S]*?<\/ul>/, '');
+    svg_content = svg_content.replace(/<g class="caption-icon[\s\S]*?<\/g>/, '');
+    svg_content = svg_content.replace(/<div class="scatterD3-caption[\s\S]*?<\/div>/, '');
+    var image_data = "data:image/octet-stream;base64," + window.btoa(unescape(encodeURIComponent(svg_content)));
     d3.select(sel)
         .attr("download", settings.html_id + ".svg")
         .attr("href", image_data);
@@ -15,7 +17,7 @@ function export_svg(sel, svg, settings) {
 
 // Function to export custom labels position to CSV file
 function export_labels_position(sel, data, settings, scales) {
-    var lines_data = ["scatterD3_label,scatterD3_label_x,scatterD3_label_y"];
+    var lines_data = ["lab,lab_x,lab_y"];
     data.forEach(function(d, index){
         var labx = d.x;
         if (d.lab_dx !== undefined) {
diff --git a/inst/htmlwidgets/scatterD3-labels.js b/inst/htmlwidgets/scatterD3-labels.js
index 281efd6..06cb442 100644
--- a/inst/htmlwidgets/scatterD3-labels.js
+++ b/inst/htmlwidgets/scatterD3-labels.js
@@ -15,6 +15,33 @@ function default_label_dy(size, y, type_var,settings) {
     }
 }
 
+// Compute label x position
+function get_label_dx(d, i, settings, scales) {
+    // Manually defined
+    if (d.lab_dx !== undefined) return(d.lab_dx);
+    // From labels_positions argument
+    if (settings.labels_positions) {
+	var dx = scales.x(settings.labels_positions[i].lab_x) - scales.x(d.x);
+	return dx;
+    }
+    // Default
+    return("0");
+}
+
+// Compute label y position
+function get_label_dy(d, i, settings, scales) {
+    // Manually defined
+    if (d.lab_dy !== undefined) return(d.lab_dy);
+    // From labels_positions argument
+    if (settings.labels_positions) {
+	var dy = scales.y(settings.labels_positions[i].lab_y) - scales.y(d.y);
+	return dy;
+    }
+    // Default
+    var size = (d.size_var === undefined) ? settings.point_size : scales.size(d.size_var);
+    return default_label_dy(size, d.y, d.type_var, settings);
+}
+
 // Apply format to text label
 function label_formatting (selection, settings, scales) {
     var sel = selection
@@ -23,14 +50,11 @@ function label_formatting (selection, settings, scales) {
         .attr("class", function(d,i) { return "point-label color color-c" + css_clean(d.col_var) + " symbol symbol-c" + css_clean(d.symbol_var); })
         .attr("transform", function(d) { return translation(d, scales); })
         .style("fill", function(d) { return scales.color(d.col_var); })
-        .attr("dx", function(d) {
-	    if (d.lab_dx === undefined) return("0px");
-	    else return(d.lab_dx + "px");
+        .attr("dx", function(d, i) {
+	    return get_label_dx(d, i, settings, scales) + "px";
         })
-        .attr("dy", function(d) {
-	    if (d.lab_dy !== undefined) return(d.lab_dy + "px");
-	    var size = (d.size_var === undefined) ? settings.point_size : scales.size(d.size_var);
-	    return default_label_dy(size, d.y, d.type_var, settings) + "px";
+        .attr("dy", function(d, i) {
+	    return get_label_dy(d, i, settings, scales) + "px";
         });
     return sel;
 }
diff --git a/inst/htmlwidgets/scatterD3-setup.js b/inst/htmlwidgets/scatterD3-setup.js
index 7d6bf51..7be99c9 100644
--- a/inst/htmlwidgets/scatterD3-setup.js
+++ b/inst/htmlwidgets/scatterD3-setup.js
@@ -113,9 +113,10 @@ function setup_scales (dims, settings, data) {
 
     // x, y scales
     if (!settings.x_categorical) {
-        scales.x = d3.scaleLinear()
-	    .range([0, dims.width])
-	    .domain([min_x - gap_x, max_x + gap_x]);
+	scales.x = settings.x_log ? d3.scaleLog() : d3.scaleLinear();
+	var x_domain = settings.x_log ? [min_x * 0.8, max_x * 1.3] : [min_x - gap_x, max_x + gap_x];
+        scales.x.range([0, dims.width])
+	    .domain(x_domain);
     } else {
 	scales.x = d3.scalePoint()
 	    .range([0, dims.width])
@@ -123,9 +124,10 @@ function setup_scales (dims, settings, data) {
 	    .domain(d3.map(data, function(d){ return d.x; }).keys().sort());
     }
     if (!settings.y_categorical) {
-        scales.y = d3.scaleLinear()
-	    .range([dims.height, 0])
-	    .domain([min_y - gap_y, max_y + gap_y]);
+	scales.y = settings.y_log ? d3.scaleLog(): d3.scaleLinear();
+	var y_domain = settings.y_log ? [min_y * 0.9, max_y * 1.1] : [min_y - gap_y, max_y + gap_y];
+        scales.y.range([dims.height, 0])
+	    .domain(y_domain);
     } else {
 	scales.y = d3.scalePoint()
 	    .range([dims.height, 0])
@@ -137,9 +139,11 @@ function setup_scales (dims, settings, data) {
     scales.y_orig = scales.y;
     // x and y axis functions
     scales.xAxis = d3.axisBottom(scales.x)
-        .tickSize(-dims.height);
+        .tickSize(-dims.height)
+	.tickFormat(d3.format(""));
     scales.yAxis = d3.axisLeft(scales.y)
-        .tickSize(-dims.width);
+        .tickSize(-dims.width)
+    	.tickFormat(d3.format(""));;
 
     // Continuous color scale
     if (settings.col_continuous) {
@@ -189,4 +193,7 @@ function gear_path () {
     return "m 24.28,7.2087374 -1.307796,0 c -0.17052,-0.655338 -0.433486,-1.286349 -0.772208,-1.858846 l 0.927566,-0.929797 c 0.281273,-0.281188 0.281273,-0.738139 0,-1.019312 L 21.600185,1.8728727 C 21.319088,1.591685 20.863146,1.5914219 20.582048,1.8726096 L 19.650069,2.8001358 C 19.077606,2.4614173 18.446602,2.1982296 17.791262,2.0278389 l 0,-1.30783846 c 0,-0.39762 -0.313645,-0.72 -0.711262,-0.72 l -2.16,0 c -0.397618,0 -0.711262,0.32238 -0.711262,0.72 l 0,1.30783846 c -0.65534,0.170 [...]
 }
 
-
+// Caption icon path
+function caption_path () {
+    return "m 9.0084765,0.0032163 q 1.8249645,0 3.4939395,0.7097539 1.668974,0.7096153 2.87781,1.918523 1.208839,1.2087707 1.91855,2.8777847 0.709702,1.6690155 0.709702,3.4939387 0,1.8249234 -0.709702,3.4939384 -0.709711,1.669015 -1.91855,2.877784 -1.208836,1.208907 -2.87781,1.918523 -1.668975,0.709754 -3.4939395,0.709754 -1.8249502,0 -3.493924,-0.709754 Q 3.8455651,16.583846 2.6367267,15.374939 1.4278885,14.16617 0.71819,12.497155 0.0084778,10.82814 0.0084778,9.0032166 0.0084778,7.17829 [...]
+}
diff --git a/inst/htmlwidgets/scatterD3.css b/inst/htmlwidgets/scatterD3.css
index ffe99f5..c29f7cd 100644
--- a/inst/htmlwidgets/scatterD3.css
+++ b/inst/htmlwidgets/scatterD3.css
@@ -1,3 +1,5 @@
+/* TOOLTIPS */
+
 .scatterD3-tooltip {
     position: absolute;
     color: #222;
@@ -12,6 +14,8 @@
     z-index: 10;
 }
 
+/* GEAR MENU */
+
 .scatterD3-menu {
   position: absolute;
   opacity: 0;
@@ -48,41 +52,112 @@
   color: #25282A;
 }
 
+/* GEAR ICON */
 
+.scatterD3 .gear-menu {
+    cursor: pointer;
+    height: 25px;
+    width: 25px;
+}
 
-.hidden {
-    display: none;
+.scatterD3 .gear-menu path {
+    opacity: 0.2;
+    transition: opacity .3s;
 }
 
-.scatterD3 .dot {
-    cursor: default;
+.scatterD3 .gear-menu:hover path,
+.scatterD3 .gear-menu.selected path {
+    opacity: 0.8;
+    transition: opacity .3s;
 }
 
-.scatterD3 .point-label {
-  cursor: pointer;
+/* CAPTION */
+
+.scatterD3-caption {
+    background: #F5F7F9;
+    color: #727476;
+    box-shadow: 0px 0px 2px 1px #d6d6d6;
+    font-family: Open Sans, Droid Sans, Helvetica, Verdana, sans-serif;
+    font-size: 1px;
+    text-align: left;
+    padding: 10px 0;
+    margin: 0;
+    position: absolute;
+    z-index: 10;
+    width: 100%;
+    transition: all .3s;
+    opacity: 0;
 }
 
-.scatterD3, .scatterD3:focus {
-  outline: 0px solid transparent
+.scatterD3-caption.visible {
+    opacity: 0.97;
+    cursor: pointer;
 }
 
-.scatterD3 .gear-menu {
+.scatterD3-caption h1,
+.scatterD3-caption h2,
+.scatterD3-caption p
+{
+    margin: 5px 15px;
+    line-height: 1.35;
+    padding: 0;
+    border: none;
+}
+
+.scatterD3-caption h1 {
+    font-size: 14px;
+    font-weight: bold;
+}
+
+.scatterD3-caption h2 {
+    font-size: 13px;
+    font-weight: normal;
+}
+
+.scatterD3-caption .caption {
+    font-size: 11px;
+    font-weight: normal;
+}
+
+/* CAPTION ICON */
+
+.scatterD3 .caption-icon {
     cursor: pointer;
     height: 25px;
     width: 25px;
 }
 
-.scatterD3 .gear-menu path {
+.scatterD3 .caption-icon path {
     opacity: 0.2;
     transition: opacity .3s;
 }
 
-.scatterD3 .gear-menu:hover path,
-.scatterD3 .gear-menu.selected path {
+.scatterD3 .caption-icon:hover path,
+.scatterD3 .caption-icon.selected path {
     opacity: 0.8;
     transition: opacity .3s;
 }
 
+
+
+/* OTHER STYLES */
+
+.hidden {
+    display: none;
+}
+
+.scatterD3 .dot {
+    cursor: default;
+}
+
+.scatterD3 .point-label {
+  cursor: pointer;
+}
+
+.scatterD3, .scatterD3:focus {
+  outline: 0px solid transparent
+}
+
 .scatterD3 .root {
     cursor: move;
 }
diff --git a/inst/htmlwidgets/scatterD3.js b/inst/htmlwidgets/scatterD3.js
index fc42e35..56a9823 100644
--- a/inst/htmlwidgets/scatterD3.js
+++ b/inst/htmlwidgets/scatterD3.js
@@ -51,20 +51,20 @@ function scatterD3() {
     // Text labels dragging function
     var dragging = false;
     drag = d3.drag()
-	.subject(function(d) {
+	.subject(function(d, i) {
             var size = (d.size_var === undefined) ? settings.point_size : scales.size(d.size_var);
-            var dx = (d.lab_dx === undefined) ? 0 : d.lab_dx;
-            var dy = (d.lab_dx === undefined) ? default_label_dy(size, d.y, d.type_var, settings) : d.lab_dy;
+            var dx = get_label_dx(d, i, settings, scales);
+            var dy = get_label_dy(d, i, settings, scales);
             return {x:scales.x(d.x)+dx, y:scales.y(d.y)+dy};
 	})
-	.on('start', function(d) {
+	.on('start', function(d, i) {
 	    if (!d3.event.sourceEvent.shiftKey) {
 		dragging = true;
 		d3.select(this).style('fill', '#000');
 		var chart = d3.select(this).node().parentNode;
 		var size = (d.size_var === undefined) ? settings.point_size : scales.size(d.size_var);
-		var dx = (d.lab_dx === undefined) ? 0 : d.lab_dx;
-		var dy = (d.lab_dx === undefined) ? default_label_dy(size, d.y, d.type_var, settings) : d.lab_dy;
+		var dx = get_label_dx(d, i, settings, scales);
+		var dy = get_label_dy(d, i, settings, scales);
 		d3.select(chart).append("svg:line")
 		    .attr("id", "scatterD3-drag-line")
 		    .attr("x1", scales.x(d.x)).attr("x2", scales.x(d.x) + dx)
@@ -220,7 +220,7 @@ function scatterD3() {
 		// Gear icon
 		var gear = svg.append("g")
 		    .attr("class", "gear-menu")
-		    .attr("transform", "translate(" + (width - 36) + ", 6)");
+		    .attr("transform", "translate(" + (width - 40) + "," + 10 + ")");
 		gear.append("rect")
 		    .attr("class", "gear-toggle")
 		    .attr("width", "25")
@@ -255,11 +255,13 @@ function scatterD3() {
 			.html("Toggle lasso on");
 		}
 
-		if (settings.has_labels) {
-                    menu.append("li")
-			.append("a")
-			.on("click", function() { export_labels_position(this, data, settings, scales); })
-			.html("Export labels positions");
+                var label_export = menu.append("li")
+		    .attr("class", "label-export");
+		label_export.append("a")
+		    .on("click", function() { export_labels_position(this, data, settings, scales); })
+		    .html("Export labels positions");
+		if (!settings.has_labels) {
+		    label_export.style("display", "none");
 		}
 
 		gear.on("click", function(d, i){
@@ -281,6 +283,57 @@ function scatterD3() {
 		});
             }
 
+	    var caption_parent = d3.select(svg.node().parentNode);
+	    var caption = caption_parent.select(".scatterD3-caption");
+
+	    // Caption
+	    if (settings.caption) {
+		if (settings.caption.title)
+		    caption.append("h1").attr("class", "title").html(settings.caption.title);
+		if (settings.caption.subtitle)
+		    caption.append("h2").attr("class", "subtitle").html(settings.caption.subtitle);
+		if (settings.caption.text)
+		    caption.append("p").attr("class", "caption").html(settings.caption.text);
+		caption.style("top", dims.svg_height + "px");
+
+		// Caption icon
+		var caption_top_margin = settings.menu ? 35 : 10;
+		var caption_icon = svg.append("g")
+		    .attr("class", "caption-icon")
+		    .attr("transform", "translate(" + (dims.svg_width - 40) + "," + (dims.svg_height - 71) + ")")
+		    .attr("transform", "translate(" + (dims.svg_width - 40) + "," + caption_top_margin + ")");
+		caption_icon.append("rect")
+		    .attr("class", "caption-toggle")
+		    .attr("width", "25")
+		    .attr("height", "25")
+		    .style("fill", "#FFFFFF");
+		caption_icon.append("path")
+		    .attr("d", caption_path())
+		    .attr("transform", "translate(4,4)")
+		    .style("fill", "#666666");
+
+		caption_icon.on("click", function() {
+		    if (!caption.classed("visible")) {
+			caption.classed("visible", true);
+			caption.style("margin-top", -caption.node().getBoundingClientRect().height + "px");
+		    }
+		    else {
+			caption.classed("visible", false);
+			caption.style("margin-top", "0px");
+		    }
+		});
+
+		caption.on("click", function() {
+		    caption.classed("visible", false);
+		    caption.style("margin-top", "0px");
+		});
+		
+	    }
+	    // No title
+	    else {
+		caption.remove();
+	    }
+
         });
     }
 
@@ -369,7 +422,7 @@ function scatterD3() {
 	var dot = chart_body.selectAll(".dot")
 	    .data(data.filter(point_filter), key);
 	dot.enter().append("path").call(function(sel) {dot_init(sel, settings, scales);})
-	    .merge(dot).transition().duration(1000).call(function(sel) {dot_formatting(sel, settings, scales);});
+	    .merge(dot).call(function(sel) {dot_init(sel, settings, scales);}).transition().duration(1000).call(function(sel) {dot_formatting(sel, settings, scales);});
 	dot.exit().transition().duration(1000).attr("transform", "translate(0,0)").remove();
 	// Add arrows
 	var arrow = chart_body.selectAll(".arrow")
@@ -403,6 +456,12 @@ function scatterD3() {
             labels.exit().transition().duration(1000).attr("transform", "translate(0,0)").remove();
 	}
 
+	if (settings.has_labels_changed) {
+	    var label_export = d3.select("#scatterD3-menu-" + settings.html_id)
+		.select(".label-export");
+	    label_export.style("display", settings.has_labels ? "block" : "none");
+	}
+
 	if (settings.legend_changed) {
 	    var legend = svg.select(".legend");
 	    dims = setup_legend_sizes(dims, scales, settings);
@@ -542,7 +601,17 @@ function scatterD3() {
             svg.select(".gear-menu")
 		.attr("transform", "translate(" + (width - 40) + "," + 10 + ")");
         }
+        // Move caption icon and div
+        if (settings.caption) {
+	    var caption_top_margin = settings.menu ? 35 : 10;
+            svg.select(".caption-icon")
+	    	.attr("transform", "translate(" + (dims.svg_width - 40) + "," + caption_top_margin + ")");
+	    d3.select(svg.node().parentNode)
+		.select(".scatterD3-caption")
+		.style("top", dims.svg_height + "px");
+        }
 
+	
     };
 
 
@@ -667,6 +736,13 @@ HTMLWidgets.widget({
 		.attr("class", "scatterD3-tooltip");
         }
 
+	// Create title and subtitle div
+        var caption = d3.select(el).select(".scatterD3-caption");
+        if (caption.empty()) {
+            caption = d3.select(el).append("div")
+		.attr("class", "scatterD3-caption");
+        }
+
         // Create menu div
         var menu = d3.select(el).select(".scatterD3-menu");
         if (menu.empty()) {
@@ -700,11 +776,15 @@ HTMLWidgets.widget({
 
 		// convert data to d3 format
 		var data = HTMLWidgets.dataframeToD3(obj.data);
+		if (obj.settings.labels_positions) {
+		    obj.settings.labels_positions = HTMLWidgets.dataframeToD3(obj.settings.labels_positions);
+		}
 
 		// If no transitions, remove chart and redraw it
 		if (!obj.settings.transitions) {
                     svg.selectAll("*:not(style)").remove();
 		    menu.selectAll("li").remove();
+		    caption.selectAll("*").remove();
 		}
 
 		// Complete draw
@@ -732,6 +812,8 @@ HTMLWidgets.widget({
                     obj.settings.size_range_changed = !array_equal(scatter.settings().size_range, obj.settings.size_range);
                     obj.settings.ellipses_changed = scatter.settings().ellipses != obj.settings.ellipses;
 		    obj.settings.colors_changed = scatter.settings().colors != obj.settings.colors;
+		    obj.settings.x_log_changed = scatter.settings().x_log != obj.settings.x_log;
+		    obj.settings.y_log_changed = scatter.settings().y_log != obj.settings.y_log;
 
 		    obj.settings.had_color_var = scatter.settings().has_color_var;
 		    obj.settings.had_symbol_var = scatter.settings().has_symbol_var;
@@ -758,6 +840,8 @@ HTMLWidgets.widget({
 			obj.settings.has_labels_changed ||
 			changed("ellipses_data") ||
 			obj.settings.ellipses_changed ||
+			obj.settings.x_log_changed ||
+			obj.settings.y_log_changed ||
 			changed("opacity_var") ||
 			changed("lines");
 
diff --git a/man/scatterD3.Rd b/man/scatterD3.Rd
index 15345c6..285540e 100644
--- a/man/scatterD3.Rd
+++ b/man/scatterD3.Rd
@@ -7,23 +7,24 @@
 D3.js was created by Michael Bostock. See \url{http://d3js.org/}
 }
 \usage{
-scatterD3(x, y, data = NULL, lab = NULL, point_size = 64,
-  labels_size = 10, point_opacity = 1, hover_size = 1,
-  hover_opacity = NULL, fixed = FALSE, col_var = NULL,
-  col_continuous = NULL, colors = NULL, ellipses = FALSE,
-  ellipses_level = 0.95, symbol_var = NULL, size_var = NULL,
-  size_range = c(10, 300), col_lab = NULL, symbol_lab = NULL,
-  size_lab = NULL, key_var = NULL, type_var = NULL, opacity_var = NULL,
-  unit_circle = FALSE, url_var = NULL, tooltips = TRUE,
-  tooltip_text = NULL, xlab = NULL, ylab = NULL, html_id = NULL,
-  width = NULL, height = NULL, legend_width = 150, left_margin = 30,
-  xlim = NULL, ylim = NULL, dom_id_reset_zoom = "scatterD3-reset-zoom",
+scatterD3(x, y, data = NULL, lab = NULL, x_log = FALSE, y_log = FALSE,
+  point_size = 64, labels_size = 10, labels_positions = NULL,
+  point_opacity = 1, hover_size = 1, hover_opacity = NULL,
+  fixed = FALSE, col_var = NULL, col_continuous = NULL, colors = NULL,
+  ellipses = FALSE, ellipses_level = 0.95, symbol_var = NULL,
+  size_var = NULL, size_range = c(10, 300), col_lab = NULL,
+  symbol_lab = NULL, size_lab = NULL, key_var = NULL, type_var = NULL,
+  opacity_var = NULL, unit_circle = FALSE, url_var = NULL,
+  tooltips = TRUE, tooltip_text = NULL, xlab = NULL, ylab = NULL,
+  html_id = NULL, width = NULL, height = NULL, legend_width = 150,
+  left_margin = 30, xlim = NULL, ylim = NULL,
+  dom_id_reset_zoom = "scatterD3-reset-zoom",
   dom_id_svg_export = "scatterD3-svg-export",
   dom_id_lasso_toggle = "scatterD3-lasso-toggle", transitions = FALSE,
   menu = TRUE, lasso = FALSE, lasso_callback = NULL,
   click_callback = NULL, zoom_callback = NULL, lines = data.frame(slope =
   c(0, Inf), intercept = c(0, 0), stroke_dasharray = c(5, 5)),
-  axes_font_size = "100\%", legend_font_size = "100\%")
+  axes_font_size = "100\%", legend_font_size = "100\%", caption = NULL)
 }
 \arguments{
 \item{x}{numerical vector of x values, or variable name if data is not NULL}
@@ -35,10 +36,18 @@ scatterD3(x, y, data = NULL, lab = NULL, point_size = 64,
 \item{lab}{optional character vector of text labels, or variable name if
 data is not NULL}
 
+\item{x_log}{if TRUE, set x scale as logarithmic}
+
+\item{y_log}{if TRUE, set y scale as logarithmic}
+
 \item{point_size}{points size. Ignored if size_var is not NULL.}
 
 \item{labels_size}{text labels size}
 
+\item{labels_positions}{A data frame, as created by the
+"Export labels positions" menu entry, giving each label x and y
+position.}
+
 \item{point_opacity}{points opacity, as an integer (same opacity for all
 points) or a vector of integers, or variable name if data is not NULL}
 
@@ -156,6 +165,10 @@ and \code{stroke_dasharray} columns. To draw a vertical line, pass
 
 \item{legend_font_size}{font size for legend text (any CSS compatible
 value)}
+
+\item{caption}{caption to be displayed when clicking on the corresponding
+icon. Either a character string, or a list with title, subtitle and
+text elements.}
 }
 \description{
 Generates an interactive scatter plot based on d3.js.
diff --git a/vignettes/introduction.Rmd b/vignettes/introduction.Rmd
index 5354a6d..a1aa254 100644
--- a/vignettes/introduction.Rmd
+++ b/vignettes/introduction.Rmd
@@ -169,7 +169,16 @@ scatterD3(data = mtcars, x = wt, y = mpg, fixed = TRUE,
 ```
 
 
-## Axis limits
+## Scales, axes and legend
+
+The `x_log` and `y_log` arguments allow to use logarithmic scales on the `x`
+and `y` values. Note that there must not be any value inferior or equal to
+zero in this case :
+
+```{r log_scales}
+scatterD3(data = mtcars, x = wt, y = mpg, col_var = cyl,
+          x_log = TRUE, y_log = TRUE)
+```
 
 You can manually specify the `x` or `y` axis limits with the `xlim` and `ylim` arguments :
 
@@ -177,9 +186,6 @@ You can manually specify the `x` or `y` axis limits with the `xlim` and `ylim` a
 scatterD3(data = mtcars, x = wt, y = mpg, xlim=c(0,10), ylim=c(10,35))
 ```
 
-
-## Axes and legend customization
-
 You can customize the value of the axes and legend labels with `xlab`, `ylab`, `col_lab`, `symbol_lab` and `size_lab` :
 
 ```{r cust_labels}
@@ -200,6 +206,36 @@ scatterD3(data = mtcars, x = wt, y = mpg, col_var = cyl,
 
 You can provide any CSS compatible value, wether a fixed size such as `2em` or a relative one like `95%`.
 
+If the left plot margin is not big enough and your y axis labels are
+truncated, you can adjust it with the `left_margin` argument :
+
+```{r cust_left_margin}
+scatterD3(data = mtcars, x = wt, y = mpg, col_var = cyl,
+          left_margin = 80)
+```
+
+## Caption
+
+You can add an optional caption to your plot, which will be shown when
+clicking on a "info sign" icon in the top right of your plot.
+
+To do so, use the `caption` argument with either a single character string :
+
+```{r caption_character}
+scatterD3(data = mtcars, x = wt, y = mpg, col_var = cyl,
+          caption = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam aliquam egestas pretium. Donec auctor semper vestibulum. Phasellus in tempor lacus. Maecenas vehicula, ipsum id malesuada placerat, diam lorem aliquet lectus, non lacinia quam leo quis eros.")
+```
+
+Or a list with the `title`, `subtitle` and `text` elements :
+
+```{r caption_list}
+scatterD3(data = mtcars, x = wt, y = mpg, col_var = cyl,
+          caption = list(title = "Caption title",
+                         subtitle = "Caption subtitle",
+                         text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam aliquam egestas pretium. Donec auctor semper vestibulum. Phasellus in tempor lacus. Maecenas vehicula, ipsum id malesuada placerat, diam lorem aliquet lectus, non lacinia quam leo quis eros."))
+```
+
+
 
 ## Custom tooltips
 
@@ -286,7 +322,7 @@ Ellipses are computed by the  `ellipse.default()` function of the [ellipse packa
 
 ## Gear menu
 
-The "gear menu" is a small menu which can be displayed by clocking on the "gear" icon on the top-right corner of the plot. It allows to reset the zoom, export the current graph to SVG, and toggle lasso selection.
+The "gear menu" is a small menu which can be displayed by clicking on the "gear" icon on the top-right corner of the plot. It allows to reset the zoom, export the current graph to SVG, and toggle lasso selection.
 
 It is displayed by default, but you can hide it with the `menu = FALSE` argument.
 
@@ -329,7 +365,17 @@ mtcars$names <- rownames(mtcars)
 scatterD3(data = mtcars, x = wt, y = mpg, lab = names)
 ```
 
-You can then open the menu and select *Export labels positions* to save them into a CSV file. If you want to use these positions in another plot, you can do something like that :
+You can then open the menu and select *Export labels positions* to save them
+into a CSV file. If you want to reuse these positions, you can use the
+`labels_positions` argument from `scatterD3` :
+
+```{r labels_export_scatterD3, eval = FALSE}
+labels <- read.csv("scatterD3_labels.csv")
+scatterD3(data = mtcars, x = wt, y = mpg, lab = names, labels_positions = labels)
+```
+
+You can also use this file to reuse coordinates in a plot from a different
+package. The following example should work with `ggplot2` :
 
 ```{r labels_export_ggplot2, eval = FALSE}
 labels <- read.csv("scatterD3_labels.csv")
@@ -337,9 +383,9 @@ library(ggplot2)
 ggplot() +
   geom_point(data = mtcars, aes(x=wt, y=mpg)) +
   geom_text(data = labels,
-            aes(x = scatterD3_label_x,
-                y = scatterD3_label_y,
-                label = scatterD3_label))
+            aes(x = lab_x,
+                y = lab_y,
+                label = lab))
 ```
 
 
@@ -384,3 +430,15 @@ If you are not happy with these ids, you can specify their names yourself with t
 
 The
 [sample scatterD3 shiny app](http://data.nozav.org/app/scatterD3/) allows you to see the different features described here. You can [check its source code on GitHub](https://github.com/juba/scatterD3_shiny_app) for a better understanding of the different arguments.
+
+## Known problems
+
+Due to a lack of support of the `download` attribute in RStudio's interface, two problems may occur when exporting a plot to SVG, or labels positions to CSV :
+
+- the file name suggested in the file save dialog is the data URI. You have to replace it with the name of your choice, and the correct extension (`.svg` or `.csv`).
+
+- when replacing an existing file, if the data to be saved are shorter than the file, it seems that RStudio will just replace the beginning of the file with the new data, but keep existing file content at the end. A workaround is either to always save to a new file, or open the plot in a modern browser before exporting.
+
+
+
+

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/r-cran-scatterd3.git



More information about the debian-med-commit mailing list