diff --git a/package-lock.json b/package-lock.json
index 3571155f851..74b99b51e3c 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,7 +9,6 @@
"version": "2.5.1",
"license": "MIT",
"dependencies": {
- "@plotly/d3": "3.8.0",
"@plotly/d3-sankey": "0.7.2",
"@plotly/d3-sankey-circular": "0.33.1",
"@turf/area": "^6.4.0",
@@ -21,6 +20,7 @@
"color-parse": "1.3.8",
"color-rgba": "2.1.1",
"country-regex": "^1.1.0",
+ "d3": "^4.13.0",
"d3-force": "^1.2.1",
"d3-format": "^1.4.5",
"d3-geo": "^1.12.1",
@@ -367,11 +367,6 @@
"node": ">= 8"
}
},
- "node_modules/@plotly/d3": {
- "version": "3.8.0",
- "resolved": "https://registry.npmjs.org/@plotly/d3/-/d3-3.8.0.tgz",
- "integrity": "sha512-L10iHgzvw3uSic/nQpYehlNzxUQvImwms5U7S95pJAEhrllzkrdQNy1Mc5DW9ab881Yr4fh300gJztKXWZDfkQ=="
- },
"node_modules/@plotly/d3-sankey": {
"version": "0.7.2",
"resolved": "https://registry.npmjs.org/@plotly/d3-sankey/-/d3-sankey-0.7.2.tgz",
@@ -2616,11 +2611,74 @@
"type": "^1.0.1"
}
},
+ "node_modules/d3": {
+ "version": "4.13.0",
+ "resolved": "https://registry.npmjs.org/d3/-/d3-4.13.0.tgz",
+ "integrity": "sha512-l8c4+0SldjVKLaE2WG++EQlqD7mh/dmQjvi2L2lKPadAVC+TbJC4ci7Uk9bRi+To0+ansgsS0iWfPjD7DBy+FQ==",
+ "dependencies": {
+ "d3-array": "1.2.1",
+ "d3-axis": "1.0.8",
+ "d3-brush": "1.0.4",
+ "d3-chord": "1.0.4",
+ "d3-collection": "1.0.4",
+ "d3-color": "1.0.3",
+ "d3-dispatch": "1.0.3",
+ "d3-drag": "1.2.1",
+ "d3-dsv": "1.0.8",
+ "d3-ease": "1.0.3",
+ "d3-force": "1.1.0",
+ "d3-format": "1.2.2",
+ "d3-geo": "1.9.1",
+ "d3-hierarchy": "1.1.5",
+ "d3-interpolate": "1.1.6",
+ "d3-path": "1.0.5",
+ "d3-polygon": "1.0.3",
+ "d3-quadtree": "1.0.3",
+ "d3-queue": "3.0.7",
+ "d3-random": "1.1.0",
+ "d3-request": "1.0.6",
+ "d3-scale": "1.0.7",
+ "d3-selection": "1.3.0",
+ "d3-shape": "1.2.0",
+ "d3-time": "1.0.8",
+ "d3-time-format": "2.1.1",
+ "d3-timer": "1.0.7",
+ "d3-transition": "1.1.1",
+ "d3-voronoi": "1.1.2",
+ "d3-zoom": "1.7.1"
+ }
+ },
"node_modules/d3-array": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.4.tgz",
"integrity": "sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw=="
},
+ "node_modules/d3-axis": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-1.0.8.tgz",
+ "integrity": "sha1-MacFoLU15ldZ3hQXOjGTMTfxjvo="
+ },
+ "node_modules/d3-brush": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-1.0.4.tgz",
+ "integrity": "sha1-AMLyOAGfJPbAoZSibUGhUw/+e8Q=",
+ "dependencies": {
+ "d3-dispatch": "1",
+ "d3-drag": "1",
+ "d3-interpolate": "1",
+ "d3-selection": "1",
+ "d3-transition": "1"
+ }
+ },
+ "node_modules/d3-chord": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-1.0.4.tgz",
+ "integrity": "sha1-fexPC6iG9xP+ERxF92NBT290yiw=",
+ "dependencies": {
+ "d3-array": "1",
+ "d3-path": "1"
+ }
+ },
"node_modules/d3-collection": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/d3-collection/-/d3-collection-1.0.7.tgz",
@@ -2636,6 +2694,41 @@
"resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-1.0.6.tgz",
"integrity": "sha512-fVjoElzjhCEy+Hbn8KygnmMS7Or0a9sI2UzGwoB7cCtvI1XpVN9GpoYlnb3xt2YV66oXYb1fLJ8GMvP4hdU1RA=="
},
+ "node_modules/d3-drag": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-1.2.1.tgz",
+ "integrity": "sha512-Cg8/K2rTtzxzrb0fmnYOUeZHvwa4PHzwXOLZZPwtEs2SKLLKLXeYwZKBB+DlOxUvFmarOnmt//cU4+3US2lyyQ==",
+ "dependencies": {
+ "d3-dispatch": "1",
+ "d3-selection": "1"
+ }
+ },
+ "node_modules/d3-dsv": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-1.0.8.tgz",
+ "integrity": "sha512-IVCJpQ+YGe3qu6odkPQI0KPqfxkhbP/oM1XhhE/DFiYmcXKfCRub4KXyiuehV1d4drjWVXHUWx4gHqhdZb6n/A==",
+ "dependencies": {
+ "commander": "2",
+ "iconv-lite": "0.4",
+ "rw": "1"
+ },
+ "bin": {
+ "csv2json": "bin/dsv2json",
+ "csv2tsv": "bin/dsv2dsv",
+ "dsv2dsv": "bin/dsv2dsv",
+ "dsv2json": "bin/dsv2json",
+ "json2csv": "bin/json2dsv",
+ "json2dsv": "bin/json2dsv",
+ "json2tsv": "bin/json2dsv",
+ "tsv2csv": "bin/dsv2dsv",
+ "tsv2json": "bin/dsv2json"
+ }
+ },
+ "node_modules/d3-ease": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-1.0.3.tgz",
+ "integrity": "sha1-aL+8NJM4o4DETYrMT7wzBKotjA4="
+ },
"node_modules/d3-force": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/d3-force/-/d3-force-1.2.1.tgz",
@@ -2696,11 +2789,56 @@
"resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz",
"integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg=="
},
+ "node_modules/d3-polygon": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-1.0.3.tgz",
+ "integrity": "sha1-FoiOkCZGCTPysXllKtN4Ik04LGI="
+ },
"node_modules/d3-quadtree": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-1.0.7.tgz",
"integrity": "sha512-RKPAeXnkC59IDGD0Wu5mANy0Q2V28L+fNe65pOCXVdVuTJS3WPKaJlFHer32Rbh9gIo9qMuJXio8ra4+YmIymA=="
},
+ "node_modules/d3-queue": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/d3-queue/-/d3-queue-3.0.7.tgz",
+ "integrity": "sha1-yTouVLQXwJWRKdfXP2z31Ckudhg="
+ },
+ "node_modules/d3-random": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-1.1.0.tgz",
+ "integrity": "sha1-ZkLlBsb6OmSFldKyRpeIqNElKdM="
+ },
+ "node_modules/d3-request": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/d3-request/-/d3-request-1.0.6.tgz",
+ "integrity": "sha512-FJj8ySY6GYuAJHZMaCQ83xEYE4KbkPkmxZ3Hu6zA1xxG2GD+z6P+Lyp+zjdsHf0xEbp2xcluDI50rCS855EQ6w==",
+ "dependencies": {
+ "d3-collection": "1",
+ "d3-dispatch": "1",
+ "d3-dsv": "1",
+ "xmlhttprequest": "1"
+ }
+ },
+ "node_modules/d3-scale": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-1.0.7.tgz",
+ "integrity": "sha512-KvU92czp2/qse5tUfGms6Kjig0AhHOwkzXG0+PqIJB3ke0WUv088AHMZI0OssO9NCkXt4RP8yju9rpH8aGB7Lw==",
+ "dependencies": {
+ "d3-array": "^1.2.0",
+ "d3-collection": "1",
+ "d3-color": "1",
+ "d3-format": "1",
+ "d3-interpolate": "1",
+ "d3-time": "1",
+ "d3-time-format": "2"
+ }
+ },
+ "node_modules/d3-selection": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-1.3.0.tgz",
+ "integrity": "sha512-qgpUOg9tl5CirdqESUAu0t9MU/t3O9klYfGfyKsXEmhyxyzLpzpeh08gaxBUTQw1uXIOkr/30Ut2YRjSSxlmHA=="
+ },
"node_modules/d3-shape": {
"version": "1.3.7",
"resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz",
@@ -2732,6 +2870,129 @@
"resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-1.0.10.tgz",
"integrity": "sha512-B1JDm0XDaQC+uvo4DT79H0XmBskgS3l6Ve+1SBCfxgmtIb1AVrPIoqd+nPSv+loMX8szQ0sVUhGngL7D5QPiXw=="
},
+ "node_modules/d3-transition": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-1.1.1.tgz",
+ "integrity": "sha512-xeg8oggyQ+y5eb4J13iDgKIjUcEfIOZs2BqV/eEmXm2twx80wTzJ4tB4vaZ5BKfz7XsI/DFmQL5me6O27/5ykQ==",
+ "dependencies": {
+ "d3-color": "1",
+ "d3-dispatch": "1",
+ "d3-ease": "1",
+ "d3-interpolate": "1",
+ "d3-selection": "^1.1.0",
+ "d3-timer": "1"
+ }
+ },
+ "node_modules/d3-voronoi": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/d3-voronoi/-/d3-voronoi-1.1.2.tgz",
+ "integrity": "sha1-Fodmfo8TotFYyAwUgMWinLDYlzw="
+ },
+ "node_modules/d3-zoom": {
+ "version": "1.7.1",
+ "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-1.7.1.tgz",
+ "integrity": "sha512-sZHQ55DGq5BZBFGnRshUT8tm2sfhPHFnOlmPbbwTkAoPeVdRTkB4Xsf9GCY0TSHrTD8PeJPZGmP/TpGicwJDJQ==",
+ "dependencies": {
+ "d3-dispatch": "1",
+ "d3-drag": "1",
+ "d3-interpolate": "1",
+ "d3-selection": "1",
+ "d3-transition": "1"
+ }
+ },
+ "node_modules/d3/node_modules/d3-array": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.1.tgz",
+ "integrity": "sha512-CyINJQ0SOUHojDdFDH4JEM0552vCR1utGyLHegJHyYH0JyCpSeTPxi4OBqHMA2jJZq4NH782LtaJWBImqI/HBw=="
+ },
+ "node_modules/d3/node_modules/d3-collection": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/d3-collection/-/d3-collection-1.0.4.tgz",
+ "integrity": "sha1-NC39EoN8kJdPM/HMCnha6lcNzcI="
+ },
+ "node_modules/d3/node_modules/d3-color": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-1.0.3.tgz",
+ "integrity": "sha1-vHZD/KjlOoNH4vva/6I2eWtYUJs="
+ },
+ "node_modules/d3/node_modules/d3-dispatch": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-1.0.3.tgz",
+ "integrity": "sha1-RuFJHqqbWMNY/OW+TovtYm54cfg="
+ },
+ "node_modules/d3/node_modules/d3-force": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-1.1.0.tgz",
+ "integrity": "sha512-2HVQz3/VCQs0QeRNZTYb7GxoUCeb6bOzMp/cGcLa87awY9ZsPvXOGeZm0iaGBjXic6I1ysKwMn+g+5jSAdzwcg==",
+ "dependencies": {
+ "d3-collection": "1",
+ "d3-dispatch": "1",
+ "d3-quadtree": "1",
+ "d3-timer": "1"
+ }
+ },
+ "node_modules/d3/node_modules/d3-format": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-1.2.2.tgz",
+ "integrity": "sha512-zH9CfF/3C8zUI47nsiKfD0+AGDEuM8LwBIP7pBVpyR4l/sKkZqITmMtxRp04rwBrlshIZ17XeFAaovN3++wzkw=="
+ },
+ "node_modules/d3/node_modules/d3-geo": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-1.9.1.tgz",
+ "integrity": "sha512-l9wL/cEQkyZQYXw3xbmLsH3eQ5ij+icNfo4r0GrLa5rOCZR/e/3am45IQ0FvQ5uMsv+77zBRunLc9ufTWSQYFA==",
+ "dependencies": {
+ "d3-array": "1"
+ }
+ },
+ "node_modules/d3/node_modules/d3-hierarchy": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-1.1.5.tgz",
+ "integrity": "sha1-ochFxC+Eoga88cAcAQmOpN2qeiY="
+ },
+ "node_modules/d3/node_modules/d3-interpolate": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-1.1.6.tgz",
+ "integrity": "sha512-mOnv5a+pZzkNIHtw/V6I+w9Lqm9L5bG3OTXPM5A+QO0yyVMQ4W1uZhR+VOJmazaOZXri2ppbiZ5BUNWT0pFM9A==",
+ "dependencies": {
+ "d3-color": "1"
+ }
+ },
+ "node_modules/d3/node_modules/d3-path": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.5.tgz",
+ "integrity": "sha1-JB6xhJvZ6egCHA0KeZ+KDo5EF2Q="
+ },
+ "node_modules/d3/node_modules/d3-quadtree": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-1.0.3.tgz",
+ "integrity": "sha1-rHmH4+I/6AWpkPKOG1DTj8uCJDg="
+ },
+ "node_modules/d3/node_modules/d3-shape": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.2.0.tgz",
+ "integrity": "sha1-RdAVOPBkuv0F6j1tLLdI/YxB93c=",
+ "dependencies": {
+ "d3-path": "1"
+ }
+ },
+ "node_modules/d3/node_modules/d3-time": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-1.0.8.tgz",
+ "integrity": "sha512-YRZkNhphZh3KcnBfitvF3c6E0JOFGikHZ4YqD+Lzv83ZHn1/u6yGenRU1m+KAk9J1GnZMnKcrtfvSktlA1DXNQ=="
+ },
+ "node_modules/d3/node_modules/d3-time-format": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-2.1.1.tgz",
+ "integrity": "sha512-8kAkymq2WMfzW7e+s/IUNAtN/y3gZXGRrdGfo6R8NKPAA85UBTxZg5E61bR6nLwjPjj4d3zywSQe1CkYLPFyrw==",
+ "dependencies": {
+ "d3-time": "1"
+ }
+ },
+ "node_modules/d3/node_modules/d3-timer": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-1.0.7.tgz",
+ "integrity": "sha512-vMZXR88XujmG/L5oB96NNKH5lCWwiLM/S2HyyAQLcjWJCloK5shxta4CwOFYLZoY3AWX73v8Lgv4cCAdWtRmOA=="
+ },
"node_modules/dash-ast": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/dash-ast/-/dash-ast-1.0.0.tgz",
@@ -7290,6 +7551,11 @@
"to-px": "^1.0.1"
}
},
+ "node_modules/mouse-wheel/node_modules/signum": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/signum/-/signum-1.0.0.tgz",
+ "integrity": "sha1-dKfSvyogtA66FqkrFSEk8dVZ+nc="
+ },
"node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
@@ -8993,11 +9259,6 @@
"integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==",
"dev": true
},
- "node_modules/signum": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/signum/-/signum-1.0.0.tgz",
- "integrity": "sha1-dKfSvyogtA66FqkrFSEk8dVZ+nc="
- },
"node_modules/simple-concat": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
@@ -9839,9 +10100,9 @@
"integrity": "sha512-keDnAusn/vc+R3iEiSDw8TOF7gPiTLdK1ArvWtYbJQiVfmRg6i/CAvbKq3uIS0vWroAC7ZecN3DjQKw3aSklUg=="
},
"node_modules/to-px": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/to-px/-/to-px-1.1.0.tgz",
- "integrity": "sha512-bfg3GLYrGoEzrGoE05TAL/Uw+H/qrf2ptr9V3W7U0lkjjyYnIfgxmVLUfhQ1hZpIQwin81uxhDjvUkDYsC0xWw==",
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/to-px/-/to-px-1.0.1.tgz",
+ "integrity": "sha1-W7rtXl1PdkRbzJA8KTojB90yRkY=",
"dependencies": {
"parse-unit": "^1.0.1"
}
@@ -10754,6 +11015,14 @@
"integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==",
"dev": true
},
+ "node_modules/xmlhttprequest": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz",
+ "integrity": "sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw=",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
"node_modules/xtend": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
@@ -11047,11 +11316,6 @@
"fastq": "^1.6.0"
}
},
- "@plotly/d3": {
- "version": "3.8.0",
- "resolved": "https://registry.npmjs.org/@plotly/d3/-/d3-3.8.0.tgz",
- "integrity": "sha512-L10iHgzvw3uSic/nQpYehlNzxUQvImwms5U7S95pJAEhrllzkrdQNy1Mc5DW9ab881Yr4fh300gJztKXWZDfkQ=="
- },
"@plotly/d3-sankey": {
"version": "0.7.2",
"resolved": "https://registry.npmjs.org/@plotly/d3-sankey/-/d3-sankey-0.7.2.tgz",
@@ -13057,11 +13321,169 @@
"type": "^1.0.1"
}
},
+ "d3": {
+ "version": "4.13.0",
+ "resolved": "https://registry.npmjs.org/d3/-/d3-4.13.0.tgz",
+ "integrity": "sha512-l8c4+0SldjVKLaE2WG++EQlqD7mh/dmQjvi2L2lKPadAVC+TbJC4ci7Uk9bRi+To0+ansgsS0iWfPjD7DBy+FQ==",
+ "requires": {
+ "d3-array": "1.2.1",
+ "d3-axis": "1.0.8",
+ "d3-brush": "1.0.4",
+ "d3-chord": "1.0.4",
+ "d3-collection": "1.0.4",
+ "d3-color": "1.0.3",
+ "d3-dispatch": "1.0.3",
+ "d3-drag": "1.2.1",
+ "d3-dsv": "1.0.8",
+ "d3-ease": "1.0.3",
+ "d3-force": "1.1.0",
+ "d3-format": "1.2.2",
+ "d3-geo": "1.9.1",
+ "d3-hierarchy": "1.1.5",
+ "d3-interpolate": "1.1.6",
+ "d3-path": "1.0.5",
+ "d3-polygon": "1.0.3",
+ "d3-quadtree": "1.0.3",
+ "d3-queue": "3.0.7",
+ "d3-random": "1.1.0",
+ "d3-request": "1.0.6",
+ "d3-scale": "1.0.7",
+ "d3-selection": "1.3.0",
+ "d3-shape": "1.2.0",
+ "d3-time": "1.0.8",
+ "d3-time-format": "2.1.1",
+ "d3-timer": "1.0.7",
+ "d3-transition": "1.1.1",
+ "d3-voronoi": "1.1.2",
+ "d3-zoom": "1.7.1"
+ },
+ "dependencies": {
+ "d3-array": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.1.tgz",
+ "integrity": "sha512-CyINJQ0SOUHojDdFDH4JEM0552vCR1utGyLHegJHyYH0JyCpSeTPxi4OBqHMA2jJZq4NH782LtaJWBImqI/HBw=="
+ },
+ "d3-collection": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/d3-collection/-/d3-collection-1.0.4.tgz",
+ "integrity": "sha1-NC39EoN8kJdPM/HMCnha6lcNzcI="
+ },
+ "d3-color": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-1.0.3.tgz",
+ "integrity": "sha1-vHZD/KjlOoNH4vva/6I2eWtYUJs="
+ },
+ "d3-dispatch": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-1.0.3.tgz",
+ "integrity": "sha1-RuFJHqqbWMNY/OW+TovtYm54cfg="
+ },
+ "d3-force": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-1.1.0.tgz",
+ "integrity": "sha512-2HVQz3/VCQs0QeRNZTYb7GxoUCeb6bOzMp/cGcLa87awY9ZsPvXOGeZm0iaGBjXic6I1ysKwMn+g+5jSAdzwcg==",
+ "requires": {
+ "d3-collection": "1",
+ "d3-dispatch": "1",
+ "d3-quadtree": "1",
+ "d3-timer": "1"
+ }
+ },
+ "d3-format": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-1.2.2.tgz",
+ "integrity": "sha512-zH9CfF/3C8zUI47nsiKfD0+AGDEuM8LwBIP7pBVpyR4l/sKkZqITmMtxRp04rwBrlshIZ17XeFAaovN3++wzkw=="
+ },
+ "d3-geo": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-1.9.1.tgz",
+ "integrity": "sha512-l9wL/cEQkyZQYXw3xbmLsH3eQ5ij+icNfo4r0GrLa5rOCZR/e/3am45IQ0FvQ5uMsv+77zBRunLc9ufTWSQYFA==",
+ "requires": {
+ "d3-array": "1"
+ }
+ },
+ "d3-hierarchy": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-1.1.5.tgz",
+ "integrity": "sha1-ochFxC+Eoga88cAcAQmOpN2qeiY="
+ },
+ "d3-interpolate": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-1.1.6.tgz",
+ "integrity": "sha512-mOnv5a+pZzkNIHtw/V6I+w9Lqm9L5bG3OTXPM5A+QO0yyVMQ4W1uZhR+VOJmazaOZXri2ppbiZ5BUNWT0pFM9A==",
+ "requires": {
+ "d3-color": "1"
+ }
+ },
+ "d3-path": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.5.tgz",
+ "integrity": "sha1-JB6xhJvZ6egCHA0KeZ+KDo5EF2Q="
+ },
+ "d3-quadtree": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-1.0.3.tgz",
+ "integrity": "sha1-rHmH4+I/6AWpkPKOG1DTj8uCJDg="
+ },
+ "d3-shape": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.2.0.tgz",
+ "integrity": "sha1-RdAVOPBkuv0F6j1tLLdI/YxB93c=",
+ "requires": {
+ "d3-path": "1"
+ }
+ },
+ "d3-time": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-1.0.8.tgz",
+ "integrity": "sha512-YRZkNhphZh3KcnBfitvF3c6E0JOFGikHZ4YqD+Lzv83ZHn1/u6yGenRU1m+KAk9J1GnZMnKcrtfvSktlA1DXNQ=="
+ },
+ "d3-time-format": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-2.1.1.tgz",
+ "integrity": "sha512-8kAkymq2WMfzW7e+s/IUNAtN/y3gZXGRrdGfo6R8NKPAA85UBTxZg5E61bR6nLwjPjj4d3zywSQe1CkYLPFyrw==",
+ "requires": {
+ "d3-time": "1"
+ }
+ },
+ "d3-timer": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-1.0.7.tgz",
+ "integrity": "sha512-vMZXR88XujmG/L5oB96NNKH5lCWwiLM/S2HyyAQLcjWJCloK5shxta4CwOFYLZoY3AWX73v8Lgv4cCAdWtRmOA=="
+ }
+ }
+ },
"d3-array": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.4.tgz",
"integrity": "sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw=="
},
+ "d3-axis": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-1.0.8.tgz",
+ "integrity": "sha1-MacFoLU15ldZ3hQXOjGTMTfxjvo="
+ },
+ "d3-brush": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-1.0.4.tgz",
+ "integrity": "sha1-AMLyOAGfJPbAoZSibUGhUw/+e8Q=",
+ "requires": {
+ "d3-dispatch": "1",
+ "d3-drag": "1",
+ "d3-interpolate": "1",
+ "d3-selection": "1",
+ "d3-transition": "1"
+ }
+ },
+ "d3-chord": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-1.0.4.tgz",
+ "integrity": "sha1-fexPC6iG9xP+ERxF92NBT290yiw=",
+ "requires": {
+ "d3-array": "1",
+ "d3-path": "1"
+ }
+ },
"d3-collection": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/d3-collection/-/d3-collection-1.0.7.tgz",
@@ -13077,6 +13499,30 @@
"resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-1.0.6.tgz",
"integrity": "sha512-fVjoElzjhCEy+Hbn8KygnmMS7Or0a9sI2UzGwoB7cCtvI1XpVN9GpoYlnb3xt2YV66oXYb1fLJ8GMvP4hdU1RA=="
},
+ "d3-drag": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-1.2.1.tgz",
+ "integrity": "sha512-Cg8/K2rTtzxzrb0fmnYOUeZHvwa4PHzwXOLZZPwtEs2SKLLKLXeYwZKBB+DlOxUvFmarOnmt//cU4+3US2lyyQ==",
+ "requires": {
+ "d3-dispatch": "1",
+ "d3-selection": "1"
+ }
+ },
+ "d3-dsv": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-1.0.8.tgz",
+ "integrity": "sha512-IVCJpQ+YGe3qu6odkPQI0KPqfxkhbP/oM1XhhE/DFiYmcXKfCRub4KXyiuehV1d4drjWVXHUWx4gHqhdZb6n/A==",
+ "requires": {
+ "commander": "2",
+ "iconv-lite": "0.4",
+ "rw": "1"
+ }
+ },
+ "d3-ease": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-1.0.3.tgz",
+ "integrity": "sha1-aL+8NJM4o4DETYrMT7wzBKotjA4="
+ },
"d3-force": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/d3-force/-/d3-force-1.2.1.tgz",
@@ -13130,11 +13576,56 @@
"resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz",
"integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg=="
},
+ "d3-polygon": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-1.0.3.tgz",
+ "integrity": "sha1-FoiOkCZGCTPysXllKtN4Ik04LGI="
+ },
"d3-quadtree": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-1.0.7.tgz",
"integrity": "sha512-RKPAeXnkC59IDGD0Wu5mANy0Q2V28L+fNe65pOCXVdVuTJS3WPKaJlFHer32Rbh9gIo9qMuJXio8ra4+YmIymA=="
},
+ "d3-queue": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/d3-queue/-/d3-queue-3.0.7.tgz",
+ "integrity": "sha1-yTouVLQXwJWRKdfXP2z31Ckudhg="
+ },
+ "d3-random": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-1.1.0.tgz",
+ "integrity": "sha1-ZkLlBsb6OmSFldKyRpeIqNElKdM="
+ },
+ "d3-request": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/d3-request/-/d3-request-1.0.6.tgz",
+ "integrity": "sha512-FJj8ySY6GYuAJHZMaCQ83xEYE4KbkPkmxZ3Hu6zA1xxG2GD+z6P+Lyp+zjdsHf0xEbp2xcluDI50rCS855EQ6w==",
+ "requires": {
+ "d3-collection": "1",
+ "d3-dispatch": "1",
+ "d3-dsv": "1",
+ "xmlhttprequest": "1"
+ }
+ },
+ "d3-scale": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-1.0.7.tgz",
+ "integrity": "sha512-KvU92czp2/qse5tUfGms6Kjig0AhHOwkzXG0+PqIJB3ke0WUv088AHMZI0OssO9NCkXt4RP8yju9rpH8aGB7Lw==",
+ "requires": {
+ "d3-array": "^1.2.0",
+ "d3-collection": "1",
+ "d3-color": "1",
+ "d3-format": "1",
+ "d3-interpolate": "1",
+ "d3-time": "1",
+ "d3-time-format": "2"
+ }
+ },
+ "d3-selection": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-1.3.0.tgz",
+ "integrity": "sha512-qgpUOg9tl5CirdqESUAu0t9MU/t3O9klYfGfyKsXEmhyxyzLpzpeh08gaxBUTQw1uXIOkr/30Ut2YRjSSxlmHA=="
+ },
"d3-shape": {
"version": "1.3.7",
"resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz",
@@ -13168,6 +13659,36 @@
"resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-1.0.10.tgz",
"integrity": "sha512-B1JDm0XDaQC+uvo4DT79H0XmBskgS3l6Ve+1SBCfxgmtIb1AVrPIoqd+nPSv+loMX8szQ0sVUhGngL7D5QPiXw=="
},
+ "d3-transition": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-1.1.1.tgz",
+ "integrity": "sha512-xeg8oggyQ+y5eb4J13iDgKIjUcEfIOZs2BqV/eEmXm2twx80wTzJ4tB4vaZ5BKfz7XsI/DFmQL5me6O27/5ykQ==",
+ "requires": {
+ "d3-color": "1",
+ "d3-dispatch": "1",
+ "d3-ease": "1",
+ "d3-interpolate": "1",
+ "d3-selection": "^1.1.0",
+ "d3-timer": "1"
+ }
+ },
+ "d3-voronoi": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/d3-voronoi/-/d3-voronoi-1.1.2.tgz",
+ "integrity": "sha1-Fodmfo8TotFYyAwUgMWinLDYlzw="
+ },
+ "d3-zoom": {
+ "version": "1.7.1",
+ "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-1.7.1.tgz",
+ "integrity": "sha512-sZHQ55DGq5BZBFGnRshUT8tm2sfhPHFnOlmPbbwTkAoPeVdRTkB4Xsf9GCY0TSHrTD8PeJPZGmP/TpGicwJDJQ==",
+ "requires": {
+ "d3-dispatch": "1",
+ "d3-drag": "1",
+ "d3-interpolate": "1",
+ "d3-selection": "1",
+ "d3-transition": "1"
+ }
+ },
"dash-ast": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/dash-ast/-/dash-ast-1.0.0.tgz",
@@ -16867,6 +17388,13 @@
"right-now": "^1.0.0",
"signum": "^1.0.0",
"to-px": "^1.0.1"
+ },
+ "dependencies": {
+ "signum": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/signum/-/signum-1.0.0.tgz",
+ "integrity": "sha1-dKfSvyogtA66FqkrFSEk8dVZ+nc="
+ }
}
},
"ms": {
@@ -18220,11 +18748,6 @@
"integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==",
"dev": true
},
- "signum": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/signum/-/signum-1.0.0.tgz",
- "integrity": "sha1-dKfSvyogtA66FqkrFSEk8dVZ+nc="
- },
"simple-concat": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
@@ -18948,9 +19471,9 @@
"integrity": "sha512-keDnAusn/vc+R3iEiSDw8TOF7gPiTLdK1ArvWtYbJQiVfmRg6i/CAvbKq3uIS0vWroAC7ZecN3DjQKw3aSklUg=="
},
"to-px": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/to-px/-/to-px-1.1.0.tgz",
- "integrity": "sha512-bfg3GLYrGoEzrGoE05TAL/Uw+H/qrf2ptr9V3W7U0lkjjyYnIfgxmVLUfhQ1hZpIQwin81uxhDjvUkDYsC0xWw==",
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/to-px/-/to-px-1.0.1.tgz",
+ "integrity": "sha1-W7rtXl1PdkRbzJA8KTojB90yRkY=",
"requires": {
"parse-unit": "^1.0.1"
}
@@ -19687,6 +20210,11 @@
"integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==",
"dev": true
},
+ "xmlhttprequest": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz",
+ "integrity": "sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw="
+ },
"xtend": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
diff --git a/package.json b/package.json
index 86353c8b461..98155bdb255 100644
--- a/package.json
+++ b/package.json
@@ -69,7 +69,6 @@
]
},
"dependencies": {
- "@plotly/d3": "3.8.0",
"@plotly/d3-sankey": "0.7.2",
"@plotly/d3-sankey-circular": "0.33.1",
"@turf/area": "^6.4.0",
@@ -81,6 +80,7 @@
"color-parse": "1.3.8",
"color-rgba": "2.1.1",
"country-regex": "^1.1.0",
+ "d3": "^4.13.0",
"d3-force": "^1.2.1",
"d3-format": "^1.4.5",
"d3-geo": "^1.12.1",
diff --git a/src/components/annotations/draw.js b/src/components/annotations/draw.js
index bf1ebf7fbec..4fcc67dc326 100644
--- a/src/components/annotations/draw.js
+++ b/src/components/annotations/draw.js
@@ -1,6 +1,6 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var Registry = require('../../registry');
var Plots = require('../../plots/plots');
@@ -221,13 +221,16 @@ function drawRaw(gd, options, index, subplotId, xa, ya) {
var annTextClip = fullLayout._topclips
.selectAll('#' + annClipID)
- .data(isSizeConstrained ? [0] : []);
+ .data(isSizeConstrained ? [0] : [])
+ .enter()
+ .append('clipPath');
- annTextClip.enter().append('clipPath')
+ annTextClip.exit().remove();
+
+ annTextClip
.classed('annclip', true)
.attr('id', annClipID)
- .append('rect');
- annTextClip.exit().remove();
+ .append('rect');
var font = options.font;
@@ -241,7 +244,7 @@ function drawRaw(gd, options, index, subplotId, xa, ya) {
function textLayout(s) {
s.call(Drawing.font, font)
- .attr({
+ .attrs({
'text-anchor': {
left: 'start',
right: 'end'
@@ -256,11 +259,11 @@ function drawRaw(gd, options, index, subplotId, xa, ya) {
// if the text has *only* a link, make the whole box into a link
var anchor3 = annText.selectAll('a');
if(anchor3.size() === 1 && anchor3.text() === annText.text()) {
- var wholeLink = annTextGroupInner.insert('a', ':first-child').attr({
+ var wholeLink = annTextGroupInner.insert('a', ':first-child').attrs({
'xlink:xlink:href': anchor3.attr('xlink:href'),
'xlink:xlink:show': anchor3.attr('xlink:show')
})
- .style({cursor: 'pointer'});
+ .styles({cursor: 'pointer'});
wholeLink.node().appendChild(annTextBG.node());
}
@@ -453,7 +456,7 @@ function drawRaw(gd, options, index, subplotId, xa, ya) {
}
if(hasMathjax) {
- mathjaxGroup.select('svg').attr({
+ mathjaxGroup.select('svg').attrs({
x: borderfull + xShift - 1,
y: borderfull + yShift
})
@@ -482,7 +485,7 @@ function drawRaw(gd, options, index, subplotId, xa, ya) {
* because we needed that for autoranging anyway, so now whether
* we have an arrow or not, we rotate about the text center.
*/
- annTextGroup.attr({transform: 'rotate(' + textangle + ',' +
+ annTextGroup.attrs({transform: 'rotate(' + textangle + ',' +
annPosPx.x.text + ',' + annPosPx.y.text + ')'});
/*
@@ -550,7 +553,7 @@ function drawRaw(gd, options, index, subplotId, xa, ya) {
var arrowSide = options.arrowside;
var arrowGroup = annGroup.append('g')
- .style({opacity: Color.opacity(arrowColor)})
+ .styles({opacity: Color.opacity(arrowColor)})
.classed('annotation-arrow-g', true);
var arrow = arrowGroup.append('path')
@@ -574,7 +577,7 @@ function drawRaw(gd, options, index, subplotId, xa, ya) {
.classed('annotation-arrow', true)
.classed('anndrag', true)
.classed('cursor-move', true)
- .attr({
+ .attrs({
d: 'M3,3H-3V-3H3ZM0,0L' + (tailX - arrowDragHeadX) + ',' + (tailY - arrowDragHeadY),
transform: strTranslate(arrowDragHeadX, arrowDragHeadY)
})
@@ -624,7 +627,7 @@ function drawRaw(gd, options, index, subplotId, xa, ya) {
}
arrowGroup.attr('transform', strTranslate(dx, dy));
- annTextGroup.attr({
+ annTextGroup.attrs({
transform: 'rotate(' + textangle + ',' +
xcenter + ',' + ycenter + ')'
});
@@ -707,7 +710,7 @@ function drawRaw(gd, options, index, subplotId, xa, ya) {
}
} else return;
- annTextGroup.attr({
+ annTextGroup.attrs({
transform: strTranslate(dx, dy) + baseTextTransform
});
diff --git a/src/components/annotations/draw_arrow_head.js b/src/components/annotations/draw_arrow_head.js
index a1f4ab305ff..c9a082e4b09 100644
--- a/src/components/annotations/draw_arrow_head.js
+++ b/src/components/annotations/draw_arrow_head.js
@@ -1,6 +1,6 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var Color = require('../color');
@@ -70,7 +70,7 @@ module.exports = function drawArrowHead(el3, ends, options) {
end.x += backOffX;
end.y += backOffY;
- el3.attr({x2: end.x, y2: end.y});
+ el3.attrs({x2: end.x, y2: end.y});
}
if(startBackOff) {
@@ -83,7 +83,7 @@ module.exports = function drawArrowHead(el3, ends, options) {
start.x -= startBackOffX;
start.y -= startbackOffY;
- el3.attr({x1: start.x, y1: start.y});
+ el3.attrs({x1: start.x, y1: start.y});
}
} else if(el.nodeName === 'path') {
var pathlen = el.getTotalLength();
@@ -126,7 +126,7 @@ module.exports = function drawArrowHead(el3, ends, options) {
if(arrowHeadStyle.noRotate) rot = 0;
d3.select(el.parentNode).append('path')
- .attr({
+ .attrs({
'class': el3.attr('class'),
d: arrowHeadStyle.path,
transform:
@@ -134,7 +134,7 @@ module.exports = function drawArrowHead(el3, ends, options) {
strRotate(rot * 180 / Math.PI) +
strScale(arrowScale)
})
- .style({
+ .styles({
fill: Color.rgb(options.arrowcolor),
'stroke-width': 0
});
diff --git a/src/components/color/index.js b/src/components/color/index.js
index c10ce0b1d4a..bc3e0835886 100644
--- a/src/components/color/index.js
+++ b/src/components/color/index.js
@@ -75,12 +75,12 @@ color.contrast = function(cstr, lightAmount, darkAmount) {
color.stroke = function(s, c) {
var tc = tinycolor(c);
- s.style({'stroke': color.tinyRGB(tc), 'stroke-opacity': tc.getAlpha()});
+ s.styles({'stroke': color.tinyRGB(tc), 'stroke-opacity': tc.getAlpha()});
};
color.fill = function(s, c) {
var tc = tinycolor(c);
- s.style({
+ s.styles({
'fill': color.tinyRGB(tc),
'fill-opacity': tc.getAlpha()
});
diff --git a/src/components/colorbar/draw.js b/src/components/colorbar/draw.js
index 4bf40d74089..20a3e448050 100644
--- a/src/components/colorbar/draw.js
+++ b/src/components/colorbar/draw.js
@@ -1,6 +1,6 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var tinycolor = require('tinycolor2');
var Plots = require('../../plots/plots');
@@ -8,6 +8,7 @@ var Registry = require('../../registry');
var Axes = require('../../plots/cartesian/axes');
var dragElement = require('../dragelement');
var Lib = require('../../lib');
+var getTraceFromCd = require('../../lib/trace_from_cd');
var strTranslate = Lib.strTranslate;
var extendFlat = require('../../lib/extend').extendFlat;
var setCursor = require('../../lib/setcursor');
@@ -33,12 +34,20 @@ function draw(gd) {
var colorBars = fullLayout._infolayer
.selectAll('g.' + cn.colorbar)
- .data(makeColorBarData(gd), function(opts) { return opts._id; });
+ .data(makeColorBarData(gd), function(opts) { return opts._id; })
+ .enter()
+ .append('g');
- colorBars.enter().append('g')
+ colorBars.exit()
+ .each(function(opts) { Plots.autoMargin(gd, opts._id); })
+ .remove();
+
+ colorBars
.attr('class', function(opts) { return opts._id; })
.classed(cn.colorbar, true);
+ colorBars.order();
+
colorBars.each(function(opts) {
var g = d3.select(this);
@@ -56,12 +65,6 @@ function draw(gd) {
makeEditable(g, opts, gd);
}
});
-
- colorBars.exit()
- .each(function(opts) { Plots.autoMargin(gd, opts._id); })
- .remove();
-
- colorBars.order();
}
function makeColorBarData(gd) {
@@ -116,7 +119,7 @@ function makeColorBarData(gd) {
for(var i = 0; i < calcdata.length; i++) {
var cd = calcdata[i];
- trace = cd[0].trace;
+ trace = getTraceFromCd(cd);
var moduleOpts = trace._module.colorbar;
if(trace.visible === true && moduleOpts) {
@@ -391,11 +394,15 @@ function drawColorBar(g, opts, gd) {
var fills = g.select('.' + cn.cbfills)
.selectAll('rect.' + cn.cbfill)
.attr('style', '')
- .data(fillLevels);
- fills.enter().append('rect')
+ .data(fillLevels)
+ .enter()
+ .append('rect');
+
+ fills.exit().remove();
+
+ fills
.classed(cn.cbfill, true)
.style('stroke', 'none');
- fills.exit().remove();
var zBounds = zrange
.map(ax.c2p)
@@ -417,7 +424,7 @@ function drawColorBar(g, opts, gd) {
// Colorbar cannot currently support opacities so we
// use an opaque fill even when alpha channels present
- var fillEl = d3.select(this).attr({
+ var fillEl = d3.select(this).attrs({
x: xLeft,
width: Math.max(thickPx, 2),
y: d3.min(z),
@@ -436,10 +443,15 @@ function drawColorBar(g, opts, gd) {
var lines = g.select('.' + cn.cblines)
.selectAll('path.' + cn.cbline)
- .data(line.color && line.width ? lineLevels : []);
- lines.enter().append('path')
- .classed(cn.cbline, true);
+ .data(line.color && line.width ? lineLevels : [])
+ .enter()
+ .append('path');
+
lines.exit().remove();
+
+ lines
+ .classed(cn.cbline, true);
+
lines.each(function(d) {
d3.select(this)
.attr('d', 'M' + xLeft + ',' +
@@ -501,7 +513,7 @@ function drawColorBar(g, opts, gd) {
var outerwidth = 2 * opts.xpad + innerWidth + opts.borderwidth + opts.outlinewidth / 2;
var outerheight = yBottomPx - yTopPx;
- g.select('.' + cn.cbbg).attr({
+ g.select('.' + cn.cbbg).attrs({
x: xLeft - opts.xpad - (opts.borderwidth + opts.outlinewidth) / 2,
y: yTopPx - yExtraPx,
width: Math.max(outerwidth, 2),
@@ -511,14 +523,14 @@ function drawColorBar(g, opts, gd) {
.call(Color.stroke, opts.bordercolor)
.style('stroke-width', opts.borderwidth);
- g.selectAll('.' + cn.cboutline).attr({
+ g.selectAll('.' + cn.cboutline).attrs({
x: xLeft,
y: yTopPx + opts.ypad + (titleSide === 'top' ? titleHeight : 0),
width: Math.max(thickPx, 2),
height: Math.max(outerheight - 2 * opts.ypad - titleHeight, 2)
})
.call(Color.stroke, opts.outlinecolor)
- .style({
+ .styles({
fill: 'none',
'stroke-width': opts.outlinewidth
});
diff --git a/src/components/colorscale/helpers.js b/src/components/colorscale/helpers.js
index fed32703b22..b0d93fee31b 100644
--- a/src/components/colorscale/helpers.js
+++ b/src/components/colorscale/helpers.js
@@ -1,6 +1,6 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var tinycolor = require('tinycolor2');
var isNumeric = require('fast-isnumeric');
@@ -169,7 +169,7 @@ function makeColorScaleFunc(specs, opts) {
_range[i] = [rgba.r, rgba.g, rgba.b, rgba.a];
}
- var _sclFunc = d3.scale.linear()
+ var _sclFunc = d3.scaleLinear()
.domain(domain)
.range(_range)
.clamp(true);
diff --git a/src/components/drawing/index.js b/src/components/drawing/index.js
index 6e8fa3fff33..91159a6a894 100644
--- a/src/components/drawing/index.js
+++ b/src/components/drawing/index.js
@@ -1,7 +1,8 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var Lib = require('../../lib');
+var getTraceFromCd = require('../../lib/trace_from_cd');
var numberFormat = Lib.numberFormat;
var isNumeric = require('fast-isnumeric');
var tinycolor = require('tinycolor2');
@@ -101,7 +102,7 @@ drawing.hideOutsideRangePoints = function(traceGroups, subplot) {
var ya = subplot.yaxis;
traceGroups.each(function(d) {
- var trace = d[0].trace;
+ var trace = getTraceFromCd(d);
var xcalendar = trace.xcalendar;
var ycalendar = trace.ycalendar;
var selector = Registry.traceIs(trace, 'bar-like') ? '.bartext' : '.point,.textpoint';
@@ -153,7 +154,7 @@ drawing.dashLine = function(s, dash, lineWidth) {
dash = drawing.dashStyle(dash, lineWidth);
- s.style({
+ s.styles({
'stroke-dasharray': dash,
'stroke-width': lineWidth + 'px'
});
@@ -193,8 +194,8 @@ drawing.fillGroupStyle = function(s) {
var shape = d3.select(this);
// N.B. 'd' won't be a calcdata item when
// fill !== 'none' on a segment-less and marker-less trace
- if(d[0].trace) {
- shape.call(Color.fill, d[0].trace.fillcolor);
+ if(getTraceFromCd(d)) {
+ shape.call(Color.fill, getTraceFromCd(d).fillcolor);
}
});
};
@@ -317,32 +318,34 @@ drawing.gradient = function(sel, gd, gradientID, type, colorscale, prop) {
var gradient = fullLayout._defs.select('.gradients')
.selectAll('#' + fullID)
- .data([type + colorStops.join(';')], Lib.identity);
+ .data([type + colorStops.join(';')], Lib.identity)
+ .enter()
+ .append(info.node);
gradient.exit().remove();
- gradient.enter()
- .append(info.node)
- .each(function() {
- var el = d3.select(this);
- if(info.attrs) el.attr(info.attrs);
-
- el.attr('id', fullID);
-
- var stops = el.selectAll('stop')
- .data(colorStops);
- stops.exit().remove();
- stops.enter().append('stop');
-
- stops.each(function(d) {
- var tc = tinycolor(d[1]);
- d3.select(this).attr({
- offset: d[0] + '%',
- 'stop-color': Color.tinyRGB(tc),
- 'stop-opacity': tc.getAlpha()
- });
+ gradient.each(function() {
+ var el = d3.select(this);
+ if(info.attrs) el.attrs(info.attrs);
+
+ el.attr('id', fullID);
+
+ var stops = el.selectAll('stop')
+ .data(colorStops)
+ .enter()
+ .append('stop');
+
+ stops.exit().remove();
+
+ stops.each(function(d) {
+ var tc = tinycolor(d[1]);
+ d3.select(this).attrs({
+ offset: d[0] + '%',
+ 'stop-color': Color.tinyRGB(tc),
+ 'stop-opacity': tc.getAlpha()
});
});
+ });
sel.style(prop, getFullUrl(fullID, gd))
.style(prop + '-opacity', null);
@@ -518,47 +521,55 @@ drawing.pattern = function(sel, calledBy, gd, patternID, shape, size, solidity,
var pattern = fullLayout._defs.select('.patterns')
.selectAll('#' + fullID)
- .data([str], Lib.identity);
+ .data([str], Lib.identity)
+ .enter()
+ .append('pattern');
pattern.exit().remove();
- pattern.enter()
- .append('pattern')
- .each(function() {
- var el = d3.select(this);
+ pattern.each(function() {
+ var el = d3.select(this);
+
+ el.attrs({
+ 'id': fullID,
+ 'width': width + 'px',
+ 'height': height + 'px',
+ 'patternUnits': 'userSpaceOnUse',
+ // for legends scale down patterns just a bit so that default size (i.e 8) nicely fit in small icons
+ 'patternTransform': isLegend ? 'scale(0.8)' : ''
+ });
- el.attr({
- 'id': fullID,
+ if(bgcolor) {
+ var rects = el.selectAll('rect')
+ .data([0])
+ .enter()
+ .append('rect');
+
+ rects.exit().remove();
+
+ rects.attrs({
'width': width + 'px',
'height': height + 'px',
- 'patternUnits': 'userSpaceOnUse',
- // for legends scale down patterns just a bit so that default size (i.e 8) nicely fit in small icons
- 'patternTransform': isLegend ? 'scale(0.8)' : ''
+ 'fill': bgcolor
});
+ }
- if(bgcolor) {
- var rects = el.selectAll('rect').data([0]);
- rects.exit().remove();
- rects.enter()
- .append('rect')
- .attr({
- 'width': width + 'px',
- 'height': height + 'px',
- 'fill': bgcolor
- });
- }
+ var patterns = el.selectAll(patternTag)
+ .data([0])
+ .enter()
+ .append(patternTag);
- var patterns = el.selectAll(patternTag).data([0]);
- patterns.exit().remove();
- patterns.enter()
- .append(patternTag)
- .attr(patternAttrs);
- });
+ patterns.exit().remove();
+
+ patterns
+ .attrs(patternAttrs);
+ });
sel.style('fill', getFullUrl(fullID, gd))
.style('fill-opacity', null);
sel.classed('pattern_filled', true);
+
var className2query = function(s) {
return '.' + s.attr('class').replace(/\s/g, '.');
};
@@ -691,7 +702,7 @@ drawing.singlePointStyle = function(d, sel, trace, fns, gd) {
// open markers can't have zero linewidth, default to 1px,
// and use fill color as stroke color
sel.call(Color.stroke, fillColor)
- .style({
+ .styles({
'stroke-width': (lineWidth || 1) + 'px',
fill: 'none'
});
@@ -1120,8 +1131,8 @@ drawing.steps = function(shape) {
// uses the id 'js-plotly-tester' and stores it in drawing.tester
drawing.makeTester = function() {
var tester = Lib.ensureSingleById(d3.select('body'), 'svg', 'js-plotly-tester', function(s) {
- s.attr(xmlnsNamespaces.svgAttrs)
- .style({
+ s.attrs(xmlnsNamespaces.svgAttrs)
+ .styles({
position: 'absolute',
left: '-10000px',
top: '-10000px',
@@ -1136,7 +1147,7 @@ drawing.makeTester = function() {
// reference point we can measure off of.
var testref = Lib.ensureSingle(tester, 'path', 'js-reference-point', function(s) {
s.attr('d', 'M0,0H1V1H0Z')
- .style({
+ .styles({
'stroke-width': 0,
fill: 'black'
});
diff --git a/src/components/drawing/symbol_defs.js b/src/components/drawing/symbol_defs.js
index 77b02946170..b050c37b4a8 100644
--- a/src/components/drawing/symbol_defs.js
+++ b/src/components/drawing/symbol_defs.js
@@ -1,6 +1,6 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
/** Marker symbol definitions
* users can specify markers either by number or name
diff --git a/src/components/errorbars/calc.js b/src/components/errorbars/calc.js
index dc6c8de2644..6dd9cfa4cba 100644
--- a/src/components/errorbars/calc.js
+++ b/src/components/errorbars/calc.js
@@ -5,7 +5,7 @@ var isNumeric = require('fast-isnumeric');
var Registry = require('../../registry');
var Axes = require('../../plots/cartesian/axes');
var Lib = require('../../lib');
-
+var getTraceFromCd = require('../../lib/trace_from_cd');
var makeComputeError = require('./compute_error');
module.exports = function calc(gd) {
@@ -13,7 +13,7 @@ module.exports = function calc(gd) {
for(var i = 0; i < calcdata.length; i++) {
var calcTrace = calcdata[i];
- var trace = calcTrace[0].trace;
+ var trace = getTraceFromCd(calcTrace);
if(trace.visible === true && Registry.traceIs(trace, 'errorBarsOK')) {
var xa = Axes.getFromId(gd, trace.xaxis);
diff --git a/src/components/errorbars/plot.js b/src/components/errorbars/plot.js
index 3a940fa28e0..adb51454ea5 100644
--- a/src/components/errorbars/plot.js
+++ b/src/components/errorbars/plot.js
@@ -1,12 +1,16 @@
'use strict';
-var d3 = require('@plotly/d3');
+var Lib = require('../../lib');
+var d3 = require('../../lib/d3');
+var getTraceFromCd = require('../../lib/trace_from_cd');
var isNumeric = require('fast-isnumeric');
var Drawing = require('../drawing');
var subTypes = require('../../traces/scatter/subtypes');
module.exports = function plot(gd, traces, plotinfo, transitionOpts) {
+ var d3EaseFn = Lib.whichD3EaseFn(transitionOpts);
+
var isNew;
var xa = plotinfo.xaxis;
@@ -15,7 +19,7 @@ module.exports = function plot(gd, traces, plotinfo, transitionOpts) {
var hasAnimation = transitionOpts && transitionOpts.duration > 0;
traces.each(function(d) {
- var trace = d[0].trace;
+ var trace = getTraceFromCd(d);
// || {} is in case the trace (specifically scatterternary)
// doesn't support error bars at all, but does go through
// the scatter.plot mechanics, which calls ErrorBars.plot
@@ -37,7 +41,9 @@ module.exports = function plot(gd, traces, plotinfo, transitionOpts) {
if(!yObj.visible && !xObj.visible) d = [];
var errorbars = d3.select(this).selectAll('g.errorbar')
- .data(d, keyFunc);
+ .data(d, keyFunc)
+ .enter()
+ .append('g');
errorbars.exit().remove();
@@ -48,11 +54,12 @@ module.exports = function plot(gd, traces, plotinfo, transitionOpts) {
errorbars.style('opacity', 1);
- var enter = errorbars.enter().append('g')
+ errorbars
.classed('errorbar', true);
if(hasAnimation) {
- enter.style('opacity', 0).transition()
+ errorbars
+ .style('opacity', 0).transition()
.duration(transitionOpts.duration)
.style('opacity', 1);
}
@@ -90,7 +97,7 @@ module.exports = function plot(gd, traces, plotinfo, transitionOpts) {
yerror = yerror
.transition()
.duration(transitionOpts.duration)
- .ease(transitionOpts.easing);
+ .ease(d3EaseFn);
}
yerror.attr('d', path);
@@ -118,7 +125,7 @@ module.exports = function plot(gd, traces, plotinfo, transitionOpts) {
xerror = xerror
.transition()
.duration(transitionOpts.duration)
- .ease(transitionOpts.easing);
+ .ease(d3EaseFn);
}
xerror.attr('d', path);
diff --git a/src/components/errorbars/style.js b/src/components/errorbars/style.js
index 2f9be42f39f..cb380ceffe0 100644
--- a/src/components/errorbars/style.js
+++ b/src/components/errorbars/style.js
@@ -1,13 +1,13 @@
'use strict';
-var d3 = require('@plotly/d3');
-
+var d3 = require('../../lib/d3');
+var getTraceFromCd = require('../../lib/trace_from_cd');
var Color = require('../color');
module.exports = function style(traces) {
traces.each(function(d) {
- var trace = d[0].trace;
+ var trace = getTraceFromCd(d);
var yObj = trace.error_y || {};
var xObj = trace.error_x || {};
diff --git a/src/components/fx/calc.js b/src/components/fx/calc.js
index d48024f371d..736434e9029 100644
--- a/src/components/fx/calc.js
+++ b/src/components/fx/calc.js
@@ -1,6 +1,7 @@
'use strict';
var Lib = require('../../lib');
+var getTraceFromCd = require('../../lib/trace_from_cd');
var Registry = require('../../registry');
module.exports = function calc(gd) {
@@ -15,7 +16,7 @@ module.exports = function calc(gd) {
for(var i = 0; i < calcdata.length; i++) {
var cd = calcdata[i];
- var trace = cd[0].trace;
+ var trace = getTraceFromCd(cd);
// don't include hover calc fields for pie traces
// as calcdata items might be sorted by value and
diff --git a/src/components/fx/hover.js b/src/components/fx/hover.js
index e09796013b5..c7764895a3b 100644
--- a/src/components/fx/hover.js
+++ b/src/components/fx/hover.js
@@ -1,10 +1,11 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var isNumeric = require('fast-isnumeric');
var tinycolor = require('tinycolor2');
var Lib = require('../../lib');
+var getTraceFromCd = require('../../lib/trace_from_cd');
var strTranslate = Lib.strTranslate;
var strRotate = Lib.strRotate;
var Events = require('../../lib/events');
@@ -342,8 +343,8 @@ function _hover(gd, evt, subplot, noHoverEvent) {
for(itemnum = 0; itemnum < evt.length; itemnum++) {
cd = gd.calcdata[evt[itemnum].curveNumber || 0];
if(cd) {
- trace = cd[0].trace;
- if(cd[0].trace.hoverinfo !== 'skip') {
+ trace = getTraceFromCd(cd);
+ if(getTraceFromCd(cd).hoverinfo !== 'skip') {
searchData.push(cd);
if(trace.orientation === 'h') {
hasOneHorizontalTrace = true;
@@ -354,7 +355,7 @@ function _hover(gd, evt, subplot, noHoverEvent) {
} else {
for(curvenum = 0; curvenum < gd.calcdata.length; curvenum++) {
cd = gd.calcdata[curvenum];
- trace = cd[0].trace;
+ trace = getTraceFromCd(cd);
if(trace.hoverinfo !== 'skip' && helpers.isTraceInSubplots(trace, subplots)) {
searchData.push(cd);
if(trace.orientation === 'h') {
@@ -434,9 +435,9 @@ function _hover(gd, evt, subplot, noHoverEvent) {
cd = searchData[curvenum];
// filter out invisible or broken data
- if(!cd || !cd[0] || !cd[0].trace) continue;
+ if(!cd || !cd[0] || !getTraceFromCd(cd)) continue;
- trace = cd[0].trace;
+ trace = getTraceFromCd(cd);
if(trace.visible !== true || trace._length === 0) continue;
@@ -712,7 +713,7 @@ function _hover(gd, evt, subplot, noHoverEvent) {
if(
helpers.isXYhover(_mode) &&
hoverData[0].length !== 0 &&
- hoverData[0].trace.type !== 'splom' // TODO: add support for splom
+ getTraceFromCd(hoverData).type !== 'splom' // TODO: add support for splom
) {
// pick winning point
var winningPoint = hoverData[0];
@@ -931,15 +932,19 @@ function createHoverText(hoverData, opts) {
}
var commonLabel = container.selectAll('g.axistext')
- .data(showCommonLabel ? [0] : []);
- commonLabel.enter().append('g')
- .classed('axistext', true);
+ .data(showCommonLabel ? [0] : [])
+ .enter()
+ .append('g');
+
commonLabel.exit().remove();
+ commonLabel
+ .classed('axistext', true);
+
commonLabel.each(function() {
var label = d3.select(this);
var lpath = Lib.ensureSingle(label, 'path', '', function(s) {
- s.style({'stroke-width': '1px'});
+ s.styles({'stroke-width': '1px'});
});
var ltext = Lib.ensureSingle(label, 'text', '', function(s) {
// prohibit tex interpretation until we can handle
@@ -956,7 +961,7 @@ function createHoverText(hoverData, opts) {
color: commonLabelOpts.font.color || contrastColor
};
- lpath.style({
+ lpath.styles({
fill: commonBgColor,
stroke: commonStroke
});
@@ -1073,10 +1078,18 @@ function createHoverText(hoverData, opts) {
clipPath = null;
}
- var textClip = fullLayout._topclips.selectAll('#' + clipId).data(clipPath ? [0] : []);
- textClip.enter().append('clipPath').attr('id', clipId).append('path');
+ var textClip = fullLayout._topclips.selectAll('#' + clipId)
+ .data(clipPath ? [0] : [])
+ .enter()
+ .append('clipPath');
+
textClip.exit().remove();
- textClip.select('path').attr('d', clipPath);
+
+ textClip
+ .attr('id', clipId).append('path')
+ .select('path')
+ .attr('d', clipPath);
+
Drawing.setClipUrl(ltext, clipPath ? clipId : null, gd);
}
@@ -1143,7 +1156,7 @@ function createHoverText(hoverData, opts) {
mockLegend.entries.push([pt]);
}
- mockLegend.entries.sort(function(a, b) { return a[0].trace.index - b[0].trace.index;});
+ mockLegend.entries.sort(function(a, b) { return getTraceFromCd(a).index - getTraceFromCd(b).index;});
mockLegend.layer = container;
// Draw unified hover label
@@ -1246,23 +1259,28 @@ function createHoverText(hoverData, opts) {
// N.B. when multiple items have the same result key-function value,
// only the first of those items in hoverData gets rendered
return hoverDataKey(d);
- });
- hoverLabels.enter().append('g')
- .classed('hovertext', true)
- .each(function() {
- var g = d3.select(this);
- // trace name label (rect and text.name)
- g.append('rect')
- .call(Color.fill, Color.addOpacity(bgColor, 0.8));
- g.append('text').classed('name', true);
- // trace data label (path and text.nums)
- g.append('path')
- .style('stroke-width', '1px');
- g.append('text').classed('nums', true)
- .call(Drawing.font, fontFamily, fontSize);
- });
+ })
+ .enter()
+ .append('g');
+
hoverLabels.exit().remove();
+ hoverLabels
+ .classed('hovertext', true);
+
+ hoverLabels.each(function() {
+ var g = d3.select(this);
+ // trace name label (rect and text.name)
+ g.append('rect')
+ .call(Color.fill, Color.addOpacity(bgColor, 0.8));
+ g.append('text').classed('name', true);
+ // trace data label (path and text.nums)
+ g.append('path')
+ .style('stroke-width', '1px');
+ g.append('text').classed('nums', true)
+ .call(Drawing.font, fontFamily, fontSize);
+ });
+
// then put the text in, position the pointer to the data,
// and figure out sizes
hoverLabels.each(function(d) {
@@ -1326,7 +1344,7 @@ function createHoverText(hoverData, opts) {
g.select('rect').remove();
}
- g.select('path').style({
+ g.select('path').styles({
fill: numsColor,
stroke: contrastColor
});
@@ -1884,7 +1902,7 @@ function createSpikelines(gd, closestPoints, opts) {
// Foreground horizontal line (to y-axis)
container.insert('line', ':first-child')
- .attr({
+ .attrs({
x1: xBase,
x2: xEndSpike,
y1: hLinePointY,
@@ -1898,7 +1916,7 @@ function createSpikelines(gd, closestPoints, opts) {
// Background horizontal Line (to y-axis)
container.insert('line', ':first-child')
- .attr({
+ .attrs({
x1: xBase,
x2: xEndSpike,
y1: hLinePointY,
@@ -1912,7 +1930,7 @@ function createSpikelines(gd, closestPoints, opts) {
// Y axis marker
if(yMode.indexOf('marker') !== -1) {
container.insert('circle', ':first-child')
- .attr({
+ .attrs({
cx: xEdge + (ya.side !== 'right' ? yThickness : -yThickness),
cy: hLinePointY,
r: yThickness,
@@ -1963,7 +1981,7 @@ function createSpikelines(gd, closestPoints, opts) {
// Foreground vertical line (to x-axis)
container.insert('line', ':first-child')
- .attr({
+ .attrs({
x1: vLinePointX,
x2: vLinePointX,
y1: yBase,
@@ -1977,7 +1995,7 @@ function createSpikelines(gd, closestPoints, opts) {
// Background vertical line (to x-axis)
container.insert('line', ':first-child')
- .attr({
+ .attrs({
x1: vLinePointX,
x2: vLinePointX,
y1: yBase,
@@ -1992,7 +2010,7 @@ function createSpikelines(gd, closestPoints, opts) {
// X axis marker
if(xMode.indexOf('marker') !== -1) {
container.insert('circle', ':first-child')
- .attr({
+ .attrs({
cx: vLinePointX,
cy: yEdge - (xa.side !== 'top' ? xThickness : -xThickness),
r: xThickness,
diff --git a/src/components/fx/index.js b/src/components/fx/index.js
index 8fc661c0c54..e771a61eff8 100644
--- a/src/components/fx/index.js
+++ b/src/components/fx/index.js
@@ -1,6 +1,6 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var Lib = require('../../lib');
var dragElement = require('../dragelement');
var helpers = require('./helpers');
diff --git a/src/components/images/draw.js b/src/components/images/draw.js
index b08cdebbd09..7cba606e0a5 100644
--- a/src/components/images/draw.js
+++ b/src/components/images/draw.js
@@ -1,6 +1,6 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var Drawing = require('../drawing');
var Axes = require('../../plots/cartesian/axes');
var axisIds = require('../../plots/cartesian/axis_ids');
@@ -181,7 +181,7 @@ module.exports = function draw(gd) {
break;
}
- thisImage.attr({
+ thisImage.attrs({
x: xPos,
y: yPos,
width: width,
@@ -204,12 +204,13 @@ module.exports = function draw(gd) {
}
var imagesBelow = fullLayout._imageLowerLayer.selectAll('image')
- .data(imageDataBelow);
+ .data(imageDataBelow)
+ .enter()
+ .append('image');
var imagesAbove = fullLayout._imageUpperLayer.selectAll('image')
- .data(imageDataAbove);
-
- imagesBelow.enter().append('image');
- imagesAbove.enter().append('image');
+ .data(imageDataAbove)
+ .enter()
+ .append('image');
imagesBelow.exit().remove();
imagesAbove.exit().remove();
@@ -235,9 +236,10 @@ module.exports = function draw(gd) {
var imagesOnSubplot = subplotObj.imagelayer.selectAll('image')
// even if there are no images on this subplot, we need to run
// enter and exit in case there were previously
- .data(imageDataSubplot[subplot] || []);
+ .data(imageDataSubplot[subplot] || [])
+ .enter()
+ .append('image');
- imagesOnSubplot.enter().append('image');
imagesOnSubplot.exit().remove();
imagesOnSubplot.each(function(d) {
diff --git a/src/components/legend/draw.js b/src/components/legend/draw.js
index 0f5e3538fe4..d08c4ac04ca 100644
--- a/src/components/legend/draw.js
+++ b/src/components/legend/draw.js
@@ -1,8 +1,9 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var Lib = require('../../lib');
+var getTraceFromCd = require('../../lib/trace_from_cd');
var Plots = require('../../plots/plots');
var Registry = require('../../registry');
var Events = require('../../lib/events');
@@ -95,29 +96,44 @@ function _draw(gd, legendObj) {
}
var scrollBar = Lib.ensureSingle(legend, 'rect', 'scrollbar', function(s) {
- s.attr(constants.scrollBarEnterAttrs)
+ s.attrs(constants.scrollBarEnterAttrs)
.call(Color.fill, constants.scrollBarColor);
});
- var groups = scrollBox.selectAll('g.groups').data(legendData);
- groups.enter().append('g').attr('class', 'groups');
+ var groups = scrollBox.selectAll('g.groups')
+ .data(legendData)
+ .enter()
+ .append('g');
+
groups.exit().remove();
- var traces = groups.selectAll('g.traces').data(Lib.identity);
- traces.enter().append('g').attr('class', 'traces');
+ groups
+ .attr('class', 'groups');
+
+ var traces = groups.selectAll('g.traces')
+ .data(Lib.identity)
+ .enter()
+ .append('g');
+
traces.exit().remove();
+ traces
+ .attr('class', 'traces');
+
traces.style('opacity', function(d) {
- var trace = d[0].trace;
+ var trace = getTraceFromCd(d);
if(Registry.traceIs(trace, 'pie-like')) {
return hiddenSlices.indexOf(d[0].label) !== -1 ? 0.5 : 1;
} else {
return trace.visible === 'legendonly' ? 0.5 : 1;
}
- })
- .each(function() { d3.select(this).call(drawTexts, gd, legendObj); })
- .call(style, gd, legendObj)
- .each(function() { if(!inHover) d3.select(this).call(setupTraceToggle, gd); });
+ });
+
+ traces.each(function() { d3.select(this).call(drawTexts, gd, legendObj); });
+
+ traces
+ .call(style, gd, legendObj)
+ .each(function() { if(!inHover) d3.select(this).call(setupTraceToggle, gd); });
Lib.syncOrAsync([
Plots.previousPromises,
@@ -168,7 +184,7 @@ function _draw(gd, legendObj) {
// if unified hover, let it be its full size
if(inHover) height = legendObj._height;
- bg.attr({
+ bg.attrs({
width: legendObj._width - bw,
height: height - bw,
x: bw / 2,
@@ -177,7 +193,7 @@ function _draw(gd, legendObj) {
Drawing.setTranslate(scrollBox, 0, 0);
- clipPath.select('rect').attr({
+ clipPath.select('rect').attrs({
width: legendObj._width - 2 * bw,
height: height - 2 * bw,
x: bw,
@@ -201,7 +217,7 @@ function _draw(gd, legendObj) {
// increase the background and clip-path width
// by the scrollbar width and margin
- bg.attr({
+ bg.attrs({
width: legendObj._width -
2 * bw +
constants.scrollBarWidth +
@@ -211,7 +227,7 @@ function _draw(gd, legendObj) {
y: bw / 2
});
- clipPath.select('rect').attr({
+ clipPath.select('rect').attrs({
width: legendObj._width -
2 * bw +
constants.scrollBarWidth +
@@ -250,8 +266,8 @@ function _draw(gd, legendObj) {
};
// scroll legend by dragging scrollBAR
- var scrollBarDrag = d3.behavior.drag()
- .on('dragstart', function() {
+ var scrollBarDrag = d3.drag()
+ .on('start', function() {
var e = d3.event.sourceEvent;
if(e.type === 'touchstart') {
eventY0 = e.changedTouches[0].clientY;
@@ -274,8 +290,8 @@ function _draw(gd, legendObj) {
scrollBar.call(scrollBarDrag);
// scroll legend by touch-dragging scrollBOX
- var scrollBoxTouchDrag = d3.behavior.drag()
- .on('dragstart', function() {
+ var scrollBoxTouchDrag = d3.drag()
+ .on('start', function() {
var e = d3.event.sourceEvent;
if(e.type === 'touchstart') {
eventY0 = e.changedTouches[0].clientY;
diff --git a/src/components/legend/style.js b/src/components/legend/style.js
index 9ca9c194af1..63f5125ee02 100644
--- a/src/components/legend/style.js
+++ b/src/components/legend/style.js
@@ -1,6 +1,6 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var Registry = require('../../registry');
var Lib = require('../../lib');
@@ -59,27 +59,28 @@ module.exports = function style(s, gd, legend) {
layers.attr('transform', strTranslate(0, markerOffsetY));
}
- var fill = layers
- .selectAll('g.legendfill')
- .data([d]);
- fill.enter().append('g')
+ layers.selectAll('g.legendfill')
+ .data([d])
+ .enter()
+ .append('g')
.classed('legendfill', true);
- var line = layers
- .selectAll('g.legendlines')
- .data([d]);
- line.enter().append('g')
+ layers.selectAll('g.legendlines')
+ .data([d])
+ .enter()
+ .append('g')
.classed('legendlines', true);
- var symbol = layers
- .selectAll('g.legendsymbols')
- .data([d]);
- symbol.enter().append('g')
+ var symbol = layers.selectAll('g.legendsymbols')
+ .data([d])
+ .enter()
+ .append('g')
.classed('legendsymbols', true);
symbol.selectAll('g.legendpoints')
.data([d])
- .enter().append('g')
+ .enter()
+ .append('g')
.classed('legendpoints', true);
})
.each(styleSpatial)
@@ -141,10 +142,15 @@ module.exports = function style(s, gd, legend) {
var this3 = d3.select(this);
var fill = this3.select('.legendfill').selectAll('path')
- .data(showFill || showGradientFill ? [d] : []);
- fill.enter().append('path').classed('js-fill', true);
+ .data(showFill || showGradientFill ? [d] : [])
+ .enter()
+ .append('path');
+
fill.exit().remove();
- fill.attr('d', pathStart + 'h' + itemWidth + 'v6h-' + itemWidth + 'z')
+
+ fill
+ .classed('js-fill', true)
+ .attr('d', pathStart + 'h' + itemWidth + 'v6h-' + itemWidth + 'z')
.call(showFill ? Drawing.fillGroupStyle : fillGradient);
if(showLine || showGradientLine) {
@@ -154,17 +160,21 @@ module.exports = function style(s, gd, legend) {
}
var line = this3.select('.legendlines').selectAll('path')
- .data(showLine || showGradientLine ? [dMod] : []);
- line.enter().append('path').classed('js-line', true);
+ .data(showLine || showGradientLine ? [dMod] : [])
+ .enter()
+ .append('path');
+
line.exit().remove();
- // this is ugly... but you can't apply a gradient to a perfectly
- // horizontal or vertical line. Presumably because then
- // the system doesn't know how to scale vertical variation, even
- // though there *is* no vertical variation in this case.
- // so add an invisibly small angle to the line
- // This issue (and workaround) exist across (Mac) Chrome, FF, and Safari
- line.attr('d', pathStart + (showGradientLine ? 'l' + itemWidth + ',0.0001' : 'h' + itemWidth))
+ line
+ .classed('js-line', true)
+ // this is ugly... but you can't apply a gradient to a perfectly
+ // horizontal or vertical line. Presumably because then
+ // the system doesn't know how to scale vertical variation, even
+ // though there *is* no vertical variation in this case.
+ // so add an invisibly small angle to the line
+ // This issue (and workaround) exist across (Mac) Chrome, FF, and Safari
+ .attr('d', pathStart + (showGradientLine ? 'l' + itemWidth + ',0.0001' : 'h' + itemWidth))
.call(showLine ? Drawing.lineGroupStyle : lineGradient);
}
@@ -254,25 +264,35 @@ module.exports = function style(s, gd, legend) {
var ptgroup = d3.select(this).select('g.legendpoints');
var pts = ptgroup.selectAll('path.scatterpts')
- .data(showMarker ? dMod : []);
- // make sure marker is on the bottom, in case it enters after text
- pts.enter().insert('path', ':first-child')
- .classed('scatterpts', true)
- .attr('transform', centerTransform);
+ .data(showMarker ? dMod : [])
+ // make sure marker is on the bottom, in case it enters after text
+ .enter()
+ .insert('path', ':first-child');
+
pts.exit().remove();
- pts.call(Drawing.pointStyle, tMod, gd);
+
+ pts
+ .classed('scatterpts', true)
+ .attr('transform', centerTransform)
+ .call(Drawing.pointStyle, tMod, gd);
// 'mrc' is set in pointStyle and used in textPointStyle:
// constrain it here
if(showMarker) dMod[0].mrc = 3;
var txt = ptgroup.selectAll('g.pointtext')
- .data(showText ? dMod : []);
- txt.enter()
- .append('g').classed('pointtext', true)
- .append('text').attr('transform', centerTransform);
+ .data(showText ? dMod : [])
+ .enter()
+ .append('g');
+
txt.exit().remove();
- txt.selectAll('text').call(Drawing.textPointStyle, tMod, gd);
+
+ txt
+ .classed('pointtext', true)
+ .append('text')
+ .attr('transform', centerTransform)
+ .selectAll('text')
+ .call(Drawing.textPointStyle, tMod, gd);
}
function styleWaterfalls(d) {
@@ -294,13 +314,17 @@ module.exports = function style(s, gd, legend) {
[['increasing', 'M-6,-6V6H6Z'], ['decreasing', 'M6,6V-6H-6Z']];
}
- var pts = d3.select(this).select('g.legendpoints')
- .selectAll('path.legendwaterfall')
- .data(ptsData);
- pts.enter().append('path').classed('legendwaterfall', true)
+ var pts = d3.select(this).select('g.legendpoints').selectAll('path.legendwaterfall')
+ .data(ptsData)
+ .enter()
+ .append('path');
+
+ pts.exit().remove();
+
+ pts
+ .classed('legendwaterfall', true)
.attr('transform', centerTransform)
.style('stroke-miterlimit', 1);
- pts.exit().remove();
pts.each(function(dd) {
var pt = d3.select(this);
@@ -333,13 +357,17 @@ module.exports = function style(s, gd, legend) {
var isVisible = (!desiredType) ? Registry.traceIs(trace, 'bar') :
(trace.visible && trace.type === desiredType);
- var barpath = d3.select(lThis).select('g.legendpoints')
- .selectAll('path.legend' + desiredType)
- .data(isVisible ? [d] : []);
- barpath.enter().append('path').classed('legend' + desiredType, true)
+ var barpath = d3.select(lThis).select('g.legendpoints').selectAll('path.legend' + desiredType)
+ .data(isVisible ? [d] : [])
+ .enter()
+ .append('path');
+
+ barpath.exit().remove();
+
+ barpath
+ .classed('legend' + desiredType, true)
.attr('d', 'M6,6H-6V-6H6Z')
.attr('transform', centerTransform);
- barpath.exit().remove();
barpath.each(function(d) {
var p = d3.select(this);
@@ -386,14 +414,18 @@ module.exports = function style(s, gd, legend) {
function styleBoxes(d) {
var trace = d[0].trace;
- var pts = d3.select(this).select('g.legendpoints')
- .selectAll('path.legendbox')
- .data(trace.visible && Registry.traceIs(trace, 'box-violin') ? [d] : []);
- pts.enter().append('path').classed('legendbox', true)
+ var pts = d3.select(this).select('g.legendpoints').selectAll('path.legendbox')
+ .data(trace.visible && Registry.traceIs(trace, 'box-violin') ? [d] : [])
+ .enter()
+ .append('path');
+
+ pts.exit().remove();
+
+ pts
+ .classed('legendbox', true)
// if we want the median bar, prepend M6,0H-6
.attr('d', 'M6,6H-6V-6H6Z')
.attr('transform', centerTransform);
- pts.exit().remove();
pts.each(function() {
var p = d3.select(this);
@@ -424,17 +456,21 @@ module.exports = function style(s, gd, legend) {
function styleCandles(d) {
var trace = d[0].trace;
- var pts = d3.select(this).select('g.legendpoints')
- .selectAll('path.legendcandle')
- .data(trace.visible && trace.type === 'candlestick' ? [d, d] : []);
- pts.enter().append('path').classed('legendcandle', true)
+ var pts = d3.select(this).select('g.legendpoints').selectAll('path.legendcandle')
+ .data(trace.visible && trace.type === 'candlestick' ? [d, d] : [])
+ .enter()
+ .append('path');
+
+ pts.exit().remove();
+
+ pts
+ .classed('legendcandle', true)
.attr('d', function(_, i) {
if(i) return 'M-15,0H-8M-8,6V-6H8Z'; // increasing
return 'M15,0H8M8,-6V6H-8Z'; // decreasing
})
.attr('transform', centerTransform)
.style('stroke-miterlimit', 1);
- pts.exit().remove();
pts.each(function(_, i) {
var p = d3.select(this);
@@ -451,17 +487,21 @@ module.exports = function style(s, gd, legend) {
function styleOHLC(d) {
var trace = d[0].trace;
- var pts = d3.select(this).select('g.legendpoints')
- .selectAll('path.legendohlc')
- .data(trace.visible && trace.type === 'ohlc' ? [d, d] : []);
- pts.enter().append('path').classed('legendohlc', true)
+ var pts = d3.select(this).select('g.legendpoints').selectAll('path.legendohlc')
+ .data(trace.visible && trace.type === 'ohlc' ? [d, d] : [])
+ .enter()
+ .append('path');
+
+ pts.exit().remove();
+
+ pts
+ .classed('legendohlc', true)
.attr('d', function(_, i) {
if(i) return 'M-15,0H0M-8,-6V0'; // increasing
return 'M15,0H0M8,6V0'; // decreasing
})
.attr('transform', centerTransform)
.style('stroke-miterlimit', 1);
- pts.exit().remove();
pts.each(function(_, i) {
var p = d3.select(this);
@@ -490,13 +530,17 @@ module.exports = function style(s, gd, legend) {
var isVisible = (!desiredType) ? Registry.traceIs(trace, desiredType) :
(trace.visible && trace.type === desiredType);
- var pts = d3.select(lThis).select('g.legendpoints')
- .selectAll('path.legend' + desiredType)
- .data(isVisible ? [d] : []);
- pts.enter().append('path').classed('legend' + desiredType, true)
+ var pts = d3.select(lThis).select('g.legendpoints').selectAll('path.legend' + desiredType)
+ .data(isVisible ? [d] : [])
+ .enter()
+ .append('path');
+
+ pts.exit().remove();
+
+ pts
+ .classed('legend' + desiredType, true)
.attr('d', 'M6,6H-6V-6H6Z')
.attr('transform', centerTransform);
- pts.exit().remove();
if(pts.size()) {
var cont = (trace.marker || {}).line;
@@ -589,13 +633,17 @@ module.exports = function style(s, gd, legend) {
}
}
- var pts = d3.select(this).select('g.legendpoints')
- .selectAll('path.legend3dandfriends')
- .data(ptsData);
- pts.enter().append('path').classed('legend3dandfriends', true)
+ var pts = d3.select(this).select('g.legendpoints').selectAll('path.legend3dandfriends')
+ .data(ptsData)
+ .enter()
+ .append('path');
+
+ pts.exit().remove();
+
+ pts
+ .classed('legend3dandfriends', true)
.attr('transform', centerTransform)
.style('stroke-miterlimit', 1);
- pts.exit().remove();
pts.each(function(dd, i) {
var pt = d3.select(this);
diff --git a/src/components/modebar/modebar.js b/src/components/modebar/modebar.js
index 143c3406668..6d72f24515b 100644
--- a/src/components/modebar/modebar.js
+++ b/src/components/modebar/modebar.js
@@ -1,6 +1,6 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var isNumeric = require('fast-isnumeric');
var Lib = require('../../lib');
diff --git a/src/components/rangeselector/draw.js b/src/components/rangeselector/draw.js
index 45c6deae4a8..4115aa6a8bf 100644
--- a/src/components/rangeselector/draw.js
+++ b/src/components/rangeselector/draw.js
@@ -1,6 +1,6 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var Registry = require('../../registry');
var Plots = require('../../plots/plots');
@@ -23,17 +23,18 @@ module.exports = function draw(gd) {
var fullLayout = gd._fullLayout;
var selectors = fullLayout._infolayer.selectAll('.rangeselector')
- .data(makeSelectorData(gd), selectorKeyFunc);
-
- selectors.enter().append('g')
- .classed('rangeselector', true);
+ .data(makeSelectorData(gd), selectorKeyFunc)
+ .enter()
+ .append('g');
selectors.exit().remove();
- selectors.style({
- cursor: 'pointer',
- 'pointer-events': 'all'
- });
+ selectors
+ .classed('rangeselector', true)
+ .styles({
+ cursor: 'pointer',
+ 'pointer-events': 'all'
+ });
selectors.each(function(d) {
var selector = d3.select(this);
@@ -41,13 +42,15 @@ module.exports = function draw(gd) {
var selectorLayout = axisLayout.rangeselector;
var buttons = selector.selectAll('g.button')
- .data(Lib.filterVisible(selectorLayout.buttons));
-
- buttons.enter().append('g')
- .classed('button', true);
+ .data(Lib.filterVisible(selectorLayout.buttons))
+ .enter()
+ .append('g');
buttons.exit().remove();
+ buttons
+ .classed('button', true);
+
buttons.each(function(d) {
var button = d3.select(this);
var update = getUpdateObject(axisLayout, d);
@@ -115,7 +118,7 @@ function drawButtonRect(button, selectorLayout, d) {
s.attr('shape-rendering', 'crispEdges');
});
- rect.attr({
+ rect.attrs({
'rx': constants.rx,
'ry': constants.ry
});
@@ -190,7 +193,7 @@ function reposition(gd, buttons, opts, axName, selector) {
button.attr('transform', strTranslate(borderWidth + width, borderWidth));
- rect.attr({
+ rect.attrs({
x: 0,
y: 0,
width: wEff,
diff --git a/src/components/rangeslider/draw.js b/src/components/rangeslider/draw.js
index 348c45697e9..9f827d18f08 100644
--- a/src/components/rangeslider/draw.js
+++ b/src/components/rangeslider/draw.js
@@ -1,11 +1,12 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var Registry = require('../../registry');
var Plots = require('../../plots/plots');
var Lib = require('../../lib');
+var getTraceFromCd = require('../../lib/trace_from_cd');
var strTranslate = Lib.strTranslate;
var Drawing = require('../drawing');
var Color = require('../color');
@@ -49,9 +50,10 @@ module.exports = function(gd) {
return axisOpts._name;
}
- var rangeSliders = fullLayout._infolayer
- .selectAll('g.' + constants.containerClassName)
- .data(rangeSliderData, keyFunction);
+ var rangeSliders = fullLayout._infolayer.selectAll('g.' + constants.containerClassName)
+ .data(rangeSliderData, keyFunction)
+ .enter()
+ .append('g');
// remove exiting sliders and their corresponding clip paths
rangeSliders.exit().each(function(axisOpts) {
@@ -62,7 +64,7 @@ module.exports = function(gd) {
// return early if no range slider is visible
if(rangeSliderData.length === 0) return;
- rangeSliders.enter().append('g')
+ rangeSliders
.classed(constants.containerClassName, true)
.attr('pointer-events', 'all');
@@ -381,7 +383,7 @@ function setPixelRange(rangeSlider, gd, axisOpts, opts, oppAxisOpts, oppAxisRang
function drawBg(rangeSlider, gd, axisOpts, opts) {
var bg = Lib.ensureSingle(rangeSlider, 'rect', constants.bgClassName, function(s) {
- s.attr({
+ s.attrs({
x: 0,
y: 0,
'shape-rendering': 'crispEdges'
@@ -395,7 +397,7 @@ function drawBg(rangeSlider, gd, axisOpts, opts) {
var offsetShift = -opts._offsetShift;
var lw = Drawing.crispRound(gd, opts.borderwidth);
- bg.attr({
+ bg.attrs({
width: opts._width + borderCorrect,
height: opts._height + borderCorrect,
transform: strTranslate(offsetShift, offsetShift),
@@ -409,10 +411,10 @@ function addClipPath(rangeSlider, gd, axisOpts, opts) {
var fullLayout = gd._fullLayout;
var clipPath = Lib.ensureSingleById(fullLayout._topdefs, 'clipPath', opts._clipId, function(s) {
- s.append('rect').attr({ x: 0, y: 0 });
+ s.append('rect').attrs({ x: 0, y: 0 });
});
- clipPath.select('rect').attr({
+ clipPath.select('rect').attrs({
width: opts._width,
height: opts._height
});
@@ -422,16 +424,18 @@ function drawRangePlot(rangeSlider, gd, axisOpts, opts) {
var calcData = gd.calcdata;
var rangePlots = rangeSlider.selectAll('g.' + constants.rangePlotClassName)
- .data(axisOpts._subplotsWith, Lib.identity);
+ .data(axisOpts._subplotsWith, Lib.identity)
+ .enter()
+ .append('g');
- rangePlots.enter().append('g')
+ rangePlots.exit().remove();
+
+ rangePlots
.attr('class', function(id) { return constants.rangePlotClassName + ' ' + id; })
.call(Drawing.setClipUrl, opts._clipId, gd);
rangePlots.order();
- rangePlots.exit().remove();
-
var mainplotinfo;
rangePlots.each(function(id, i) {
@@ -506,7 +510,7 @@ function filterRangePlotCalcData(calcData, subplotId) {
for(var i = 0; i < calcData.length; i++) {
var calcTrace = calcData[i];
- var trace = calcTrace[0].trace;
+ var trace = getTraceFromCd(calcTrace);
if(trace.xaxis + trace.yaxis === subplotId) {
out.push(calcTrace);
@@ -518,7 +522,7 @@ function filterRangePlotCalcData(calcData, subplotId) {
function drawMasks(rangeSlider, gd, axisOpts, opts, oppAxisRangeOpts) {
var maskMin = Lib.ensureSingle(rangeSlider, 'rect', constants.maskMinClassName, function(s) {
- s.attr({
+ s.attrs({
x: 0,
y: 0,
'shape-rendering': 'crispEdges'
@@ -530,7 +534,7 @@ function drawMasks(rangeSlider, gd, axisOpts, opts, oppAxisRangeOpts) {
.call(Color.fill, constants.maskColor);
var maskMax = Lib.ensureSingle(rangeSlider, 'rect', constants.maskMaxClassName, function(s) {
- s.attr({
+ s.attrs({
y: 0,
'shape-rendering': 'crispEdges'
});
@@ -543,7 +547,7 @@ function drawMasks(rangeSlider, gd, axisOpts, opts, oppAxisRangeOpts) {
// masks used for oppAxis zoom
if(oppAxisRangeOpts.rangemode !== 'match') {
var maskMinOppAxis = Lib.ensureSingle(rangeSlider, 'rect', constants.maskMinOppAxisClassName, function(s) {
- s.attr({
+ s.attrs({
y: 0,
'shape-rendering': 'crispEdges'
});
@@ -554,7 +558,7 @@ function drawMasks(rangeSlider, gd, axisOpts, opts, oppAxisRangeOpts) {
.call(Color.fill, constants.maskOppAxisColor);
var maskMaxOppAxis = Lib.ensureSingle(rangeSlider, 'rect', constants.maskMaxOppAxisClassName, function(s) {
- s.attr({
+ s.attrs({
y: 0,
'shape-rendering': 'crispEdges'
});
@@ -571,14 +575,14 @@ function drawSlideBox(rangeSlider, gd, axisOpts, opts) {
if(gd._context.staticPlot) return;
var slideBox = Lib.ensureSingle(rangeSlider, 'rect', constants.slideBoxClassName, function(s) {
- s.attr({
+ s.attrs({
y: 0,
cursor: constants.slideBoxCursor,
'shape-rendering': 'crispEdges'
});
});
- slideBox.attr({
+ slideBox.attrs({
height: opts._height,
fill: constants.slideBoxFill
});
@@ -604,14 +608,14 @@ function drawGrabbers(rangeSlider, gd, axisOpts, opts) {
height: Math.round(opts._height / 2),
};
var handleMin = Lib.ensureSingle(grabberMin, 'rect', constants.handleMinClassName, function(s) {
- s.attr(handleFixAttrs);
+ s.attrs(handleFixAttrs);
});
- handleMin.attr(handleDynamicAttrs);
+ handleMin.attrs(handleDynamicAttrs);
var handleMax = Lib.ensureSingle(grabberMax, 'rect', constants.handleMaxClassName, function(s) {
- s.attr(handleFixAttrs);
+ s.attrs(handleFixAttrs);
});
- handleMax.attr(handleDynamicAttrs);
+ handleMax.attrs(handleDynamicAttrs);
//
var grabAreaFixAttrs = {
@@ -623,12 +627,12 @@ function drawGrabbers(rangeSlider, gd, axisOpts, opts) {
};
var grabAreaMin = Lib.ensureSingle(grabberMin, 'rect', constants.grabAreaMinClassName, function(s) {
- s.attr(grabAreaFixAttrs);
+ s.attrs(grabAreaFixAttrs);
});
grabAreaMin.attr('height', opts._height);
var grabAreaMax = Lib.ensureSingle(grabberMax, 'rect', constants.grabAreaMaxClassName, function(s) {
- s.attr(grabAreaFixAttrs);
+ s.attrs(grabAreaFixAttrs);
});
grabAreaMax.attr('height', opts._height);
}
diff --git a/src/components/shapes/draw.js b/src/components/shapes/draw.js
index 06050ca72c5..446b4e33f64 100644
--- a/src/components/shapes/draw.js
+++ b/src/components/shapes/draw.js
@@ -129,7 +129,7 @@ function drawOne(gd, index) {
}
var path = shapeLayer.append('path')
- .attr(attrs)
+ .attrs(attrs)
.style('opacity', opacity)
.call(Color.stroke, lineColor)
.call(Color.fill, fillColor)
@@ -141,7 +141,7 @@ function drawOne(gd, index) {
if(isActiveShape || gd._context.edits.shapePosition) editHelpers = arrayEditor(gd.layout, 'shapes', options);
if(isActiveShape) {
- path.style({
+ path.styles({
'cursor': 'move',
});
@@ -242,7 +242,7 @@ function setupDragElement(gd, shapePath, shapeOptions, index, shapeLayer, editHe
// Helper path for moving
g.append('path')
.attr('d', shapePath.attr('d'))
- .style({
+ .styles({
'cursor': 'move',
'stroke-width': sensoryWidth,
'stroke-opacity': '0' // ensure not visible
@@ -255,23 +255,23 @@ function setupDragElement(gd, shapePath, shapeOptions, index, shapeLayer, editHe
var circleRadius = Math.max(sensoryWidth / 2, minSensoryWidth);
g.append('circle')
- .attr({
+ .attrs({
'data-line-point': 'start-point',
'cx': xPixelSized ? x2p(shapeOptions.xanchor) + shapeOptions.x0 : x2p(shapeOptions.x0),
'cy': yPixelSized ? y2p(shapeOptions.yanchor) - shapeOptions.y0 : y2p(shapeOptions.y0),
'r': circleRadius
})
- .style(circleStyle)
+ .styles(circleStyle)
.classed('cursor-grab', true);
g.append('circle')
- .attr({
+ .attrs({
'data-line-point': 'end-point',
'cx': xPixelSized ? x2p(shapeOptions.xanchor) + shapeOptions.x1 : x2p(shapeOptions.x1),
'cy': yPixelSized ? y2p(shapeOptions.yanchor) - shapeOptions.y1 : y2p(shapeOptions.y1),
'r': circleRadius
})
- .style(circleStyle)
+ .styles(circleStyle)
.classed('cursor-grab', true);
return g;
@@ -504,20 +504,22 @@ function setupDragElement(gd, shapePath, shapeOptions, index, shapeLayer, editHe
function renderAnchor() {
var isNotPath = shapeOptions.type !== 'path';
- // d3 join with dummy data to satisfy d3 data-binding
- var visualCues = shapeLayer.selectAll('.visual-cue').data([0]);
-
- // Enter
var strokeWidth = 1;
- visualCues.enter()
- .append('path')
- .attr({
- 'fill': '#fff',
- 'fill-rule': 'evenodd',
- 'stroke': '#000',
- 'stroke-width': strokeWidth
- })
- .classed('visual-cue', true);
+
+ // d3 join with dummy data to satisfy d3 data-binding
+ var visualCues = shapeLayer.selectAll('.visual-cue')
+ .data([0])
+ .enter()
+ .append('path');
+
+ visualCues
+ .attrs({
+ 'fill': '#fff',
+ 'fill-rule': 'evenodd',
+ 'stroke': '#000',
+ 'stroke-width': strokeWidth
+ })
+ .classed('visual-cue', true);
// Update
var posX = x2p(
diff --git a/src/components/shapes/draw_newshape/display_outlines.js b/src/components/shapes/draw_newshape/display_outlines.js
index 4d855b3bc51..b49500a1f3b 100644
--- a/src/components/shapes/draw_newshape/display_outlines.js
+++ b/src/components/shapes/draw_newshape/display_outlines.js
@@ -202,7 +202,7 @@ module.exports = function displayOutlines(polygons, outlines, dragOptions, nCall
.attr('cx', x)
.attr('cy', y)
.attr('r', 4)
- .style({
+ .styles({
'mix-blend-mode': 'luminosity',
fill: 'black',
stroke: 'white',
diff --git a/src/components/sliders/draw.js b/src/components/sliders/draw.js
index 1ad51536c9b..148598a7ccc 100644
--- a/src/components/sliders/draw.js
+++ b/src/components/sliders/draw.js
@@ -1,6 +1,6 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var Plots = require('../../plots/plots');
var Color = require('../color');
@@ -21,11 +21,17 @@ module.exports = function draw(gd) {
var sliderData = makeSliderData(fullLayout, gd);
// draw a container for *all* sliders:
- var sliders = fullLayout._infolayer
- .selectAll('g.' + constants.containerClassName)
- .data(sliderData.length > 0 ? [0] : []);
+ var sliders = fullLayout._infolayer.selectAll('g.' + constants.containerClassName)
+ .data(sliderData.length > 0 ? [0] : [])
+ .enter()
+ .append('g');
- sliders.enter().append('g')
+ sliders.exit().each(function() {
+ d3.select(this).selectAll('g.' + constants.groupClassName)
+ .each(clearSlider);
+ }).remove();
+
+ sliders
.classed(constants.containerClassName, true)
.style('cursor', 'ew-resize');
@@ -41,25 +47,21 @@ module.exports = function draw(gd) {
Plots.autoMargin(gd, autoMarginId(sliderOpts));
}
- sliders.exit().each(function() {
- d3.select(this).selectAll('g.' + constants.groupClassName)
- .each(clearSlider);
- })
- .remove();
-
// Return early if no menus visible:
if(sliderData.length === 0) return;
var sliderGroups = sliders.selectAll('g.' + constants.groupClassName)
- .data(sliderData, keyFunction);
-
- sliderGroups.enter().append('g')
- .classed(constants.groupClassName, true);
+ .data(sliderData, keyFunction)
+ .enter()
+ .append('g');
sliderGroups.exit()
.each(clearSlider)
.remove();
+ sliderGroups
+ .classed(constants.groupClassName, true);
+
// Find the dimensions of the sliders:
for(var i = 0; i < sliderData.length; i++) {
var sliderOpts = sliderData[i];
@@ -117,11 +119,15 @@ function keyFunction(opts) {
// Compute the dimensions (mutates sliderOpts):
function findDimensions(gd, sliderOpts) {
var sliderLabels = Drawing.tester.selectAll('g.' + constants.labelGroupClass)
- .data(sliderOpts._visibleSteps);
+ .data(sliderOpts._visibleSteps)
+ .enter()
+ .append('g');
- sliderLabels.enter().append('g')
+ sliderLabels
.classed(constants.labelGroupClass, true);
+ sliderLabels.remove();
+
// loop over fake buttons to find width / height
var maxLabelWidth = 0;
var labelHeight = 0;
@@ -138,8 +144,6 @@ function findDimensions(gd, sliderOpts) {
}
});
- sliderLabels.remove();
-
var dims = sliderOpts._dims = {};
dims.inputAreaWidth = Math.max(
@@ -295,7 +299,7 @@ function drawCurrentValue(sliderGroup, sliderOpts, valueOverride) {
}
var text = Lib.ensureSingle(sliderGroup, 'text', constants.labelClass, function(s) {
- s.attr({
+ s.attrs({
'text-anchor': textAnchor,
'data-notex': 1
});
@@ -336,7 +340,7 @@ function drawGrip(sliderGroup, gd, sliderOpts) {
.style('pointer-events', 'all');
});
- grip.attr({
+ grip.attrs({
width: constants.gripWidth,
height: constants.gripHeight,
rx: constants.gripRadius,
@@ -349,7 +353,7 @@ function drawGrip(sliderGroup, gd, sliderOpts) {
function drawLabel(item, data, sliderOpts) {
var text = Lib.ensureSingle(item, 'text', constants.labelClass, function(s) {
- s.attr({
+ s.attrs({
'text-anchor': 'middle',
'data-notex': 1
});
@@ -371,13 +375,15 @@ function drawLabelGroup(sliderGroup, sliderOpts) {
var dims = sliderOpts._dims;
var labelItems = labels.selectAll('g.' + constants.labelGroupClass)
- .data(dims.labelSteps);
-
- labelItems.enter().append('g')
- .classed(constants.labelGroupClass, true);
+ .data(dims.labelSteps)
+ .enter()
+ .append('g');
labelItems.exit().remove();
+ labelItems
+ .classed(constants.labelGroupClass, true);
+
labelItems.each(function(d) {
var item = d3.select(this);
@@ -508,26 +514,28 @@ function attachGripEvents(item, gd, sliderGroup) {
}
function drawTicks(sliderGroup, sliderOpts) {
- var tick = sliderGroup.selectAll('rect.' + constants.tickRectClass)
- .data(sliderOpts._visibleSteps);
var dims = sliderOpts._dims;
- tick.enter().append('rect')
- .classed(constants.tickRectClass, true);
+ var tick = sliderGroup.selectAll('rect.' + constants.tickRectClass)
+ .data(sliderOpts._visibleSteps)
+ .enter()
+ .append('rect');
tick.exit().remove();
- tick.attr({
- width: sliderOpts.tickwidth + 'px',
- 'shape-rendering': 'crispEdges'
- });
+ tick
+ .classed(constants.tickRectClass, true)
+ .attrs({
+ width: sliderOpts.tickwidth + 'px',
+ 'shape-rendering': 'crispEdges'
+ });
tick.each(function(d, i) {
var isMajor = i % dims.labelStride === 0;
var item = d3.select(this);
item
- .attr({height: isMajor ? sliderOpts.ticklen : sliderOpts.minorticklen})
+ .attrs({height: isMajor ? sliderOpts.ticklen : sliderOpts.minorticklen})
.call(Color.fill, isMajor ? sliderOpts.tickcolor : sliderOpts.tickcolor);
Drawing.setTranslate(item,
@@ -599,7 +607,7 @@ function drawTouchRect(sliderGroup, gd, sliderOpts) {
.style('pointer-events', 'all');
});
- rect.attr({
+ rect.attrs({
width: dims.inputAreaLength,
height: Math.max(dims.inputAreaWidth, constants.tickOffset + sliderOpts.ticklen + dims.labelHeight)
})
@@ -614,7 +622,7 @@ function drawRail(sliderGroup, sliderOpts) {
var computedLength = dims.inputAreaLength - constants.railInset * 2;
var rect = Lib.ensureSingle(sliderGroup, 'rect', constants.railRectClass);
- rect.attr({
+ rect.attrs({
width: computedLength,
height: constants.railWidth,
rx: constants.railRadius,
diff --git a/src/components/titles/index.js b/src/components/titles/index.js
index 3a260108d67..3ea01ed7239 100644
--- a/src/components/titles/index.js
+++ b/src/components/titles/index.js
@@ -1,6 +1,6 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var isNumeric = require('fast-isnumeric');
var Plots = require('../../plots/plots');
@@ -101,18 +101,22 @@ function draw(gd, titleClass, options) {
}
var el = group.selectAll('text')
- .data(elShouldExist ? [0] : []);
- el.enter().append('text');
- el.text(txt)
+ .data(elShouldExist ? [0] : [])
+ .enter()
+ .append('text');
+
+ el.exit().remove();
+
+ if(!elShouldExist) return group;
+
+ el
+ .text(txt)
// this is hacky, but convertToTspans uses the class
// to determine whether to rotate mathJax...
// so we need to clear out any old class and put the
// correct one (only relevant for colorbars, at least
// for now) - ie don't use .classed
.attr('class', titleClass);
- el.exit().remove();
-
- if(!elShouldExist) return group;
function titleLayout(titleEl) {
Lib.syncOrAsync([drawTitle, scootTitle], titleEl);
@@ -135,23 +139,23 @@ function draw(gd, titleClass, options) {
titleEl.attr('transform', transformVal);
- titleEl.style({
+ titleEl.styles({
'font-family': fontFamily,
'font-size': d3.round(fontSize, 2) + 'px',
fill: Color.rgb(fontColor),
opacity: opacity * Color.opacity(fontColor),
'font-weight': Plots.fontWeight
})
- .attr(attributes)
- .call(svgTextUtils.convertToTspans, gd);
+ .attrs(attributes)
+ .each(function() { svgTextUtils.convertToTspans(d3.select(this), gd); });
return Plots.previousPromises(gd);
}
function scootTitle(titleElIn) {
- var titleGroup = d3.select(titleElIn.node().parentNode);
-
if(avoid && avoid.selection && avoid.side && txt) {
+ var titleGroup = d3.select(titleElIn.node().parentNode);
+
titleGroup.attr('transform', null);
// move toward avoid.side (= left, right, top, bottom) if needed
diff --git a/src/components/updatemenus/draw.js b/src/components/updatemenus/draw.js
index 826d686fdb5..709eacbe889 100644
--- a/src/components/updatemenus/draw.js
+++ b/src/components/updatemenus/draw.js
@@ -1,6 +1,6 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var Plots = require('../../plots/plots');
var Color = require('../color');
@@ -50,13 +50,10 @@ module.exports = function draw(gd) {
}
// draw update menu container
- var menus = fullLayout._menulayer
- .selectAll('g.' + constants.containerClassName)
- .data(menuData.length > 0 ? [0] : []);
-
- menus.enter().append('g')
- .classed(constants.containerClassName, true)
- .style('cursor', 'pointer');
+ var menus = fullLayout._menulayer.selectAll('g.' + constants.containerClassName)
+ .data(menuData.length > 0 ? [0] : [])
+ .enter()
+ .append('g');
menus.exit().each(function() {
// Most components don't need to explicitly remove autoMargin, because
@@ -68,14 +65,20 @@ module.exports = function draw(gd) {
.each(clearAutoMargin);
}).remove();
+ menus
+ .classed(constants.containerClassName, true)
+ .style('cursor', 'pointer');
+
// return early if no update menus are visible
if(menuData.length === 0) return;
// join header group
var headerGroups = menus.selectAll('g.' + constants.headerGroupClassName)
- .data(menuData, keyFunction);
+ .data(menuData, keyFunction)
+ .enter()
+ .append('g');
- headerGroups.enter().append('g')
+ headerGroups
.classed(constants.headerGroupClassName, true);
// draw dropdown button container
@@ -191,7 +194,7 @@ function drawHeader(gd, gHeader, gButton, scrollBox, menuOpts) {
.text(constants.arrowSymbol[menuOpts.direction]);
});
- arrow.attr({
+ arrow.attrs({
x: dims.headerWidth - constants.arrowOffsetX + menuOpts.pad.l,
y: dims.headerHeight / 2 + constants.textOffsetY + menuOpts.pad.t
});
@@ -232,9 +235,11 @@ function drawButtons(gd, gHeader, gButton, scrollBox, menuOpts) {
var klass = menuOpts.type === 'dropdown' ? constants.dropdownButtonClassName : constants.buttonClassName;
var buttons = gButton.selectAll('g.' + klass)
- .data(Lib.filterVisible(buttonData));
+ .data(Lib.filterVisible(buttonData))
+ .enter()
+ .append('g');
- var enter = buttons.enter().append('g')
+ var enter = buttons
.classed(klass, true);
var exit = buttons.exit();
@@ -294,7 +299,7 @@ function drawButtons(gd, gHeader, gButton, scrollBox, menuOpts) {
.call(setItemPosition, menuOpts, posOpts);
button.on('click', function() {
- // skip `dragend` events
+ // skip `end` events
if(d3.event.defaultPrevented) return;
if(buttonOpts.execute) {
@@ -411,7 +416,7 @@ function drawItem(item, menuOpts, itemOpts, gd) {
function drawItemRect(item, menuOpts) {
var rect = Lib.ensureSingle(item, 'rect', constants.itemRectClassName, function(s) {
- s.attr({
+ s.attrs({
rx: constants.rx,
ry: constants.ry,
'shape-rendering': 'crispEdges'
@@ -425,7 +430,7 @@ function drawItemRect(item, menuOpts) {
function drawItemText(item, menuOpts, itemOpts, gd) {
var text = Lib.ensureSingle(item, 'text', constants.itemTextClassName, function(s) {
- s.attr({
+ s.attrs({
'text-anchor': 'start',
'data-notex': 1
});
@@ -479,9 +484,11 @@ function findDimensions(gd, menuOpts) {
};
var fakeButtons = Drawing.tester.selectAll('g.' + constants.dropdownButtonClassName)
- .data(Lib.filterVisible(menuOpts.buttons));
+ .data(Lib.filterVisible(menuOpts.buttons))
+ .enter()
+ .append('g');
- fakeButtons.enter().append('g')
+ fakeButtons
.classed(constants.dropdownButtonClassName, true);
var isVertical = ['up', 'down'].indexOf(menuOpts.direction) !== -1;
@@ -610,7 +617,7 @@ function setItemPosition(item, menuOpts, posOpts, overrideOpts) {
var isVertical = ['up', 'down'].indexOf(menuOpts.direction) !== -1;
var finalHeight = overrideOpts.height || (isVertical ? dims.heights[index] : dims.height1);
- rect.attr({
+ rect.attrs({
x: 0,
y: 0,
width: overrideOpts.width || (isVertical ? dims.width1 : dims.widths[index]),
diff --git a/src/components/updatemenus/scrollbox.js b/src/components/updatemenus/scrollbox.js
index 1b116d3392f..60d14508654 100644
--- a/src/components/updatemenus/scrollbox.js
+++ b/src/components/updatemenus/scrollbox.js
@@ -2,7 +2,7 @@
module.exports = ScrollBox;
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var Color = require('../color');
var Drawing = require('../drawing');
@@ -30,17 +30,20 @@ function ScrollBox(gd, container, id) {
this.vbar = null; // vertical scrollbar D3 selection
// element to capture pointer events
- this.bg = this.container.selectAll('rect.scrollbox-bg').data([0]);
+ this.bg = this.container.selectAll('rect.scrollbox-bg')
+ .data([0])
+ .enter()
+ .append('rect');
this.bg.exit()
.on('.drag', null)
.on('wheel', null)
.remove();
- this.bg.enter().append('rect')
+ this.bg
.classed('scrollbox-bg', true)
.style('pointer-events', 'all')
- .attr({
+ .attrs({
opacity: 0,
x: 0,
y: 0,
@@ -147,19 +150,21 @@ ScrollBox.prototype.enable = function enable(position, translateX, translateY) {
if(hbarT + hbarH > fullHeight) hbarT = fullHeight - hbarH;
- var hbar = this.container.selectAll('rect.scrollbar-horizontal').data(
- (needsHorizontalScrollBar) ? [0] : []);
+ var hbar = this.container.selectAll('rect.scrollbar-horizontal')
+ .data((needsHorizontalScrollBar) ? [0] : [])
+ .enter()
+ .append('rect');
hbar.exit()
.on('.drag', null)
.remove();
- hbar.enter().append('rect')
+ hbar
.classed('scrollbar-horizontal', true)
.call(Color.fill, ScrollBox.barColor);
if(needsHorizontalScrollBar) {
- this.hbar = hbar.attr({
+ this.hbar = hbar.attrs({
'rx': ScrollBox.barRadius,
'ry': ScrollBox.barRadius,
'x': hbarL,
@@ -187,19 +192,21 @@ ScrollBox.prototype.enable = function enable(position, translateX, translateY) {
if(vbarL + vbarW > fullWidth) vbarL = fullWidth - vbarW;
- var vbar = this.container.selectAll('rect.scrollbar-vertical').data(
- (needsVerticalScrollBar) ? [0] : []);
+ var vbar = this.container.selectAll('rect.scrollbar-vertical')
+ .data((needsVerticalScrollBar) ? [0] : [])
+ .enter()
+ .append('rect');
vbar.exit()
.on('.drag', null)
.remove();
- vbar.enter().append('rect')
+ vbar
.classed('scrollbar-vertical', true)
.call(Color.fill, ScrollBox.barColor);
if(needsVerticalScrollBar) {
- this.vbar = vbar.attr({
+ this.vbar = vbar.attrs({
'rx': ScrollBox.barRadius,
'ry': ScrollBox.barRadius,
'x': vbarL,
@@ -225,16 +232,18 @@ ScrollBox.prototype.enable = function enable(position, translateX, translateY) {
var clipB = (needsHorizontalScrollBar) ? boxB + hbarH + 0.5 : boxB + 0.5;
var clipPath = fullLayout._topdefs.selectAll('#' + clipId)
- .data((needsHorizontalScrollBar || needsVerticalScrollBar) ? [0] : []);
+ .data((needsHorizontalScrollBar || needsVerticalScrollBar) ? [0] : [])
+ .enter()
+ .append('clipPath');
clipPath.exit().remove();
- clipPath.enter()
- .append('clipPath').attr('id', clipId)
+ clipPath
+ .attr('id', clipId)
.append('rect');
if(needsHorizontalScrollBar || needsVerticalScrollBar) {
- this._clipRect = clipPath.select('rect').attr({
+ this._clipRect = clipPath.select('rect').attrs({
x: Math.floor(clipL),
y: Math.floor(clipT),
width: Math.ceil(clipR) - Math.floor(clipL),
@@ -243,14 +252,14 @@ ScrollBox.prototype.enable = function enable(position, translateX, translateY) {
this.container.call(Drawing.setClipUrl, clipId, this.gd);
- this.bg.attr({
+ this.bg.attrs({
x: l,
y: t,
width: w,
height: h
});
} else {
- this.bg.attr({
+ this.bg.attrs({
width: 0,
height: 0
});
@@ -263,8 +272,8 @@ ScrollBox.prototype.enable = function enable(position, translateX, translateY) {
// set up drag listeners (if scroll bars are needed)
if(needsHorizontalScrollBar || needsVerticalScrollBar) {
- var onBoxDrag = d3.behavior.drag()
- .on('dragstart', function() {
+ var onBoxDrag = d3.drag()
+ .on('start', function() {
d3.event.sourceEvent.preventDefault();
})
.on('drag', this._onBoxDrag.bind(this));
@@ -275,8 +284,8 @@ ScrollBox.prototype.enable = function enable(position, translateX, translateY) {
.on('.drag', null)
.call(onBoxDrag);
- var onBarDrag = d3.behavior.drag()
- .on('dragstart', function() {
+ var onBarDrag = d3.drag()
+ .on('start', function() {
d3.event.sourceEvent.preventDefault();
d3.event.sourceEvent.stopPropagation();
})
@@ -306,7 +315,7 @@ ScrollBox.prototype.enable = function enable(position, translateX, translateY) {
*/
ScrollBox.prototype.disable = function disable() {
if(this.hbar || this.vbar) {
- this.bg.attr({
+ this.bg.attrs({
width: 0,
height: 0
});
@@ -431,7 +440,7 @@ ScrollBox.prototype.setTranslate = function setTranslate(translateX, translateY)
this._box.t - this.position.t - translateY);
if(this._clipRect) {
- this._clipRect.attr({
+ this._clipRect.attrs({
x: Math.floor(this.position.l + translateX - 0.5),
y: Math.floor(this.position.t + translateY - 0.5)
});
diff --git a/src/lib/d3.js b/src/lib/d3.js
new file mode 100644
index 00000000000..77cd07a259a
--- /dev/null
+++ b/src/lib/d3.js
@@ -0,0 +1,118 @@
+'use strict';
+
+var d3 = require('d3');
+
+// copy of d3.round from v3
+d3.round = function(x, n) {
+ return n ? Math.round(x * (n = Math.pow(10, n))) / n : Math.round(x);
+};
+
+// copy of d3.rebind from v3
+d3.rebind = function(target, source) {
+ var i = 1;
+ var n = arguments.length;
+ var method;
+ while(++i < n) target[method = arguments[i]] = _rebind(target, source, source[method]);
+ return target;
+};
+
+function _rebind(target, source, method) {
+ return function() {
+ var value = method.apply(source, arguments);
+ return value === source ? target : value;
+ };
+}
+
+// Adapt node_modules/d3-selection-multi/build/d3-selection-multi.js
+function attrsFunction(selection$$1, map) {
+ return selection$$1.each(function() {
+ var x = map.apply(this, arguments);
+ var s = d3.selection.select(this);
+ for(var name in x) s.attr(name, x[name]);
+ });
+}
+
+function attrsObject(selection$$1, map) {
+ for(var name in map) selection$$1.attr(name, map[name]);
+ return selection$$1;
+}
+
+var selectionAttrs = function(map) {
+ return (typeof map === 'function' ? attrsFunction : attrsObject)(this, map);
+};
+
+function stylesFunction(selection$$1, map, priority) {
+ return selection$$1.each(function() {
+ var x = map.apply(this, arguments);
+ var s = d3.selection.select(this);
+ for(var name in x) s.style(name, x[name], priority);
+ });
+}
+
+function stylesObject(selection$$1, map, priority) {
+ for(var name in map) selection$$1.style(name, map[name], priority);
+ return selection$$1;
+}
+
+var selectionStyles = function(map, priority) {
+ return (typeof map === 'function' ? stylesFunction : stylesObject)(this, map, priority === null ? '' : priority);
+};
+
+function propertiesFunction(selection$$1, map) {
+ return selection$$1.each(function() {
+ var x = map.apply(this, arguments);
+ var s = d3.selection.select(this);
+ for(var name in x) s.property(name, x[name]);
+ });
+}
+
+function propertiesObject(selection$$1, map) {
+ for(var name in map) selection$$1.property(name, map[name]);
+ return selection$$1;
+}
+
+var selectionProperties = function(map) {
+ return (typeof map === 'function' ? propertiesFunction : propertiesObject)(this, map);
+};
+
+function attrsFunction$1(transition$$1, map) {
+ return transition$$1.each(function() {
+ var x = map.apply(this, arguments);
+ var t = d3.selection.select(this).transition(transition$$1);
+ for(var name in x) t.attr(name, x[name]);
+ });
+}
+
+function attrsObject$1(transition$$1, map) {
+ for(var name in map) transition$$1.attr(name, map[name]);
+ return transition$$1;
+}
+
+var transitionAttrs = function(map) {
+ return (typeof map === 'function' ? attrsFunction$1 : attrsObject$1)(this, map);
+};
+
+function stylesFunction$1(transition$$1, map, priority) {
+ return transition$$1.each(function() {
+ var x = map.apply(this, arguments);
+ var t = d3.selection.select(this).transition(transition$$1);
+ for(var name in x) t.style(name, x[name], priority);
+ });
+}
+
+function stylesObject$1(transition$$1, map, priority) {
+ for(var name in map) transition$$1.style(name, map[name], priority);
+ return transition$$1;
+}
+
+var transitionStyles = function(map, priority) {
+ return (typeof map === 'function' ? stylesFunction$1 : stylesObject$1)(this, map, priority === null ? '' : priority);
+};
+
+d3.selection.prototype.attrs = selectionAttrs;
+d3.selection.prototype.styles = selectionStyles;
+d3.selection.prototype.properties = selectionProperties;
+d3.transition.prototype.attrs = transitionAttrs;
+d3.transition.prototype.styles = transitionStyles;
+
+module.exports = d3;
diff --git a/src/lib/dom.js b/src/lib/dom.js
index 6a13e80c188..51d28cc9c60 100644
--- a/src/lib/dom.js
+++ b/src/lib/dom.js
@@ -1,6 +1,6 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('./d3');
var loggers = require('./loggers');
var matrix = require('./matrix');
var mat4X4 = require('gl-mat4');
diff --git a/src/lib/geo_location_utils.js b/src/lib/geo_location_utils.js
index 04771902143..da1285df9fb 100644
--- a/src/lib/geo_location_utils.js
+++ b/src/lib/geo_location_utils.js
@@ -1,6 +1,6 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('./d3');
var countryRegex = require('country-regex');
var turfArea = require('@turf/area');
var turfCentroid = require('@turf/centroid');
@@ -12,6 +12,8 @@ var isPlainObject = require('./is_plain_object');
var nestedProperty = require('./nested_property');
var polygon = require('./polygon');
+var getTraceFromCd = require('./trace_from_cd');
+
// make list of all country iso3 ids from at runtime
var countryIds = Object.keys(countryRegex);
@@ -194,7 +196,7 @@ function getTraceGeojson(trace) {
}
function extractTraceFeature(calcTrace) {
- var trace = calcTrace[0].trace;
+ var trace = getTraceFromCd(calcTrace);
var geojsonIn = getTraceGeojson(trace);
if(!geojsonIn) return false;
diff --git a/src/lib/geojson_utils.js b/src/lib/geojson_utils.js
index 599f7d85e6b..5ba108abb87 100644
--- a/src/lib/geojson_utils.js
+++ b/src/lib/geojson_utils.js
@@ -1,5 +1,6 @@
'use strict';
+var getTraceFromCd = require('./trace_from_cd');
var BADNUM = require('../constants/numerical').BADNUM;
/**
@@ -14,7 +15,7 @@ var BADNUM = require('../constants/numerical').BADNUM;
*
*/
exports.calcTraceToLineCoords = function(calcTrace) {
- var trace = calcTrace[0].trace;
+ var trace = getTraceFromCd(calcTrace);
var connectgaps = trace.connectgaps;
var coords = [];
diff --git a/src/lib/index.js b/src/lib/index.js
index 5d97f2cfc89..cd2f123d384 100644
--- a/src/lib/index.js
+++ b/src/lib/index.js
@@ -1,16 +1,20 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('./d3');
var utcFormat = require('d3-time-format').utcFormat;
var d3Format = require('d3-format').format;
var isNumeric = require('fast-isnumeric');
+var getTraceFromCd = require('./trace_from_cd');
var numConstants = require('../constants/numerical');
var MAX_SAFE = numConstants.FP_SAFE;
var MIN_SAFE = -MAX_SAFE;
var BADNUM = numConstants.BADNUM;
-var lib = module.exports = {};
+var lib = module.exports = {
+ d3: d3,
+ getTraceFromCd: getTraceFromCd
+};
lib.adjustFormat = function adjustFormat(formatStr) {
if(
@@ -278,6 +282,12 @@ lib.cancelTransition = function(selection) {
return selection.transition().duration(0);
};
+lib.whichD3EaseFn = function(transitionOpts) {
+ return transitionOpts && transitionOpts.easing ?
+ d3['ease' + lib.titleCase(transitionOpts.easing)] :
+ function() {};
+};
+
// constrain - restrict a number v to be between v0 and v1
lib.constrain = function(v, v0, v1) {
if(v0 > v1) return Math.max(v1, Math.min(v0, v));
diff --git a/src/lib/make_trace_groups.js b/src/lib/make_trace_groups.js
index b967287c64e..b59c53751a6 100644
--- a/src/lib/make_trace_groups.js
+++ b/src/lib/make_trace_groups.js
@@ -1,6 +1,6 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('./d3');
/**
* General helper to manage trace groups based on calcdata
@@ -15,12 +15,13 @@ var d3 = require('@plotly/d3');
*/
module.exports = function makeTraceGroups(traceLayer, cdModule, cls) {
var traces = traceLayer.selectAll('g.' + cls.replace(/\s/g, '.'))
- .data(cdModule, function(cd) { return cd[0].trace.uid; });
+ .data(cdModule, function(cd) { return cd[0].trace.uid; })
+ .enter()
+ .append('g');
traces.exit().remove();
- traces.enter().append('g')
- .attr('class', cls);
+ traces.attr('class', cls);
traces.order();
diff --git a/src/lib/notifier.js b/src/lib/notifier.js
index b675787dbab..7f3d423b890 100644
--- a/src/lib/notifier.js
+++ b/src/lib/notifier.js
@@ -1,6 +1,6 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('./d3');
var isNumeric = require('fast-isnumeric');
var NOTEDATA = [];
@@ -21,14 +21,18 @@ module.exports = function(text, displayLength) {
if(isNumeric(displayLength)) ts = displayLength;
else if(displayLength === 'long') ts = 3000;
- var notifierContainer = d3.select('body')
- .selectAll('.plotly-notifier')
- .data([0]);
- notifierContainer.enter()
- .append('div')
+ var notifierContainer = d3.select('body').selectAll('.plotly-notifier')
+ .data([0])
+ .enter()
+ .append('div');
+
+ notifierContainer
.classed('plotly-notifier', true);
- var notes = notifierContainer.selectAll('.notifier-note').data(NOTEDATA);
+ var notes = notifierContainer.selectAll('.notifier-note')
+ .data(NOTEDATA)
+ .enter()
+ .append('div');
function killNote(transition) {
transition
@@ -41,7 +45,7 @@ module.exports = function(text, displayLength) {
});
}
- notes.enter().append('div')
+ notes
.classed('notifier-note', true)
.style('opacity', 0)
.each(function(thisText) {
diff --git a/src/lib/svg_text_utils.js b/src/lib/svg_text_utils.js
index caa6b13e076..a773cff8a8f 100644
--- a/src/lib/svg_text_utils.js
+++ b/src/lib/svg_text_utils.js
@@ -2,7 +2,7 @@
/* global MathJax:false */
-var d3 = require('@plotly/d3');
+var d3 = require('./d3');
var Lib = require('../lib');
var strTranslate = Lib.strTranslate;
@@ -29,7 +29,7 @@ exports.convertToTspans = function(_context, gd, _callback) {
parent.selectAll('svg.' + svgClass).remove();
parent.selectAll('g.' + svgClass + '-group').remove();
_context.style('display', null)
- .attr({
+ .attrs({
// some callers use data-unformatted *from the element* in 'cancel'
// so we need it here even if we're going to turn it into math
// these two (plus style and text-anchor attributes) form the key we're
@@ -80,7 +80,7 @@ exports.convertToTspans = function(_context, gd, _callback) {
var mathjaxGroup = parent.append('g')
.classed(svgClass + '-group', true)
- .attr({
+ .attrs({
'pointer-events': 'none',
'data-unformatted': str,
'data-math': 'Y'
@@ -97,16 +97,16 @@ exports.convertToTspans = function(_context, gd, _callback) {
var w0 = _svgBBox.width;
var h0 = _svgBBox.height;
- newSvg.attr({
+ newSvg.attrs({
'class': svgClass,
height: h0,
preserveAspectRatio: 'xMinYMin meet'
})
- .style({overflow: 'visible', 'pointer-events': 'none'});
+ .styles({overflow: 'visible', 'pointer-events': 'none'});
var fill = _context.node().style.fill || 'black';
var g = newSvg.select('g');
- g.attr({fill: fill, stroke: fill});
+ g.attrs({fill: fill, stroke: fill});
var bb = g.node().getBoundingClientRect();
var w = bb.width;
@@ -129,7 +129,7 @@ exports.convertToTspans = function(_context, gd, _callback) {
var dy = -textHeight / 4;
if(svgClass[0] === 'y') {
- mathjaxGroup.attr({
+ mathjaxGroup.attrs({
transform: 'rotate(' + [-90, x, y] +
')' + strTranslate(-w / 2, dy - h / 2)
});
@@ -148,7 +148,7 @@ exports.convertToTspans = function(_context, gd, _callback) {
y = y + dy - h / 2;
}
- newSvg.attr({
+ newSvg.attrs({
x: x,
y: y
});
@@ -207,9 +207,9 @@ function texToSVG(_texString, _config, _callback) {
function() {
var randomID = 'math-output-' + Lib.randstr({}, 64);
tmpDiv = d3.select('body').append('div')
- .attr({id: randomID})
- .style({visibility: 'hidden', position: 'absolute'})
- .style({'font-size': _config.fontSize + 'px'})
+ .attrs({id: randomID})
+ .styles({visibility: 'hidden', position: 'absolute'})
+ .styles({'font-size': _config.fontSize + 'px'})
.text(cleanEscapesForTex(_texString));
return MathJax.Hub.Typeset(tmpDiv.node());
@@ -483,7 +483,7 @@ function buildSVGText(containerNode, str) {
currentLine++;
var lineNode = document.createElementNS(xmlnsNamespaces.svg, 'tspan');
- d3.select(lineNode).attr({
+ d3.select(lineNode).attrs({
class: 'line',
dy: (currentLine * LINE_SPACING) + 'em'
});
@@ -545,7 +545,7 @@ function buildSVGText(containerNode, str) {
currentNode.appendChild(newNode);
}
- d3.select(newNode).attr(nodeAttrs);
+ d3.select(newNode).attrs(nodeAttrs);
currentNode = nodeSpec.node = newNode;
nodeStack.push(nodeSpec);
@@ -702,7 +702,7 @@ exports.sanitizeHTML = function sanitizeHTML(str) {
var newNode = document.createElement(tagType);
currentNode.appendChild(newNode);
- d3.select(newNode).attr(nodeAttrs);
+ d3.select(newNode).attrs(nodeAttrs);
currentNode = newNode;
nodeStack.push(newNode);
@@ -740,7 +740,7 @@ exports.positionText = function positionText(s, x, y) {
var thisY = setOrGet('y', y);
if(this.nodeName === 'text') {
- text.selectAll('tspan.line').attr({x: thisX, y: thisY});
+ text.selectAll('tspan.line').attrs({x: thisX, y: thisY});
}
});
};
@@ -783,7 +783,7 @@ function alignHTMLWith(_base, container, options) {
y0 = transformedCoords[1];
}
- this.style({
+ this.styles({
top: y0 + 'px',
left: x0 + 'px',
'z-index': 1000
@@ -825,20 +825,20 @@ exports.makeEditable = function(context, options) {
var dispatch = d3.dispatch('edit', 'input', 'cancel');
var handlerElement = _delegate || context;
- context.style({'pointer-events': _delegate ? 'none' : 'all'});
+ context.styles({'pointer-events': _delegate ? 'none' : 'all'});
if(context.size() !== 1) throw new Error('boo');
function handleClick() {
appendEditable();
- context.style({opacity: 0});
+ context.styles({opacity: 0});
// also hide any mathjax svg
var svgClass = handlerElement.attr('class');
var mathjaxClass;
if(svgClass) mathjaxClass = '.' + svgClass.split(' ')[0] + '-math-group';
else mathjaxClass = '[class*=-math-group]';
if(mathjaxClass) {
- d3.select(context.node().parentNode).select(mathjaxClass).style({opacity: 0});
+ d3.select(context.node().parentNode).select(mathjaxClass).styles({opacity: 0});
}
}
@@ -863,7 +863,7 @@ exports.makeEditable = function(context, options) {
if(initialText === undefined) initialText = context.attr('data-unformatted');
div.classed('plugin-editable editable', true)
- .style({
+ .styles({
position: 'absolute',
'font-family': cStyle.fontFamily || 'Arial',
'font-size': fontSize,
@@ -875,19 +875,19 @@ exports.makeEditable = function(context, options) {
padding: '0',
'box-sizing': 'border-box'
})
- .attr({contenteditable: true})
+ .attrs({contenteditable: true})
.text(initialText)
.call(alignHTMLWith(context, container, options))
.on('blur', function() {
gd._editing = false;
context.text(this.textContent)
- .style({opacity: 1});
+ .styles({opacity: 1});
var svgClass = d3.select(this).attr('class');
var mathjaxClass;
if(svgClass) mathjaxClass = '.' + svgClass.split(' ')[0] + '-math-group';
else mathjaxClass = '[class*=-math-group]';
if(mathjaxClass) {
- d3.select(context.node().parentNode).select(mathjaxClass).style({opacity: 0});
+ d3.select(context.node().parentNode).select(mathjaxClass).styles({opacity: 0});
}
var text = this.textContent;
d3.select(this).transition().duration(0).remove();
@@ -905,9 +905,9 @@ exports.makeEditable = function(context, options) {
.on('keyup', function() {
if(d3.event.which === 27) {
gd._editing = false;
- context.style({opacity: 1});
+ context.styles({opacity: 1});
d3.select(this)
- .style({opacity: 0})
+ .styles({opacity: 0})
.on('blur', function() { return false; })
.transition().remove();
dispatch.cancel.call(context, this.textContent);
diff --git a/src/lib/trace_from_cd.js b/src/lib/trace_from_cd.js
new file mode 100644
index 00000000000..31bc28c7a82
--- /dev/null
+++ b/src/lib/trace_from_cd.js
@@ -0,0 +1,13 @@
+'use strict';
+
+function getTraceFromCd(cd) {
+ var trace = cd.trace;
+ if(trace) return trace;
+
+ for(var i = 0; i < cd.length; i++) {
+ trace = cd[i].trace;
+ if(trace) return trace;
+ }
+}
+
+module.exports = getTraceFromCd;
diff --git a/src/plot_api/plot_api.js b/src/plot_api/plot_api.js
index 1a9386a3915..cf84a980146 100644
--- a/src/plot_api/plot_api.js
+++ b/src/plot_api/plot_api.js
@@ -1,6 +1,6 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../lib/d3');
var isNumeric = require('fast-isnumeric');
var hasHover = require('has-hover');
@@ -195,25 +195,26 @@ function _doPlot(gd, data, layout, config) {
}
if(!fullLayout._glcanvas && fullLayout._has('gl')) {
- fullLayout._glcanvas = fullLayout._glcontainer.selectAll('.gl-canvas').data([{
- key: 'contextLayer',
- context: true,
- pick: false
- }, {
- key: 'focusLayer',
- context: false,
- pick: false
- }, {
- key: 'pickLayer',
- context: false,
- pick: true
- }], function(d) { return d.key; });
-
- fullLayout._glcanvas.enter().append('canvas')
+ fullLayout._glcanvas = fullLayout._glcontainer.selectAll('.gl-canvas')
+ .data([{
+ key: 'contextLayer',
+ context: true,
+ pick: false
+ }, {
+ key: 'focusLayer',
+ context: false,
+ pick: false
+ }, {
+ key: 'pickLayer',
+ context: false,
+ pick: true
+ }], function(d) { return d.key; })
+ .enter()
+ .append('canvas')
.attr('class', function(d) {
return 'gl-canvas gl-canvas-' + d.key.replace('Layer', '');
})
- .style({
+ .styles({
position: 'absolute',
top: 0,
left: 0,
@@ -3639,15 +3640,18 @@ function makePlotFramework(gd) {
fullLayout._calcInverseTransform(gd);
// Plot container
- fullLayout._container = gd3.selectAll('.plot-container').data([0]);
- fullLayout._container.enter()
+ fullLayout._container = gd3.selectAll('.plot-container')
+ .data([0])
+ .enter()
.insert('div', ':first-child')
.classed('plot-container', true)
.classed('plotly', true);
// Make the svg container
- fullLayout._paperdiv = fullLayout._container.selectAll('.svg-container').data([0]);
- fullLayout._paperdiv.enter().append('div')
+ fullLayout._paperdiv = fullLayout._container.selectAll('.svg-container')
+ .data([0])
+ .enter()
+ .append('div')
.classed('user-select-none', true)
.classed('svg-container', true)
.style('position', 'relative');
@@ -3659,9 +3663,9 @@ function makePlotFramework(gd) {
// explicitly delete anything
// FIXME: parcoords reuses this object, not the best pattern
fullLayout._glcontainer = fullLayout._paperdiv.selectAll('.gl-container')
- .data([{}]);
-
- fullLayout._glcontainer.enter().append('div')
+ .data([{}])
+ .enter()
+ .append('div')
.classed('gl-container', true);
fullLayout._paperdiv.selectAll('.main-svg').remove();
@@ -3674,6 +3678,7 @@ function makePlotFramework(gd) {
.classed('main-svg', true);
fullLayout._modebardiv = fullLayout._paperdiv.append('div');
+
delete fullLayout._modeBar;
fullLayout._hoverpaper = fullLayout._paperdiv.append('svg')
@@ -3688,7 +3693,7 @@ function makePlotFramework(gd) {
}
fullLayout._paperdiv.selectAll('.main-svg')
- .attr(xmlnsNamespaces.svgAttrs);
+ .attrs(xmlnsNamespaces.svgAttrs);
fullLayout._defs = fullLayout._paper.append('defs')
.attr('id', 'defs-' + fullLayout._uid);
diff --git a/src/plot_api/subroutines.js b/src/plot_api/subroutines.js
index 20a7a59f85a..96ec3b463b0 100644
--- a/src/plot_api/subroutines.js
+++ b/src/plot_api/subroutines.js
@@ -1,6 +1,6 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../lib/d3');
var Registry = require('../registry');
var Plots = require('../plots/plots');
@@ -49,7 +49,7 @@ function lsInner(gd) {
var axList = Axes.list(gd, '', true);
var i, subplot, plotinfo, ax, xa, ya;
- fullLayout._paperdiv.style({
+ fullLayout._paperdiv.styles({
width: (gd._context.responsive && fullLayout.autosize && !gd._context._hasZeroWidth && !gd.layout.width) ? '100%' : fullLayout.width + 'px',
height: (gd._context.responsive && fullLayout.autosize && !gd._context._hasZeroHeight && !gd.layout.height) ? '100%' : fullLayout.height + 'px'
})
@@ -153,32 +153,32 @@ function lsInner(gd) {
// now create all the lower-layer backgrounds at once now that
// we have the list of subplots that need them
var lowerBackgrounds = fullLayout._bgLayer.selectAll('.bg')
- .data(lowerBackgroundIDs);
+ .data(lowerBackgroundIDs)
+ .enter()
+ .append('rect');
- lowerBackgrounds.enter().append('rect')
+ lowerBackgrounds.exit().remove();
+
+ lowerBackgrounds
.classed('bg', true);
- lowerBackgrounds.exit().remove();
+ lowerBackgrounds.each(function(subplot, i) {
+ var s = d3.select(this);
- lowerBackgrounds.each(function(subplot) {
- fullLayout._plots[subplot].bg = d3.select(this);
- });
+ fullLayout._plots[subplot].bg = s;
- // style all backgrounds
- for(i = 0; i < backgroundIds.length; i++) {
+ // style all backgrounds
plotinfo = fullLayout._plots[backgroundIds[i]];
xa = plotinfo.xaxis;
ya = plotinfo.yaxis;
- if(plotinfo.bg && xa._offset !== undefined && ya._offset !== undefined) {
- plotinfo.bg
- .call(Drawing.setRect,
- xa._offset - pad, ya._offset - pad,
- xa._length + 2 * pad, ya._length + 2 * pad)
- .call(Color.fill, fullLayout.plot_bgcolor)
- .style('stroke-width', 0);
- }
- }
+ Drawing.setRect(s,
+ xa._offset - pad, ya._offset - pad,
+ xa._length + 2 * pad, ya._length + 2 * pad);
+
+ Color.fill(s, fullLayout.plot_bgcolor);
+ })
+ .style('stroke-width', 0);
if(!fullLayout._hasOnlyLargeSploms) {
for(subplot in fullLayout._plots) {
@@ -194,7 +194,7 @@ function lsInner(gd) {
.append('rect');
});
- plotinfo.clipRect = plotClip.select('rect').attr({
+ plotinfo.clipRect = plotClip.select('rect').attrs({
width: xa._length,
height: ya._length
});
diff --git a/src/plots/cartesian/autorange.js b/src/plots/cartesian/autorange.js
index d5e3a858eb1..6378ca9ab94 100644
--- a/src/plots/cartesian/autorange.js
+++ b/src/plots/cartesian/autorange.js
@@ -1,6 +1,6 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var isNumeric = require('fast-isnumeric');
var Lib = require('../../lib');
diff --git a/src/plots/cartesian/axes.js b/src/plots/cartesian/axes.js
index 6f03bfc517b..d539fb11f4a 100644
--- a/src/plots/cartesian/axes.js
+++ b/src/plots/cartesian/axes.js
@@ -1,6 +1,6 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var isNumeric = require('fast-isnumeric');
var Plots = require('../../plots/plots');
@@ -1902,17 +1902,19 @@ axes.makeClipPaths = function(gd) {
// have to use class instead
// https://groups.google.com/forum/#!topic/d3-js/6EpAzQ2gU9I
var axClips = fullLayout._clips.selectAll('.axesclip')
- .data(clipList, function(d) { return d.x._id + d.y._id; });
+ .data(clipList, function(d) { return d.x._id + d.y._id; })
+ .enter()
+ .append('clipPath');
- axClips.enter().append('clipPath')
+ axClips.exit().remove();
+
+ axClips
.classed('axesclip', true)
.attr('id', function(d) { return 'clip' + fullLayout._uid + d.x._id + d.y._id; })
- .append('rect');
-
- axClips.exit().remove();
+ .append('rect');
axClips.each(function(d) {
- d3.select(this).select('rect').attr({
+ d3.select(this).select('rect').attrs({
x: d.x._offset || 0,
y: d.y._offset || 0,
width: d.x._length || 1,
@@ -2801,11 +2803,13 @@ axes.drawTicks = function(gd, ax, opts) {
}
var ticks = opts.layer.selectAll('path.' + cls)
- .data(ax.ticks ? vals : [], tickDataFn);
+ .data(ax.ticks ? vals : [], tickDataFn)
+ .enter()
+ .append('path');
ticks.exit().remove();
- ticks.enter().append('path')
+ ticks
.classed(cls, 1)
.classed('ticks', 1)
.classed('crisp', opts.crisp !== false)
@@ -2864,11 +2868,13 @@ axes.drawGrid = function(gd, ax, opts) {
}
var grid = opts.layer.selectAll('path.' + cls)
- .data(vals, tickDataFn);
+ .data(vals, tickDataFn)
+ .enter()
+ .append('path');
grid.exit().remove();
- grid.enter().append('path')
+ grid
.classed(cls, 1)
.classed('crisp', opts.crisp !== false);
@@ -2909,11 +2915,13 @@ axes.drawZeroLine = function(gd, ax, opts) {
var show = axes.shouldShowZeroLine(gd, ax, opts.counterAxis);
var zl = opts.layer.selectAll('path.' + cls)
- .data(show ? [{x: 0, id: ax._id}] : []);
+ .data(show ? [{x: 0, id: ax._id}] : [])
+ .enter()
+ .append('path');
zl.exit().remove();
- zl.enter().append('path')
+ zl
.classed(cls, 1)
.classed('zl', 1)
.classed('crisp', opts.crisp !== false)
@@ -2924,9 +2932,8 @@ axes.drawZeroLine = function(gd, ax, opts) {
opts.layer.selectAll('path').sort(function(da, db) {
return idSort(da.id, db.id);
});
- });
-
- zl.attr('transform', opts.transFn)
+ })
+ .attr('transform', opts.transFn)
.attr('d', opts.path)
.call(Color.stroke, ax.zerolinecolor || Color.defaultLine)
.style('stroke-width', Drawing.crispRound(gd, ax.zerolinewidth, ax._gw || 1) + 'px')
@@ -2972,45 +2979,47 @@ axes.drawLabels = function(gd, ax, opts) {
var tickAngle = opts.secondary ? 0 : ax.tickangle;
var prevAngle = (ax._prevTickAngles || {})[cls];
+ var labelsReady = [];
+
var tickLabels = opts.layer.selectAll('g.' + cls)
- .data(ax.showticklabels ? vals : [], tickDataFn);
+ .data(ax.showticklabels ? vals : [], tickDataFn)
+ .enter()
+ .append('g');
- var labelsReady = [];
+ tickLabels.exit().remove();
- tickLabels.enter().append('g')
+ tickLabels
.classed(cls, 1)
.append('text')
- // only so tex has predictable alignment that we can
- // alter later
- .attr('text-anchor', 'middle')
- .each(function(d) {
- var thisLabel = d3.select(this);
- var newPromise = gd._promises.length;
-
- thisLabel
- .call(svgTextUtils.positionText, labelFns.xFn(d), labelFns.yFn(d))
- .call(Drawing.font, d.font, d.fontSize, d.fontColor)
- .text(d.text)
- .call(svgTextUtils.convertToTspans, gd);
-
- if(gd._promises[newPromise]) {
- // if we have an async label, we'll deal with that
- // all here so take it out of gd._promises and
- // instead position the label and promise this in
- // labelsReady
- labelsReady.push(gd._promises.pop().then(function() {
- positionLabels(thisLabel, tickAngle);
- }));
- } else {
- // sync label: just position it now.
+ // only so tex has predictable alignment that we can
+ // alter later
+ .attr('text-anchor', 'middle')
+ .each(function(d) {
+ var thisLabel = d3.select(this);
+ var newPromise = gd._promises.length;
+
+ thisLabel
+ .call(svgTextUtils.positionText, labelFns.xFn(d), labelFns.yFn(d))
+ .call(Drawing.font, d.font, d.fontSize, d.fontColor)
+ .text(d.text)
+ .call(svgTextUtils.convertToTspans, gd);
+
+ if(gd._promises[newPromise]) {
+ // if we have an async label, we'll deal with that
+ // all here so take it out of gd._promises and
+ // instead position the label and promise this in
+ // labelsReady
+ labelsReady.push(gd._promises.pop().then(function() {
positionLabels(thisLabel, tickAngle);
- }
- });
+ }));
+ } else {
+ // sync label: just position it now.
+ positionLabels(thisLabel, tickAngle);
+ }
+ });
hideCounterAxisInsideTickLabels(ax, [TICK_TEXT]);
- tickLabels.exit().remove();
-
if(opts.repositionOnUpdate) {
tickLabels.each(function(d) {
d3.select(this).select('text')
@@ -3041,7 +3050,7 @@ axes.drawLabels = function(gd, ax, opts) {
if(mathjaxGroup.empty()) {
var thisText = thisLabel.select('text');
- thisText.attr({
+ thisText.attrs({
transform: transform,
'text-anchor': anchor
});
@@ -3362,17 +3371,17 @@ function drawDividers(gd, ax, opts) {
var vals = opts.vals;
var dividers = opts.layer.selectAll('path.' + cls)
- .data(vals, tickDataFn);
+ .data(vals, tickDataFn)
+ .enter()
+ .insert('path', ':first-child');
dividers.exit().remove();
- dividers.enter().insert('path', ':first-child')
+ dividers
.classed(cls, 1)
.classed('crisp', 1)
.call(Color.stroke, ax.dividercolor)
- .style('stroke-width', Drawing.crispRound(gd, ax.dividerwidth, 1) + 'px');
-
- dividers
+ .style('stroke-width', Drawing.crispRound(gd, ax.dividerwidth, 1) + 'px')
.attr('transform', opts.transFn)
.attr('d', opts.path);
}
diff --git a/src/plots/cartesian/dragbox.js b/src/plots/cartesian/dragbox.js
index b12489e399c..76c619eb602 100644
--- a/src/plots/cartesian/dragbox.js
+++ b/src/plots/cartesian/dragbox.js
@@ -1,6 +1,6 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var Lib = require('../../lib');
var numberFormat = Lib.numberFormat;
var tinycolor = require('tinycolor2');
@@ -997,7 +997,7 @@ function makeDragBox(gd, plotinfo, x, y, w, h, ns, ew) {
function makeDragger(plotinfo, nodeName, dragClass, cursor) {
var dragger3 = Lib.ensureSingle(plotinfo.draglayer, nodeName, dragClass, function(s) {
s.classed('drag', true)
- .style({fill: 'transparent', 'stroke-width': 0})
+ .styles({fill: 'transparent', 'stroke-width': 0})
.attr('data-subplot', plotinfo.id);
});
@@ -1115,7 +1115,7 @@ function getDragCursor(nsew, dragmode, isMainDrag) {
function makeZoombox(zoomlayer, lum, xs, ys, path0) {
return zoomlayer.append('path')
.attr('class', 'zoombox')
- .style({
+ .styles({
'fill': lum > 0.2 ? 'rgba(0,0,0,0)' : 'rgba(255,255,255,0)',
'stroke-width': 0
})
@@ -1126,7 +1126,7 @@ function makeZoombox(zoomlayer, lum, xs, ys, path0) {
function makeCorners(zoomlayer, xs, ys) {
return zoomlayer.append('path')
.attr('class', 'zoombox-corners')
- .style({
+ .styles({
fill: Color.background,
stroke: Color.defaultLine,
'stroke-width': 1,
diff --git a/src/plots/cartesian/graph_interact.js b/src/plots/cartesian/graph_interact.js
index a7e08ea41dd..e5c8ab1158d 100644
--- a/src/plots/cartesian/graph_interact.js
+++ b/src/plots/cartesian/graph_interact.js
@@ -1,6 +1,6 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var Fx = require('../../components/fx');
var dragElement = require('../../components/dragelement');
diff --git a/src/plots/cartesian/index.js b/src/plots/cartesian/index.js
index 591f85c2bf5..527e8cb37d0 100644
--- a/src/plots/cartesian/index.js
+++ b/src/plots/cartesian/index.js
@@ -1,9 +1,10 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var Registry = require('../../registry');
var Lib = require('../../lib');
+var getTraceFromCd = require('../../lib/trace_from_cd');
var Plots = require('../plots');
var Drawing = require('../../components/drawing');
@@ -147,7 +148,7 @@ exports.plot = function(gd, traces, transitionOpts, makeOnCompleteCallback) {
for(var j = 0; j < calcdata.length; j++) {
var cd = calcdata[j];
- var trace = cd[0].trace;
+ var trace = getTraceFromCd(cd);
// Skip trace if whitelist provided and it's not whitelisted:
// if (Array.isArray(traces) && traces.indexOf(i) === -1) continue;
@@ -226,15 +227,17 @@ function plotOne(gd, plotinfo, cdSubplot, transitionOpts, makeOnCompleteCallback
layerData.sort(function(a, b) { return a.i - b.i; });
var layers = plotinfo.plot.selectAll('g.mlayer')
- .data(layerData, function(d) { return d.className; });
+ .data(layerData, function(d) { return d.className; })
+ .enter()
+ .append('g');
- layers.enter().append('g')
+ layers.exit().remove();
+
+ layers
.attr('class', function(d) { return d.className; })
.classed('mlayer', true)
.classed('rangeplot', plotinfo.isRangePlot);
- layers.exit().remove();
-
layers.order();
layers.each(function(d) {
@@ -346,28 +349,27 @@ exports.drawFramework = function(gd) {
var subplotData = makeSubplotData(gd);
var subplotLayers = fullLayout._cartesianlayer.selectAll('.subplot')
- .data(subplotData, String);
-
- subplotLayers.enter().append('g')
- .attr('class', function(d) { return 'subplot ' + d[0]; });
-
- subplotLayers.order();
-
- subplotLayers.exit()
- .call(purgeSubplotLayers, fullLayout);
-
- subplotLayers.each(function(d) {
- var id = d[0];
- var plotinfo = fullLayout._plots[id];
-
- plotinfo.plotgroup = d3.select(this);
- makeSubplotLayer(gd, plotinfo);
-
- // make separate drag layers for each subplot,
- // but append them to paper rather than the plot groups,
- // so they end up on top of the rest
- plotinfo.draglayer = ensureSingle(fullLayout._draggers, 'g', id);
- });
+ .data(subplotData, String)
+ .enter()
+ .append('g');
+
+ subplotLayers.exit().call(purgeSubplotLayers, fullLayout);
+
+ subplotLayers
+ .attr('class', function(d) { return 'subplot ' + d[0]; })
+ .order()
+ .each(function(d) {
+ var id = d[0];
+ var plotinfo = fullLayout._plots[id];
+
+ plotinfo.plotgroup = d3.select(this);
+ makeSubplotLayer(gd, plotinfo);
+
+ // make separate drag layers for each subplot,
+ // but append them to paper rather than the plot groups,
+ // so they end up on top of the rest
+ plotinfo.draglayer = ensureSingle(fullLayout._draggers, 'g', id);
+ });
};
exports.rangePlot = function(gd, plotinfo, cdSubplot) {
@@ -528,7 +530,8 @@ function makeSubplotLayer(gd, plotinfo) {
ensureSingleAndAddDatum(plotinfo.gridlayer, 'g', plotinfo.xaxis._id);
ensureSingleAndAddDatum(plotinfo.gridlayer, 'g', plotinfo.yaxis._id);
plotinfo.gridlayer.selectAll('g')
- .map(function(d) { return d[0]; })
+ .nodes()
+ .map(function(e) { return e.className.baseVal; })
.sort(axisIds.idSort);
}
@@ -590,7 +593,7 @@ exports.toSVG = function(gd) {
var imageData = canvas.toDataURL('image/png');
var image = imageRoot.append('svg:image');
- image.attr({
+ image.attrs({
xmlns: xmlnsNamespaces.svg,
'xlink:href': imageData,
preserveAspectRatio: 'none',
diff --git a/src/plots/cartesian/select.js b/src/plots/cartesian/select.js
index ebab65a69a8..62303528ef6 100644
--- a/src/plots/cartesian/select.js
+++ b/src/plots/cartesian/select.js
@@ -19,6 +19,7 @@ var handleEllipse = require('../../components/shapes/draw_newshape/helpers').han
var newShapes = require('../../components/shapes/draw_newshape/newshapes');
var Lib = require('../../lib');
+var getTraceFromCd = require('../../lib/trace_from_cd');
var polygon = require('../../lib/polygon');
var throttle = require('../../lib/throttle');
var getFromId = require('./axis_ids').getFromId;
@@ -84,13 +85,17 @@ function prepSelect(e, startX, startY, dragOptions, mode) {
filterPoly = filteredPolygon([[x0, y0]], constants.BENDPX);
}
- var outlines = zoomLayer.selectAll('path.select-outline-' + plotinfo.id).data(isDrawMode ? [0] : [1, 2]);
var drwStyle = fullLayout.newshape;
+ var outlines = zoomLayer.selectAll('path.select-outline-' + plotinfo.id)
+ .data(isDrawMode ? [0] : [1, 2])
+ .enter()
+ .append('path');
- outlines.enter()
- .append('path')
+ outlines.exit().remove();
+
+ outlines
.attr('class', function(d) { return 'select-outline select-outline-' + d + ' select-outline-' + plotinfo.id; })
- .style(isDrawMode ? {
+ .styles(isDrawMode ? {
opacity: drwStyle.opacity / 2,
fill: isOpenMode ? undefined : drwStyle.fillcolor,
stroke: drwStyle.line.color,
@@ -104,7 +109,7 @@ function prepSelect(e, startX, startY, dragOptions, mode) {
var corners = zoomLayer.append('path')
.attr('class', 'zoombox-corners')
- .style({
+ .styles({
fill: Color.background,
stroke: Color.defaultLine,
'stroke-width': 1
@@ -491,8 +496,8 @@ function newPointNumTester(pointSelectionDef) {
ymax: 0,
pts: [],
contains: function(pt, omitFirstEdge, pointNumber, searchInfo) {
- var idxWantedTrace = pointSelectionDef.searchInfo.cd[0].trace._expandedIndex;
- var idxActualTrace = searchInfo.cd[0].trace._expandedIndex;
+ var idxWantedTrace = getTraceFromCd(pointSelectionDef.searchInfo.cd)._expandedIndex;
+ var idxActualTrace = getTraceFromCd(searchInfo.cd)._expandedIndex;
return idxActualTrace === idxWantedTrace &&
pointNumber === pointSelectionDef.pointNumber;
},
@@ -637,7 +642,7 @@ function determineSearchTraces(gd, xAxes, yAxes, subplot) {
for(i = 0; i < gd.calcdata.length; i++) {
cd = gd.calcdata[i];
- trace = cd[0].trace;
+ trace = getTraceFromCd(cd);
if(trace.visible !== true || !trace._module || !trace._module.selectPoints) continue;
@@ -691,7 +696,7 @@ function extractClickedPtInfo(hoverData, searchTraces) {
for(i = 0; i < searchTraces.length; i++) {
searchInfo = searchTraces[i];
- if(hoverDatum.fullData._expandedIndex === searchInfo.cd[0].trace._expandedIndex) {
+ if(hoverDatum.fullData._expandedIndex === getTraceFromCd(searchInfo.cd)._expandedIndex) {
// Special case for box (and violin)
if(hoverDatum.hoverOnBox === true) {
break;
@@ -720,7 +725,7 @@ function extractClickedPtInfo(hoverData, searchTraces) {
}
function isPointOrBinSelected(clickedPtInfo) {
- var trace = clickedPtInfo.searchInfo.cd[0].trace;
+ var trace = getTraceFromCd(clickedPtInfo.searchInfo.cd);
var ptNum = clickedPtInfo.pointNumber;
var ptNums = clickedPtInfo.pointNumbers;
var ptNumsSet = ptNums.length > 0;
@@ -744,7 +749,7 @@ function isOnlyThisBinSelected(searchTraces, clickedPtInfo) {
for(i = 0; i < searchTraces.length; i++) {
searchInfo = searchTraces[i];
- if(searchInfo.cd[0].trace.selectedpoints && searchInfo.cd[0].trace.selectedpoints.length > 0) {
+ if(getTraceFromCd(searchInfo.cd).selectedpoints && getTraceFromCd(searchInfo.cd).selectedpoints.length > 0) {
tracesWithSelectedPts.push(searchInfo);
}
}
@@ -752,7 +757,7 @@ function isOnlyThisBinSelected(searchTraces, clickedPtInfo) {
if(tracesWithSelectedPts.length === 1) {
isSameTrace = tracesWithSelectedPts[0] === clickedPtInfo.searchInfo;
if(isSameTrace) {
- trace = clickedPtInfo.searchInfo.cd[0].trace;
+ trace = getTraceFromCd(clickedPtInfo.searchInfo.cd);
if(trace.selectedpoints.length === clickedPtInfo.pointNumbers.length) {
for(i = 0; i < clickedPtInfo.pointNumbers.length; i++) {
if(trace.selectedpoints.indexOf(clickedPtInfo.pointNumbers[i]) < 0) {
@@ -773,7 +778,7 @@ function isOnlyOnePointSelected(searchTraces) {
for(i = 0; i < searchTraces.length; i++) {
searchInfo = searchTraces[i];
- trace = searchInfo.cd[0].trace;
+ trace = getTraceFromCd(searchInfo.cd);
if(trace.selectedpoints) {
if(trace.selectedpoints.length > 1) return false;
@@ -790,7 +795,7 @@ function updateSelectedState(gd, searchTraces, eventData) {
// before anything else, update preGUI if necessary
for(i = 0; i < searchTraces.length; i++) {
- var fullInputTrace = searchTraces[i].cd[0].trace._fullInput;
+ var fullInputTrace = getTraceFromCd(searchTraces[i].cd)._fullInput;
var tracePreGUI = gd._fullLayout._tracePreGUI[fullInputTrace.uid] || {};
if(tracePreGUI.selectedpoints === undefined) {
tracePreGUI.selectedpoints = fullInputTrace._input.selectedpoints || null;
@@ -801,7 +806,7 @@ function updateSelectedState(gd, searchTraces, eventData) {
var pts = eventData.points || [];
for(i = 0; i < searchTraces.length; i++) {
- trace = searchTraces[i].cd[0].trace;
+ trace = getTraceFromCd(searchTraces[i].cd);
trace._input.selectedpoints = trace._fullInput.selectedpoints = [];
if(trace._fullInput !== trace) trace.selectedpoints = [];
}
@@ -825,7 +830,7 @@ function updateSelectedState(gd, searchTraces, eventData) {
}
} else {
for(i = 0; i < searchTraces.length; i++) {
- trace = searchTraces[i].cd[0].trace;
+ trace = getTraceFromCd(searchTraces[i].cd);
delete trace.selectedpoints;
delete trace._input.selectedpoints;
if(trace._fullInput !== trace) {
@@ -839,7 +844,7 @@ function updateSelectedState(gd, searchTraces, eventData) {
for(i = 0; i < searchTraces.length; i++) {
searchInfo = searchTraces[i];
cd = searchInfo.cd;
- trace = cd[0].trace;
+ trace = getTraceFromCd(cd);
if(Registry.traceIs(trace, 'regl')) {
hasRegl = true;
@@ -888,7 +893,7 @@ function mergePolygons(list, poly, subtract) {
function fillSelectionItem(selection, searchInfo) {
if(Array.isArray(selection)) {
var cd = searchInfo.cd;
- var trace = searchInfo.cd[0].trace;
+ var trace = getTraceFromCd(searchInfo.cd);
for(var i = 0; i < selection.length; i++) {
selection[i] = makeEventData(selection[i], trace, cd);
diff --git a/src/plots/cartesian/set_convert.js b/src/plots/cartesian/set_convert.js
index c8d00c9bbde..5e683b124e7 100644
--- a/src/plots/cartesian/set_convert.js
+++ b/src/plots/cartesian/set_convert.js
@@ -1,6 +1,6 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var utcFormat = require('d3-time-format').utcFormat;
var Lib = require('../../lib');
var numberFormat = Lib.numberFormat;
diff --git a/src/plots/cartesian/transition_axes.js b/src/plots/cartesian/transition_axes.js
index f98969de352..9104705a7b2 100644
--- a/src/plots/cartesian/transition_axes.js
+++ b/src/plots/cartesian/transition_axes.js
@@ -1,6 +1,6 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var Registry = require('../../registry');
var Lib = require('../../lib');
@@ -24,6 +24,8 @@ var Axes = require('./axes');
* @param {function} makeOnCompleteCallback
*/
module.exports = function transitionAxes(gd, edits, transitionOpts, makeOnCompleteCallback) {
+ var d3EaseFn = Lib.whichD3EaseFn(transitionOpts);
+
var fullLayout = gd._fullLayout;
// special case for redraw:false Plotly.animate that relies on this
@@ -170,7 +172,7 @@ module.exports = function transitionAxes(gd, edits, transitionOpts, makeOnComple
}
var t1, t2, raf;
- var easeFn = d3.ease(transitionOpts.easing);
+ var easeFn = d3.ease(d3EaseFn);
gd._transitionData._interruptCallbacks.push(function() {
window.cancelAnimationFrame(raf);
diff --git a/src/plots/geo/geo.js b/src/plots/geo/geo.js
index 2ee4aec5739..871ff305cb7 100644
--- a/src/plots/geo/geo.js
+++ b/src/plots/geo/geo.js
@@ -2,7 +2,7 @@
/* global PlotlyGeoAssets:false */
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var geo = require('d3-geo');
var geoPath = geo.geoPath;
var geoDistance = geo.geoDistance;
@@ -10,6 +10,7 @@ var geoProjection = require('d3-geo-projection');
var Registry = require('../../registry');
var Lib = require('../../lib');
+var getTraceFromCd = require('../../lib/trace_from_cd');
var strTranslate = Lib.strTranslate;
var Color = require('../../components/color');
var Drawing = require('../../components/drawing');
@@ -145,7 +146,7 @@ proto.update = function(geoCalcData, fullLayout) {
for(var i = 0; i < geoCalcData.length; i++) {
var calcTrace = geoCalcData[i];
- var trace = calcTrace[0].trace;
+ var trace = getTraceFromCd(calcTrace);
if(trace.type === 'choropleth') {
this.hasChoropleth = true;
@@ -319,7 +320,9 @@ proto.updateBaseLayers = function(fullLayout, geoLayout) {
});
var join = _this.framework.selectAll('.layer')
- .data(layerData, String);
+ .data(layerData, String)
+ .enter()
+ .append('g');
join.exit().each(function(d) {
delete layers[d];
@@ -327,7 +330,7 @@ proto.updateBaseLayers = function(fullLayout, geoLayout) {
d3.select(this).remove();
});
- join.enter().append('g')
+ join
.attr('class', function(d) { return 'layer ' + d; })
.each(function(d) {
var layer = layers[d] = d3.select(this);
diff --git a/src/plots/geo/zoom.js b/src/plots/geo/zoom.js
index d486122ddbc..340f2149597 100644
--- a/src/plots/geo/zoom.js
+++ b/src/plots/geo/zoom.js
@@ -1,13 +1,13 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var Lib = require('../../lib');
var Registry = require('../../registry');
var radians = Math.PI / 180;
var degrees = 180 / Math.PI;
-var zoomstartStyle = {cursor: 'pointer'};
-var zoomendStyle = {cursor: 'auto'};
+var startStyle = {cursor: 'pointer'};
+var endStyle = {cursor: 'auto'};
function createGeoZoom(geo, geoLayout) {
var projection = geo.projection;
@@ -30,9 +30,11 @@ module.exports = createGeoZoom;
// common to all zoom types
function initZoom(geo, projection) {
- return d3.behavior.zoom()
- .translate(projection.translate())
- .scale(projection.scale());
+ return d3.zoom(
+ d3.zoomIdentity
+ .translate(projection.translate())
+ .scale(projection.scale())
+ );
}
// sync zoom updates with user & full layout
@@ -70,7 +72,7 @@ function zoomScoped(geo, projection) {
var zoom = initZoom(geo, projection);
function handleZoomstart() {
- d3.select(this).style(zoomstartStyle);
+ d3.select(this).styles(startStyle);
}
function handleZoom() {
@@ -95,14 +97,14 @@ function zoomScoped(geo, projection) {
}
function handleZoomend() {
- d3.select(this).style(zoomendStyle);
+ d3.select(this).styles(endStyle);
sync(geo, projection, syncCb);
}
zoom
- .on('zoomstart', handleZoomstart)
+ .on('start', handleZoomstart)
.on('zoom', handleZoom)
- .on('zoomend', handleZoomend);
+ .on('end', handleZoomend);
return zoom;
}
@@ -130,7 +132,7 @@ function zoomNonClipped(geo, projection) {
}
function handleZoomstart() {
- d3.select(this).style(zoomstartStyle);
+ d3.select(this).styles(startStyle);
mouse0 = d3.mouse(this);
rotate0 = projection.rotate();
@@ -175,7 +177,7 @@ function zoomNonClipped(geo, projection) {
}
function handleZoomend() {
- d3.select(this).style(zoomendStyle);
+ d3.select(this).styles(endStyle);
if(didZoom) sync(geo, projection, syncCb);
}
@@ -189,9 +191,9 @@ function zoomNonClipped(geo, projection) {
}
zoom
- .on('zoomstart', handleZoomstart)
+ .on('start', handleZoomstart)
.on('zoom', handleZoom)
- .on('zoomend', handleZoomend);
+ .on('end', handleZoomend);
return zoom;
}
@@ -201,14 +203,14 @@ function zoomNonClipped(geo, projection) {
function zoomClipped(geo, projection) {
var view = {r: projection.rotate(), k: projection.scale()};
var zoom = initZoom(geo, projection);
- var event = d3eventDispatch(zoom, 'zoomstart', 'zoom', 'zoomend');
+ var event = d3eventDispatch(zoom, 'start', 'zoom', 'end');
var zooming = 0;
var zoomOn = zoom.on;
var zoomPoint;
- zoom.on('zoomstart', function() {
- d3.select(this).style(zoomstartStyle);
+ zoom.on('start', function() {
+ d3.select(this).styles(startStyle);
var mouse0 = d3.mouse(this);
var rotate0 = projection.rotate();
@@ -259,12 +261,12 @@ function zoomClipped(geo, projection) {
zoomed(event.of(this, arguments));
});
- zoomstarted(event.of(this, arguments));
+ started(event.of(this, arguments));
})
- .on('zoomend', function() {
- d3.select(this).style(zoomendStyle);
+ .on('end', function() {
+ d3.select(this).styles(endStyle);
zoomOn.call(zoom, 'zoom', null);
- zoomended(event.of(this, arguments));
+ ended(event.of(this, arguments));
sync(geo, projection, syncCb);
})
.on('zoom.redraw', function() {
@@ -278,16 +280,16 @@ function zoomClipped(geo, projection) {
});
});
- function zoomstarted(dispatch) {
- if(!zooming++) dispatch({type: 'zoomstart'});
+ function started(dispatch) {
+ if(!zooming++) dispatch({type: 'start'});
}
function zoomed(dispatch) {
dispatch({type: 'zoom'});
}
- function zoomended(dispatch) {
- if(!--zooming) dispatch({type: 'zoomend'});
+ function ended(dispatch) {
+ if(!--zooming) dispatch({type: 'end'});
}
function syncCb(set) {
diff --git a/src/plots/get_data.js b/src/plots/get_data.js
index 5561692960e..403f3dfc5f0 100644
--- a/src/plots/get_data.js
+++ b/src/plots/get_data.js
@@ -1,5 +1,6 @@
'use strict';
+var getTraceFromCd = require('../lib/trace_from_cd');
var Registry = require('../registry');
var SUBPLOT_PATTERN = require('./cartesian/constants').SUBPLOT_PATTERN;
@@ -21,7 +22,7 @@ exports.getSubplotCalcData = function(calcData, type, subplotId) {
for(var i = 0; i < calcData.length; i++) {
var calcTrace = calcData[i];
- var trace = calcTrace[0].trace;
+ var trace = getTraceFromCd(calcTrace);
if(trace[attr] === subplotId) subplotCalcData.push(calcTrace);
}
@@ -60,7 +61,7 @@ exports.getModuleCalcData = function(calcdata, arg1) {
for(var i = 0; i < calcdata.length; i++) {
var cd = calcdata[i];
- var trace = cd[0].trace;
+ var trace = getTraceFromCd(cd);
// N.B.
// - 'legendonly' traces do not make it past here
// - skip over 'visible' traces that got trimmed completely during calc transforms
diff --git a/src/plots/gl2d/index.js b/src/plots/gl2d/index.js
index efb10fe9045..af55ef32f0c 100644
--- a/src/plots/gl2d/index.js
+++ b/src/plots/gl2d/index.js
@@ -115,7 +115,7 @@ exports.toSVG = function(gd) {
var imageData = scene.toImage('png');
var image = fullLayout._glimages.append('svg:image');
- image.attr({
+ image.attrs({
xmlns: xmlnsNamespaces.svg,
'xlink:href': imageData,
x: 0,
diff --git a/src/plots/gl3d/index.js b/src/plots/gl3d/index.js
index 089e3db9551..4fde62f0b49 100644
--- a/src/plots/gl3d/index.js
+++ b/src/plots/gl3d/index.js
@@ -114,7 +114,7 @@ exports.toSVG = function(gd) {
var imageData = scene.toImage('png');
var image = fullLayout._glimages.append('svg:image');
- image.attr({
+ image.attrs({
xmlns: xmlnsNamespaces.svg,
'xlink:href': imageData,
x: size.l + size.w * domain.x[0],
diff --git a/src/plots/mapbox/index.js b/src/plots/mapbox/index.js
index 1fe03d82e39..9de3ca36382 100644
--- a/src/plots/mapbox/index.js
+++ b/src/plots/mapbox/index.js
@@ -7,7 +7,7 @@ var strTranslate = Lib.strTranslate;
var strScale = Lib.strScale;
var getSubplotCalcData = require('../../plots/get_data').getSubplotCalcData;
var xmlnsNamespaces = require('../../constants/xmlns_namespaces');
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var Drawing = require('../../components/drawing');
var svgTextUtils = require('../../lib/svg_text_utils');
@@ -104,7 +104,7 @@ exports.toSVG = function(gd) {
var imageData = mapbox.toImage('png');
var image = fullLayout._glimages.append('svg:image');
- image.attr({
+ image.attrs({
xmlns: xmlnsNamespaces.svg,
'xlink:href': imageData,
x: size.l + size.w * domain.x[0],
@@ -123,7 +123,7 @@ exports.toSVG = function(gd) {
logo.attr('transform', strTranslate(size.l + size.w * domain.x[0] + 10, size.t + size.h * (1 - domain.y[0]) - 31));
logo.append('path')
.attr('d', constants.mapboxLogo.path0)
- .style({
+ .styles({
opacity: 0.9,
fill: '#ffffff',
'enable-background': 'new'
@@ -141,7 +141,7 @@ exports.toSVG = function(gd) {
logo.append('polygon')
.attr('points', constants.mapboxLogo.polygon)
- .style({
+ .styles({
opacity: 0.9,
fill: '#ffffff',
'enable-background': 'new'
@@ -159,7 +159,7 @@ exports.toSVG = function(gd) {
attributionText
.text(attributions)
.classed('static-attribution', true)
- .attr({
+ .attrs({
'font-size': 12,
'font-family': 'Arial',
'color': 'rgba(0, 0, 0, 0.75)',
@@ -185,7 +185,7 @@ exports.toSVG = function(gd) {
// Draw white rectangle behind text
attributionGroup
.insert('rect', '.static-attribution')
- .attr({
+ .attrs({
x: -bBox.width - 6,
y: -bBox.height - 3,
width: bBox.width + 6,
diff --git a/src/plots/mapbox/mapbox.js b/src/plots/mapbox/mapbox.js
index 5046b261e22..a085f048e70 100644
--- a/src/plots/mapbox/mapbox.js
+++ b/src/plots/mapbox/mapbox.js
@@ -3,6 +3,7 @@
var mapboxgl = require('mapbox-gl/dist/mapbox-gl-unminified');
var Lib = require('../../lib');
+var getTraceFromCd = require('../../lib/trace_from_cd');
var geoUtils = require('../../lib/geo_location_utils');
var Registry = require('../../registry');
var Axes = require('../cartesian/axes');
@@ -271,8 +272,8 @@ proto.updateData = function(calcData) {
// e.g. choroplethmapbox traces will be below scattermapbox traces
var calcDataSorted = calcData.slice().sort(function(a, b) {
return (
- traceType2orderIndex[a[0].trace.type] -
- traceType2orderIndex[b[0].trace.type]
+ traceType2orderIndex[getTraceFromCd(a).type] -
+ traceType2orderIndex[getTraceFromCd(b).type]
);
});
@@ -280,7 +281,7 @@ proto.updateData = function(calcData) {
for(i = 0; i < calcDataSorted.length; i++) {
var calcTrace = calcDataSorted[i];
- trace = calcTrace[0].trace;
+ trace = getTraceFromCd(calcTrace);
traceObj = traceHash[trace.uid];
var didUpdate = false;
@@ -466,7 +467,7 @@ proto.initFx = function(calcData, fullLayout) {
Fx.loneUnhover(fullLayout._hoverlayer);
}
- map.on('dragstart', function() {
+ map.on('start', function() {
self.dragging = true;
unhover();
});
diff --git a/src/plots/plots.js b/src/plots/plots.js
index d4ec300d719..8b9b0bf99ef 100644
--- a/src/plots/plots.js
+++ b/src/plots/plots.js
@@ -1,6 +1,6 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../lib/d3');
var timeFormatLocale = require('d3-time-format').timeFormatLocale;
var formatLocale = require('d3-format').formatLocale;
var isNumeric = require('fast-isnumeric');
@@ -129,7 +129,7 @@ plots.addLinks = function(gd) {
var fullLayout = gd._fullLayout;
var linkContainer = Lib.ensureSingle(fullLayout._paper, 'text', 'js-plot-link-container', function(s) {
- s.style({
+ s.styles({
'font-family': '"Open Sans", Arial, sans-serif',
'font-size': '12px',
'fill': Color.defaultLine,
@@ -162,7 +162,7 @@ plots.addLinks = function(gd) {
attrs.x = fullLayout._paper.attr('width') - 7;
}
- linkContainer.attr(attrs);
+ linkContainer.attrs(attrs);
var toolspan = linkContainer.select('.js-link-to-tool');
var spacespan = linkContainer.select('.js-link-spacer');
@@ -182,7 +182,7 @@ plots.addLinks = function(gd) {
function positionPlayWithData(gd, container) {
container.text('');
var link = container.append('a')
- .attr({
+ .attrs({
'xlink:xlink:href': '#',
'class': 'link--impt link--embedview',
'font-weight': 'bold'
@@ -196,7 +196,7 @@ function positionPlayWithData(gd, container) {
} else {
var path = window.location.pathname.split('/');
var query = window.location.search;
- link.attr({
+ link.attrs({
'xlink:xlink:show': 'new',
'xlink:xlink:href': '/' + path[2].split('.')[0] + '/' + path[1] + query
});
@@ -216,7 +216,7 @@ plots.sendDataToCloud = function(gd) {
var hiddenform = hiddenformDiv
.append('form')
- .attr({
+ .attrs({
action: baseUrl + '/external',
method: 'post',
target: '_blank'
@@ -224,7 +224,7 @@ plots.sendDataToCloud = function(gd) {
var hiddenformInput = hiddenform
.append('input')
- .attr({
+ .attrs({
type: 'text',
name: 'data'
});
diff --git a/src/plots/polar/polar.js b/src/plots/polar/polar.js
index 30cc3f0608c..b947d824cdd 100644
--- a/src/plots/polar/polar.js
+++ b/src/plots/polar/polar.js
@@ -1,6 +1,6 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var tinycolor = require('tinycolor2');
var Registry = require('../../registry');
@@ -146,11 +146,14 @@ proto.updateLayers = function(fullLayout, polarLayout) {
if(!isRadialAxisBelowTraces) layerData.push('radial-axis');
var subLayer = (isSmith ? 'smith' : 'polar') + 'sublayer';
-
var join = _this.framework.selectAll('.' + subLayer)
- .data(layerData, String);
+ .data(layerData, String)
+ .enter()
+ .append('g');
+
+ join.exit().remove();
- join.enter().append('g')
+ join
.attr('class', function(d) { return subLayer + ' ' + d;})
.each(function(d) {
var sel = layers[d] = d3.select(this);
@@ -1556,7 +1559,7 @@ function snapToVertexAngle(a, vangles) {
function updateElement(sel, showAttr, attrs) {
if(showAttr) {
sel.attr('display', null);
- sel.attr(attrs);
+ sel.attrs(attrs);
} else if(sel) {
sel.attr('display', 'none');
}
diff --git a/src/plots/ternary/ternary.js b/src/plots/ternary/ternary.js
index 004cc8ef202..3101fd20d9f 100644
--- a/src/plots/ternary/ternary.js
+++ b/src/plots/ternary/ternary.js
@@ -1,6 +1,6 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var tinycolor = require('tinycolor2');
var Registry = require('../../registry');
@@ -129,11 +129,15 @@ proto.updateLayers = function(ternaryLayout) {
}
var toplevel = _this.plotContainer.selectAll('g.toplevel')
- .data(plotLayers, String);
+ .data(plotLayers, String)
+ .enter()
+ .append('g');
+
+ toplevel.exit().remove();
var grids = ['agrid', 'bgrid', 'cgrid'];
- toplevel.enter().append('g')
+ toplevel
.attr('class', function(d) { return 'toplevel ' + d; })
.each(function(d) {
var s = d3.select(this);
@@ -593,7 +597,7 @@ proto.initInteractions = function() {
zb = zoomLayer.append('path')
.attr('class', 'zoombox')
.attr('transform', strTranslate(_this.x0, _this.y0))
- .style({
+ .styles({
'fill': lum > 0.2 ? 'rgba(0,0,0,0)' : 'rgba(255,255,255,0)',
'stroke-width': 0
})
@@ -602,7 +606,7 @@ proto.initInteractions = function() {
corners = zoomLayer.append('path')
.attr('class', 'zoombox-corners')
.attr('transform', strTranslate(_this.x0, _this.y0))
- .style({
+ .styles({
fill: Color.background,
stroke: Color.defaultLine,
'stroke-width': 1,
diff --git a/src/snapshot/tosvg.js b/src/snapshot/tosvg.js
index 34ebfdc5f8d..dd622fc11ad 100644
--- a/src/snapshot/tosvg.js
+++ b/src/snapshot/tosvg.js
@@ -1,6 +1,6 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../lib/d3');
var Lib = require('../lib');
var Drawing = require('../components/drawing');
@@ -12,7 +12,7 @@ var DUMMY_SUB = 'TOBESTRIPPED';
var DUMMY_REGEX = new RegExp('("' + DUMMY_SUB + ')|(' + DUMMY_SUB + '")', 'g');
function htmlEntityDecode(s) {
- var hiddenDiv = d3.select('body').append('div').style({display: 'none'}).html('');
+ var hiddenDiv = d3.select('body').append('div').styles({display: 'none'}).html('');
var replaced = s.replace(/(&[^;]*;)/gi, function(d) {
if(d === '<') { return '<'; } // special handling for brackets
if(d === '&rt;') { return '>'; }
@@ -80,7 +80,7 @@ module.exports = function toSVG(gd, format, scale) {
svg.node().style.background = '';
svg.selectAll('text')
- .attr({'data-unformatted': null, 'data-math': null})
+ .attrs({'data-unformatted': null, 'data-math': null})
.each(function() {
var txt = d3.select(this);
@@ -94,7 +94,7 @@ module.exports = function toSVG(gd, format, scale) {
} else {
// clear other visibility/display values to default
// to not potentially confuse non-browser SVG implementations
- txt.style({visibility: null, display: null});
+ txt.styles({visibility: null, display: null});
}
// Font family styles break things because of quotation marks,
diff --git a/src/traces/bar/cross_trace_calc.js b/src/traces/bar/cross_trace_calc.js
index f1cad80924d..941b8a88e1f 100644
--- a/src/traces/bar/cross_trace_calc.js
+++ b/src/traces/bar/cross_trace_calc.js
@@ -1,7 +1,10 @@
'use strict';
var isNumeric = require('fast-isnumeric');
-var isArrayOrTypedArray = require('../../lib').isArrayOrTypedArray;
+
+var Lib = require('../../lib');
+var getTraceFromCd = require('../../lib/trace_from_cd');
+var isArrayOrTypedArray = Lib.isArrayOrTypedArray;
var BADNUM = require('../../constants/numerical').BADNUM;
var Registry = require('../../registry');
@@ -84,7 +87,7 @@ function setGroupPositions(gd, pa, sa, calcTraces, opts) {
included = [];
for(i = 0; i < calcTraces.length; i++) {
calcTrace = calcTraces[i];
- fullTrace = calcTrace[0].trace;
+ fullTrace = getTraceFromCd(calcTrace);
if(fullTrace.offset === undefined) included.push(calcTrace);
else excluded.push(calcTrace);
@@ -105,7 +108,7 @@ function setGroupPositions(gd, pa, sa, calcTraces, opts) {
included = [];
for(i = 0; i < calcTraces.length; i++) {
calcTrace = calcTraces[i];
- fullTrace = calcTrace[0].trace;
+ fullTrace = getTraceFromCd(calcTrace);
if(fullTrace.base === undefined) included.push(calcTrace);
else excluded.push(calcTrace);
@@ -128,7 +131,7 @@ function initBase(sa, calcTraces) {
for(i = 0; i < calcTraces.length; i++) {
var cd = calcTraces[i];
- var trace = cd[0].trace;
+ var trace = getTraceFromCd(cd);
var base = (trace.type === 'funnel') ? trace._base : trace.base;
var b;
@@ -303,7 +306,7 @@ function setOffsetAndWidthInGroupMode(gd, pa, sieve, opts) {
for(var i = 0; i < nTraces; i++) {
var calcTrace = calcTraces[i];
- var trace = calcTrace[0].trace;
+ var trace = getTraceFromCd(calcTrace);
var alignmentGroupOpts = alignmentGroups[trace.alignmentgroup] || {};
var nOffsetGroups = Object.keys(alignmentGroupOpts.offsetGroups || {}).length;
@@ -497,7 +500,7 @@ function setBaseAndTop(sa, sieve) {
for(var i = 0; i < calcTraces.length; i++) {
var calcTrace = calcTraces[i];
- var fullTrace = calcTrace[0].trace;
+ var fullTrace = getTraceFromCd(calcTrace);
var pts = [];
var tozero = false;
@@ -533,7 +536,7 @@ function stackBars(sa, sieve, opts) {
for(i = 0; i < calcTraces.length; i++) {
calcTrace = calcTraces[i];
- fullTrace = calcTrace[0].trace;
+ fullTrace = getTraceFromCd(calcTrace);
if(fullTrace.type === 'funnel') {
for(j = 0; j < calcTrace.length; j++) {
@@ -549,7 +552,7 @@ function stackBars(sa, sieve, opts) {
for(i = 0; i < calcTraces.length; i++) {
calcTrace = calcTraces[i];
- fullTrace = calcTrace[0].trace;
+ fullTrace = getTraceFromCd(calcTrace);
isFunnel = (fullTrace.type === 'funnel');
@@ -617,7 +620,7 @@ function unhideBarsWithinTrace(sieve, pa) {
for(var i = 0; i < calcTraces.length; i++) {
var calcTrace = calcTraces[i];
- var fullTrace = calcTrace[0].trace;
+ var fullTrace = getTraceFromCd(calcTrace);
if(fullTrace.base === undefined) {
var inTraceSieve = new Sieve([calcTrace], {
@@ -664,7 +667,7 @@ function normalizeBars(sa, sieve, opts) {
for(var i = 0; i < calcTraces.length; i++) {
var calcTrace = calcTraces[i];
- var fullTrace = calcTrace[0].trace;
+ var fullTrace = getTraceFromCd(calcTrace);
var pts = [];
var tozero = false;
var padded = false;
diff --git a/src/traces/bar/hover.js b/src/traces/bar/hover.js
index e062c4b50af..7fe1b5c117b 100644
--- a/src/traces/bar/hover.js
+++ b/src/traces/bar/hover.js
@@ -4,7 +4,9 @@ var Fx = require('../../components/fx');
var Registry = require('../../registry');
var Color = require('../../components/color');
-var fillText = require('../../lib').fillText;
+var Lib = require('../../lib');
+var fillText = Lib.fillText;
+var getTraceFromCd = require('../../lib/trace_from_cd');
var getLineWidth = require('./helpers').getLineWidth;
var hoverLabelText = require('../../plots/cartesian/axes').hoverLabelText;
var BADNUM = require('../../constants/numerical').BADNUM;
@@ -14,7 +16,7 @@ function hoverPoints(pointData, xval, yval, hovermode, opts) {
if(barPointData) {
var cd = barPointData.cd;
- var trace = cd[0].trace;
+ var trace = getTraceFromCd(cd);
var di = cd[barPointData.index];
barPointData.color = getTraceColor(trace, di);
@@ -26,7 +28,7 @@ function hoverPoints(pointData, xval, yval, hovermode, opts) {
function hoverOnBars(pointData, xval, yval, hovermode, opts) {
var cd = pointData.cd;
- var trace = cd[0].trace;
+ var trace = getTraceFromCd(cd);
var t = cd[0].t;
var isClosest = (hovermode === 'closest');
var isWaterfall = (trace.type === 'waterfall');
diff --git a/src/traces/bar/plot.js b/src/traces/bar/plot.js
index 8923665593d..7a569a66e1a 100644
--- a/src/traces/bar/plot.js
+++ b/src/traces/bar/plot.js
@@ -1,9 +1,10 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var isNumeric = require('fast-isnumeric');
var Lib = require('../../lib');
+var getTraceFromCd = require('../../lib/trace_from_cd');
var svgTextUtils = require('../../lib/svg_text_utils');
var Color = require('../../components/color');
@@ -94,7 +95,7 @@ function plot(gd, plotinfo, cdModule, traceLayer, opts, makeOnCompleteCallback)
var bartraces = Lib.makeTraceGroups(traceLayer, cdModule, 'trace bars').each(function(cd) {
var plotGroup = d3.select(this);
- var trace = cd[0].trace;
+ var trace = getTraceFromCd(cd);
var isWaterfall = (trace.type === 'waterfall');
var isFunnel = (trace.type === 'funnel');
var isBar = (trace.type === 'bar');
@@ -111,13 +112,14 @@ function plot(gd, plotinfo, cdModule, traceLayer, opts, makeOnCompleteCallback)
var pointGroup = Lib.ensureSingle(plotGroup, 'g', 'points');
var keyFunc = getKeyFunc(trace);
- var bars = pointGroup.selectAll('g.point').data(Lib.identity, keyFunc);
-
- bars.enter().append('g')
- .classed('point', true);
+ var bars = pointGroup.selectAll('g.point').data(Lib.identity, keyFunc)
+ .enter()
+ .append('g');
bars.exit().remove();
+ bars.classed('point', true);
+
bars.each(function(di, i) {
var bar = d3.select(this);
@@ -269,7 +271,7 @@ function appendBarText(gd, plotinfo, bar, cd, i, x0, x1, y0, y1, opts, makeOnCom
function appendTextNode(bar, text, font) {
var textSelection = Lib.ensureSingle(bar, 'text')
.text(text)
- .attr({
+ .attrs({
'class': 'bartext bartext-' + textPosition,
'text-anchor': 'middle',
// prohibit tex interpretation until we can handle
@@ -283,7 +285,7 @@ function appendBarText(gd, plotinfo, bar, cd, i, x0, x1, y0, y1, opts, makeOnCom
}
// get trace attributes
- var trace = cd[0].trace;
+ var trace = getTraceFromCd(cd);
var isHorizontal = (trace.orientation === 'h');
var text = getText(fullLayout, cd, i, xa, ya);
@@ -605,7 +607,7 @@ function toMoveOutsideBar(x0, x1, y0, y1, textBB, opts) {
}
function getText(fullLayout, cd, index, xa, ya) {
- var trace = cd[0].trace;
+ var trace = getTraceFromCd(cd);
var texttemplate = trace.texttemplate;
var value;
@@ -626,7 +628,7 @@ function getTextPosition(trace, index) {
}
function calcTexttemplate(fullLayout, cd, index, xa, ya) {
- var trace = cd[0].trace;
+ var trace = getTraceFromCd(cd);
var texttemplate = Lib.castOption(trace, index, 'texttemplate');
if(!texttemplate) return '';
var isWaterfall = (trace.type === 'waterfall');
@@ -696,7 +698,7 @@ function calcTexttemplate(fullLayout, cd, index, xa, ya) {
}
function calcTextinfo(cd, index, xa, ya) {
- var trace = cd[0].trace;
+ var trace = getTraceFromCd(cd);
var isHorizontal = (trace.orientation === 'h');
var isWaterfall = (trace.type === 'waterfall');
var isFunnel = (trace.type === 'funnel');
diff --git a/src/traces/bar/select.js b/src/traces/bar/select.js
index a41a26639ea..c13bbafc07b 100644
--- a/src/traces/bar/select.js
+++ b/src/traces/bar/select.js
@@ -1,10 +1,12 @@
'use strict';
+var getTraceFromCd = require('../../lib/trace_from_cd');
+
module.exports = function selectPoints(searchInfo, selectionTester) {
var cd = searchInfo.cd;
var xa = searchInfo.xaxis;
var ya = searchInfo.yaxis;
- var trace = cd[0].trace;
+ var trace = getTraceFromCd(cd);
var isFunnel = (trace.type === 'funnel');
var isHorizontal = (trace.orientation === 'h');
var selection = [];
diff --git a/src/traces/bar/style.js b/src/traces/bar/style.js
index df30b7c3850..5eca9a3067e 100644
--- a/src/traces/bar/style.js
+++ b/src/traces/bar/style.js
@@ -1,9 +1,10 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var Color = require('../../components/color');
var Drawing = require('../../components/drawing');
var Lib = require('../../lib');
+var getTraceFromCd = require('../../lib/trace_from_cd');
var Registry = require('../../registry');
var resizeText = require('./uniform_text').resizeText;
@@ -21,7 +22,7 @@ function style(gd) {
var fullLayout = gd._fullLayout;
// trace styling
- s.style('opacity', function(d) { return d[0].trace.opacity; })
+ s.style('opacity', function(d) { return getTraceFromCd(d).opacity; })
// for gapless (either stacked or neighboring grouped) bars use
// crispEdges to turn off antialiasing so an artificial gap
@@ -30,14 +31,14 @@ function style(gd) {
if((fullLayout.barmode === 'stack' && barcount > 1) ||
(fullLayout.bargap === 0 &&
fullLayout.bargroupgap === 0 &&
- !d[0].trace.marker.line.width)) {
+ !getTraceFromCd(d).marker.line.width)) {
d3.select(this).attr('shape-rendering', 'crispEdges');
}
});
s.selectAll('g.points').each(function(d) {
var sel = d3.select(this);
- var trace = d[0].trace;
+ var trace = getTraceFromCd(d);
stylePoints(sel, trace, gd);
});
@@ -59,7 +60,7 @@ function styleTextPoints(sel, trace, gd) {
}
function styleOnSelect(gd, cd, sel) {
- var trace = cd[0].trace;
+ var trace = getTraceFromCd(cd);
if(trace.selectedpoints) {
stylePointsInSelectionMode(sel, trace, gd);
diff --git a/src/traces/bar/uniform_text.js b/src/traces/bar/uniform_text.js
index b7b2390d8b5..87f20c7c16e 100644
--- a/src/traces/bar/uniform_text.js
+++ b/src/traces/bar/uniform_text.js
@@ -1,6 +1,6 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var Lib = require('../../lib');
function resizeText(gd, gTrace, traceType) {
diff --git a/src/traces/barpolar/hover.js b/src/traces/barpolar/hover.js
index ab2b084e983..8c444c5466f 100644
--- a/src/traces/barpolar/hover.js
+++ b/src/traces/barpolar/hover.js
@@ -2,6 +2,7 @@
var Fx = require('../../components/fx');
var Lib = require('../../lib');
+var getTraceFromCd = require('../../lib/trace_from_cd');
var getTraceColor = require('../bar/hover').getTraceColor;
var fillText = Lib.fillText;
var makeHoverPointText = require('../scatterpolar/hover').makeHoverPointText;
@@ -9,7 +10,7 @@ var isPtInsidePolygon = require('../../plots/polar/helpers').isPtInsidePolygon;
module.exports = function hoverPoints(pointData, xval, yval) {
var cd = pointData.cd;
- var trace = cd[0].trace;
+ var trace = getTraceFromCd(cd);
var subplot = pointData.subplot;
var radialAxis = subplot.radialAxis;
diff --git a/src/traces/barpolar/plot.js b/src/traces/barpolar/plot.js
index 41015dc3c08..7909df61ae2 100644
--- a/src/traces/barpolar/plot.js
+++ b/src/traces/barpolar/plot.js
@@ -1,6 +1,6 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var isNumeric = require('fast-isnumeric');
var Lib = require('../../lib');
@@ -18,15 +18,18 @@ module.exports = function plot(gd, subplot, cdbar) {
Lib.makeTraceGroups(barLayer, cdbar, 'trace bars').each(function() {
var plotGroup = d3.select(this);
var pointGroup = Lib.ensureSingle(plotGroup, 'g', 'points');
- var bars = pointGroup.selectAll('g.point').data(Lib.identity);
+ var bars = pointGroup.selectAll('g.point')
+ .data(Lib.identity)
+ .enter()
+ .append('g');
- bars.enter().append('g')
+ bars.exit().remove();
+
+ bars
.style('vector-effect', 'non-scaling-stroke')
.style('stroke-miterlimit', 2)
.classed('point', true);
- bars.exit().remove();
-
bars.each(function(di) {
var bar = d3.select(this);
diff --git a/src/traces/box/cross_trace_calc.js b/src/traces/box/cross_trace_calc.js
index 00632d0dbb2..bb4c4f0c025 100644
--- a/src/traces/box/cross_trace_calc.js
+++ b/src/traces/box/cross_trace_calc.js
@@ -2,6 +2,7 @@
var Axes = require('../../plots/cartesian/axes');
var Lib = require('../../lib');
+var getTraceFromCd = require('../../lib/trace_from_cd');
var getAxisGroup = require('../../plots/cartesian/constraints').getAxisGroup;
var orientations = ['v', 'h'];
@@ -21,7 +22,7 @@ function crossTraceCalc(gd, plotinfo) {
for(var j = 0; j < calcdata.length; j++) {
var cd = calcdata[j];
var t = cd[0].t;
- var trace = cd[0].trace;
+ var trace = getTraceFromCd(cd);
if(trace.visible === true &&
(trace.type === 'box' || trace.type === 'candlestick') &&
@@ -79,7 +80,7 @@ function setPositionOffset(traceType, gd, boxList, posAxis) {
for(i = 0; i < boxList.length; i++) {
calcTrace = calcdata[boxList[i]];
- var trace = calcTrace[0].trace;
+ var trace = getTraceFromCd(calcTrace);
var t = calcTrace[0].t;
var width = trace.width;
var side = trace.side;
diff --git a/src/traces/box/hover.js b/src/traces/box/hover.js
index 6ae73777347..e44410403d0 100644
--- a/src/traces/box/hover.js
+++ b/src/traces/box/hover.js
@@ -2,13 +2,14 @@
var Axes = require('../../plots/cartesian/axes');
var Lib = require('../../lib');
+var getTraceFromCd = require('../../lib/trace_from_cd');
var Fx = require('../../components/fx');
var Color = require('../../components/color');
var fillText = Lib.fillText;
function hoverPoints(pointData, xval, yval, hovermode) {
var cd = pointData.cd;
- var trace = cd[0].trace;
+ var trace = getTraceFromCd(cd);
var hoveron = trace.hoveron;
var closeBoxData = [];
var closePtData;
@@ -41,7 +42,7 @@ function hoverOnBoxes(pointData, xval, yval, hovermode) {
var cd = pointData.cd;
var xa = pointData.xa;
var ya = pointData.ya;
- var trace = cd[0].trace;
+ var trace = getTraceFromCd(cd);
var t = cd[0].t;
var isViolin = trace.type === 'violin';
var closeBoxData = [];
@@ -194,7 +195,7 @@ function hoverOnPoints(pointData, xval, yval) {
var cd = pointData.cd;
var xa = pointData.xa;
var ya = pointData.ya;
- var trace = cd[0].trace;
+ var trace = getTraceFromCd(cd);
var xPx = xa.c2p(xval);
var yPx = ya.c2p(yval);
var closePtData;
diff --git a/src/traces/box/plot.js b/src/traces/box/plot.js
index d62c00079f5..426ccc461e3 100644
--- a/src/traces/box/plot.js
+++ b/src/traces/box/plot.js
@@ -1,6 +1,6 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var Lib = require('../../lib');
var Drawing = require('../../components/drawing');
@@ -67,17 +67,20 @@ function plotBoxAndWhiskers(sel, axes, trace, t) {
bdPos1 = t.bdPos;
}
- var paths = sel.selectAll('path.box').data((
- trace.type !== 'violin' ||
- trace.box.visible
- ) ? Lib.identity : []);
+ var paths = sel.selectAll('path.box')
+ .data((
+ trace.type !== 'violin' ||
+ trace.box.visible
+ ) ? Lib.identity : [])
+ .enter()
+ .append('path');
- paths.enter().append('path')
+ paths.exit().remove();
+
+ paths
.style('vector-effect', 'non-scaling-stroke')
.attr('class', 'box');
- paths.exit().remove();
-
paths.each(function(d) {
if(d.empty) return 'M0,0Z';
@@ -180,13 +183,15 @@ function plotPoints(sel, axes, trace, t) {
};
var gPoints = sel.selectAll('g.points')
- .data(mode ? fn : []);
-
- gPoints.enter().append('g')
- .attr('class', 'points');
+ .data(mode ? fn : [])
+ .enter()
+ .append('g');
gPoints.exit().remove();
+ gPoints
+ .attr('class', 'points');
+
var paths = gPoints.selectAll('path')
.data(function(d) {
var i;
@@ -257,13 +262,15 @@ function plotPoints(sel, axes, trace, t) {
}
return pts;
- });
-
- paths.enter().append('path')
- .classed('point', true);
+ })
+ .enter()
+ .append('path');
paths.exit().remove();
+ paths
+ .classed('point', true);
+
paths.call(Drawing.translatePoints, xa, ya);
}
@@ -289,14 +296,17 @@ function plotBoxMean(sel, axes, trace, t) {
bdPos1 = t.bdPos;
}
- var paths = sel.selectAll('path.mean').data((
- (trace.type === 'box' && trace.boxmean) ||
- (trace.type === 'violin' && trace.box.visible && trace.meanline.visible)
- ) ? Lib.identity : []);
+ var paths = sel.selectAll('path.mean')
+ .data((
+ (trace.type === 'box' && trace.boxmean) ||
+ (trace.type === 'violin' && trace.box.visible && trace.meanline.visible)
+ ) ? Lib.identity : [])
+ .enter()
+ .append('path');
- paths.enter().append('path')
+ paths
.attr('class', 'mean')
- .style({
+ .styles({
fill: 'none',
'vector-effect': 'non-scaling-stroke'
});
diff --git a/src/traces/box/style.js b/src/traces/box/style.js
index 5e28eeefa27..ea77b91e91f 100644
--- a/src/traces/box/style.js
+++ b/src/traces/box/style.js
@@ -1,17 +1,18 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
+var getTraceFromCd = require('../../lib/trace_from_cd');
var Color = require('../../components/color');
var Drawing = require('../../components/drawing');
function style(gd, cd, sel) {
var s = sel ? sel : d3.select(gd).selectAll('g.trace.boxes');
- s.style('opacity', function(d) { return d[0].trace.opacity; });
+ s.style('opacity', function(d) { return getTraceFromCd(d).opacity; });
s.each(function(d) {
var el = d3.select(this);
- var trace = d[0].trace;
+ var trace = getTraceFromCd(d);
var lineWidth = trace.line.width;
function styleBox(boxSel, lineWidth, lineColor, fillColor) {
@@ -35,7 +36,7 @@ function style(gd, cd, sel) {
} else {
styleBox(allBoxes, lineWidth, trace.line.color, trace.fillcolor);
el.selectAll('path.mean')
- .style({
+ .styles({
'stroke-width': lineWidth,
'stroke-dasharray': (2 * lineWidth) + 'px,' + lineWidth + 'px'
})
@@ -48,7 +49,7 @@ function style(gd, cd, sel) {
}
function styleOnSelect(gd, cd, sel) {
- var trace = cd[0].trace;
+ var trace = getTraceFromCd(cd);
var pts = sel.selectAll('path.point');
if(trace.selectedpoints) {
diff --git a/src/traces/carpet/plot.js b/src/traces/carpet/plot.js
index f12c30b8b3a..1d8c6a46695 100644
--- a/src/traces/carpet/plot.js
+++ b/src/traces/carpet/plot.js
@@ -1,6 +1,6 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var Drawing = require('../../components/drawing');
var map1dArray = require('./map_1d_array');
var makepath = require('./makepath');
@@ -81,9 +81,14 @@ function drawClipPath(trace, t, layer, xaxis, yaxis) {
function drawGridLines(xaxis, yaxis, layer, axis, axisLetter, gridlines) {
var lineClass = 'const-' + axisLetter + '-lines';
- var gridJoin = layer.selectAll('.' + lineClass).data(gridlines);
+ var gridJoin = layer.selectAll('.' + lineClass)
+ .data(gridlines)
+ .enter()
+ .append('path');
- gridJoin.enter().append('path')
+ gridJoin.exit().remove();
+
+ gridJoin
.classed(lineClass, true)
.style('vector-effect', 'non-scaling-stroke');
@@ -104,14 +109,17 @@ function drawGridLines(xaxis, yaxis, layer, axis, axisLetter, gridlines) {
.style('stroke', gridline.color)
.style('fill', 'none');
});
-
- gridJoin.exit().remove();
}
function drawAxisLabels(gd, xaxis, yaxis, trace, t, layer, labels, labelClass) {
- var labelJoin = layer.selectAll('text.' + labelClass).data(labels);
+ var labelJoin = layer.selectAll('text.' + labelClass)
+ .data(labels)
+ .enter()
+ .append('text');
- labelJoin.enter().append('text')
+ labelJoin.exit().remove();
+
+ labelJoin
.classed(labelClass, true);
var maxExtent = 0;
@@ -135,7 +143,7 @@ function drawAxisLabels(gd, xaxis, yaxis, trace, t, layer, labels, labelClass) {
var direction = (label.endAnchor ? -1 : 1) * orientation.flip;
var labelEl = d3.select(this)
- .attr({
+ .attrs({
'text-anchor': direction > 0 ? 'start' : 'end',
'data-notex': 1
})
@@ -157,8 +165,6 @@ function drawAxisLabels(gd, xaxis, yaxis, trace, t, layer, labels, labelClass) {
maxExtent = Math.max(maxExtent, bbox.width + label.axis.labelpadding);
});
- labelJoin.exit().remove();
-
labelOrientation.maxExtent = maxExtent;
return labelOrientation;
}
@@ -194,12 +200,17 @@ var lineSpacing = alignmentConstants.LINE_SPACING;
var midShift = ((1 - alignmentConstants.MID_SHIFT) / lineSpacing) + 1;
function drawAxisTitle(gd, layer, trace, t, xy, dxy, axis, xa, ya, labelOrientation, labelClass) {
+ var offset = labelOrientation.maxExtent;
var data = [];
if(axis.title.text) data.push(axis.title.text);
- var titleJoin = layer.selectAll('text.' + labelClass).data(data);
- var offset = labelOrientation.maxExtent;
+ var titleJoin = layer.selectAll('text.' + labelClass)
+ .data(data)
+ .enter()
+ .append('text');
- titleJoin.enter().append('text')
+ titleJoin.exit().remove();
+
+ titleJoin
.classed(labelClass, true);
// There's only one, but we'll do it as a join so it's updated nicely:
@@ -235,6 +246,4 @@ function drawAxisTitle(gd, layer, trace, t, xy, dxy, axis, xa, ya, labelOrientat
.attr('text-anchor', 'middle')
.call(Drawing.font, axis.title.font);
});
-
- titleJoin.exit().remove();
}
diff --git a/src/traces/choropleth/hover.js b/src/traces/choropleth/hover.js
index 0f58dec902e..dcabce3c214 100644
--- a/src/traces/choropleth/hover.js
+++ b/src/traces/choropleth/hover.js
@@ -2,11 +2,13 @@
var Axes = require('../../plots/cartesian/axes');
var attributes = require('./attributes');
-var fillText = require('../../lib').fillText;
+var Lib = require('../../lib');
+var fillText = Lib.fillText;
+var getTraceFromCd = require('../../lib/trace_from_cd');
module.exports = function hoverPoints(pointData, xval, yval) {
var cd = pointData.cd;
- var trace = cd[0].trace;
+ var trace = getTraceFromCd(cd);
var geo = pointData.subplot;
var pt, i, j, isInside;
diff --git a/src/traces/choropleth/plot.js b/src/traces/choropleth/plot.js
index da27bf17d78..d92ecdd5b42 100644
--- a/src/traces/choropleth/plot.js
+++ b/src/traces/choropleth/plot.js
@@ -1,8 +1,9 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var Lib = require('../../lib');
+var getTraceFromCd = require('../../lib/trace_from_cd');
var geoUtils = require('../../lib/geo_location_utils');
var getTopojsonFeatures = require('../../lib/topojson_utils').getTopojsonFeatures;
var findExtremes = require('../../plots/cartesian/autorange').findExtremes;
@@ -16,20 +17,22 @@ function plot(gd, geo, calcData) {
var sel = d3.select(this);
var paths = sel.selectAll('path.choroplethlocation')
- .data(Lib.identity);
-
- paths.enter().append('path')
- .classed('choroplethlocation', true);
+ .data(Lib.identity)
+ .enter()
+ .append('path');
paths.exit().remove();
+ paths
+ .classed('choroplethlocation', true);
+
// call style here within topojson request callback
style(gd, calcTrace);
});
}
function calcGeoJSON(calcTrace, fullLayout) {
- var trace = calcTrace[0].trace;
+ var trace = getTraceFromCd(calcTrace);
var geoLayout = fullLayout[trace.geo];
var geo = geoLayout._subplot;
var locationmode = trace.locationmode;
diff --git a/src/traces/choropleth/style.js b/src/traces/choropleth/style.js
index 4ca8671a64d..a77a937f00c 100644
--- a/src/traces/choropleth/style.js
+++ b/src/traces/choropleth/style.js
@@ -1,6 +1,7 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
+var getTraceFromCd = require('../../lib/trace_from_cd');
var Color = require('../../components/color');
var Drawing = require('../../components/drawing');
var Colorscale = require('../../components/colorscale');
@@ -10,7 +11,7 @@ function style(gd, calcTrace) {
}
function styleTrace(gd, calcTrace) {
- var trace = calcTrace[0].trace;
+ var trace = getTraceFromCd(calcTrace);
var s = calcTrace[0].node3;
var locs = s.selectAll('.choroplethlocation');
var marker = trace.marker || {};
@@ -31,7 +32,7 @@ function styleTrace(gd, calcTrace) {
function styleOnSelect(gd, calcTrace) {
var s = calcTrace[0].node3;
- var trace = calcTrace[0].trace;
+ var trace = getTraceFromCd(calcTrace);
if(trace.selectedpoints) {
Drawing.selectedPointStyle(s.selectAll('.choroplethlocation'), trace, gd);
diff --git a/src/traces/choroplethmapbox/convert.js b/src/traces/choroplethmapbox/convert.js
index d770eb22f80..0cfbad4e3e8 100644
--- a/src/traces/choroplethmapbox/convert.js
+++ b/src/traces/choroplethmapbox/convert.js
@@ -3,6 +3,7 @@
var isNumeric = require('fast-isnumeric');
var Lib = require('../../lib');
+var getTraceFromCd = require('../../lib/trace_from_cd');
var Colorscale = require('../../components/colorscale');
var Drawing = require('../../components/drawing');
@@ -21,7 +22,7 @@ var geoUtils = require('../../lib/geo_location_utils');
*/
function convert(calcTrace) {
- var trace = calcTrace[0].trace;
+ var trace = getTraceFromCd(calcTrace);
var isVisible = trace.visible === true && trace._length !== 0;
var fill = {
@@ -113,7 +114,7 @@ function convert(calcTrace) {
}
function convertOnSelect(calcTrace) {
- var trace = calcTrace[0].trace;
+ var trace = getTraceFromCd(calcTrace);
var opts = trace._opts;
var opacitySetting;
diff --git a/src/traces/choroplethmapbox/index.js b/src/traces/choroplethmapbox/index.js
index 5c1f1ce8f43..bb51a00feef 100644
--- a/src/traces/choroplethmapbox/index.js
+++ b/src/traces/choroplethmapbox/index.js
@@ -1,5 +1,7 @@
'use strict';
+var getTraceFromCd = require('../../lib/trace_from_cd');
+
module.exports = {
attributes: require('./attributes'),
supplyDefaults: require('./defaults'),
@@ -12,7 +14,7 @@ module.exports = {
styleOnSelect: function(_, cd) {
if(cd) {
- var trace = cd[0].trace;
+ var trace = getTraceFromCd(cd);
trace._glTrace.updateOnSelect(cd);
}
},
diff --git a/src/traces/choroplethmapbox/plot.js b/src/traces/choroplethmapbox/plot.js
index 874cf7c6cae..892dcae27a5 100644
--- a/src/traces/choroplethmapbox/plot.js
+++ b/src/traces/choroplethmapbox/plot.js
@@ -2,6 +2,7 @@
var convert = require('./convert').convert;
var convertOnSelect = require('./convert').convertOnSelect;
+var getTraceFromCd = require('../../lib/trace_from_cd');
var LAYER_PREFIX = require('../../plots/mapbox/constants').traceLayerPrefix;
function ChoroplethMapbox(subplot, uid) {
@@ -97,7 +98,7 @@ proto.dispose = function() {
};
module.exports = function createChoroplethMapbox(subplot, calcTrace) {
- var trace = calcTrace[0].trace;
+ var trace = getTraceFromCd(calcTrace);
var choroplethMapbox = new ChoroplethMapbox(subplot, trace.uid);
var sourceId = choroplethMapbox.sourceId;
var optsAll = convert(calcTrace);
@@ -111,7 +112,7 @@ module.exports = function createChoroplethMapbox(subplot, calcTrace) {
choroplethMapbox._addLayers(optsAll, below);
// link ref for quick update during selections
- calcTrace[0].trace._glTrace = choroplethMapbox;
+ getTraceFromCd(calcTrace)._glTrace = choroplethMapbox;
return choroplethMapbox;
};
diff --git a/src/traces/contour/make_color_map.js b/src/traces/contour/make_color_map.js
index 46cc9f10a28..e225919979e 100644
--- a/src/traces/contour/make_color_map.js
+++ b/src/traces/contour/make_color_map.js
@@ -1,6 +1,6 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var Colorscale = require('../../components/colorscale');
var endPlus = require('./end_plus');
diff --git a/src/traces/contour/plot.js b/src/traces/contour/plot.js
index 76b4520fea9..918e9d0ea7c 100644
--- a/src/traces/contour/plot.js
+++ b/src/traces/contour/plot.js
@@ -1,6 +1,6 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var Lib = require('../../lib');
var Drawing = require('../../components/drawing');
@@ -71,9 +71,12 @@ function makeBackground(plotgroup, perimeter, contours) {
var bggroup = Lib.ensureSingle(plotgroup, 'g', 'contourbg');
var bgfill = bggroup.selectAll('path')
- .data(contours.coloring === 'fill' ? [0] : []);
- bgfill.enter().append('path');
+ .data(contours.coloring === 'fill' ? [0] : [])
+ .enter()
+ .append('path');
+
bgfill.exit().remove();
+
bgfill
.attr('d', 'M' + perimeter.join('L') + 'Z')
.style('stroke', 'none');
@@ -90,9 +93,13 @@ function makeFills(plotgroup, pathinfo, perimeter, contours) {
var fillgroup = Lib.ensureSingle(plotgroup, 'g', 'contourfill');
- var fillitems = fillgroup.selectAll('path').data(hasFills ? pathinfo : []);
- fillitems.enter().append('path');
+ var fillitems = fillgroup.selectAll('path')
+ .data(hasFills ? pathinfo : [])
+ .enter()
+ .append('path');
+
fillitems.exit().remove();
+
fillitems.each(function(pi) {
// join all paths for this level together into a single path
// first follow clockwise around the perimeter to close any open paths
@@ -214,11 +221,13 @@ function makeLinesAndLabels(plotgroup, pathinfo, gd, cd0, contours) {
var lineClip = exports.createLineClip(lineContainer, clipLinesForLabels, gd, cd0.trace.uid);
var labelGroup = plotgroup.selectAll('g.contourlabels')
- .data(showLabels ? [0] : []);
+ .data(showLabels ? [0] : [])
+ .enter()
+ .append('g');
labelGroup.exit().remove();
- labelGroup.enter().append('g')
+ labelGroup
.classed('contourlabels', true);
if(showLabels) {
@@ -322,23 +331,27 @@ exports.createLines = function(lineContainer, makeLines, pathinfo) {
var smoothing = pathinfo[0].smoothing;
var linegroup = lineContainer.selectAll('g.contourlevel')
- .data(makeLines ? pathinfo : []);
+ .data(makeLines ? pathinfo : [])
+ .enter()
+ .append('g');
linegroup.exit().remove();
- linegroup.enter().append('g')
+
+ linegroup
.classed('contourlevel', true);
if(makeLines) {
// pedgepaths / ppaths are used by contourcarpet, for the paths transformed from a/b to x/y
// edgepaths / paths are used by contour since it's in x/y from the start
var opencontourlines = linegroup.selectAll('path.openline')
- .data(function(d) { return d.pedgepaths || d.edgepaths; });
+ .data(function(d) { return d.pedgepaths || d.edgepaths; })
+ .enter()
+ .append('path');
opencontourlines.exit().remove();
- opencontourlines.enter().append('path')
- .classed('openline', true);
opencontourlines
+ .classed('openline', true)
.attr('d', function(d) {
return Drawing.smoothopen(d, smoothing);
})
@@ -346,13 +359,14 @@ exports.createLines = function(lineContainer, makeLines, pathinfo) {
.style('vector-effect', 'non-scaling-stroke');
var closedcontourlines = linegroup.selectAll('path.closedline')
- .data(function(d) { return d.ppaths || d.paths; });
+ .data(function(d) { return d.ppaths || d.paths; })
+ .enter()
+ .append('path');
closedcontourlines.exit().remove();
- closedcontourlines.enter().append('path')
- .classed('closedline', true);
closedcontourlines
+ .classed('closedline', true)
.attr('d', function(d) {
return Drawing.smoothclosed(d, smoothing);
})
@@ -368,10 +382,13 @@ exports.createLineClip = function(lineContainer, clipLinesForLabels, gd, uid) {
var clipId = clipLinesForLabels ? ('clipline' + uid) : null;
var lineClip = clips.selectAll('#' + clipId)
- .data(clipLinesForLabels ? [0] : []);
+ .data(clipLinesForLabels ? [0] : [])
+ .enter()
+ .append('clipPath');
+
lineClip.exit().remove();
- lineClip.enter().append('clipPath')
+ lineClip
.classed('contourlineclip', true)
.attr('id', clipId);
@@ -580,12 +597,14 @@ exports.drawLabels = function(labelGroup, labelData, gd, lineClip, labelClipPath
var labels = labelGroup.selectAll('text')
.data(labelData, function(d) {
return d.text + ',' + d.x + ',' + d.y + ',' + d.theta;
- });
+ })
+ .enter()
+ .append('text');
labels.exit().remove();
- labels.enter().append('text')
- .attr({
+ labels
+ .attrs({
'data-notex': 1,
'text-anchor': 'middle'
})
@@ -594,7 +613,7 @@ exports.drawLabels = function(labelGroup, labelData, gd, lineClip, labelClipPath
var y = d.y - Math.cos(d.theta) * d.dy;
d3.select(this)
.text(d.text)
- .attr({
+ .attrs({
x: x,
y: y,
transform: 'rotate(' + (180 * d.theta / Math.PI) + ' ' + x + ' ' + y + ')'
@@ -619,11 +638,15 @@ function clipGaps(plotGroup, plotinfo, gd, cd0, perimeter) {
var clipId = 'clip' + trace.uid;
var clipPath = clips.selectAll('#' + clipId)
- .data(trace.connectgaps ? [] : [0]);
- clipPath.enter().append('clipPath')
+ .data(trace.connectgaps ? [] : [0])
+ .enter()
+ .append('clipPath');
+
+ clipPath.exit().remove();
+
+ clipPath
.classed('contourclip', true)
.attr('id', clipId);
- clipPath.exit().remove();
if(trace.connectgaps === false) {
var clipPathInfo = {
diff --git a/src/traces/contour/style.js b/src/traces/contour/style.js
index 7206581606f..aa95eceffae 100644
--- a/src/traces/contour/style.js
+++ b/src/traces/contour/style.js
@@ -1,7 +1,7 @@
'use strict';
-var d3 = require('@plotly/d3');
-
+var d3 = require('../../lib/d3');
+var getTraceFromCd = require('../../lib/trace_from_cd');
var Drawing = require('../../components/drawing');
var heatmapStyle = require('../heatmap/style');
@@ -12,12 +12,12 @@ module.exports = function style(gd) {
var contours = d3.select(gd).selectAll('g.contour');
contours.style('opacity', function(d) {
- return d[0].trace.opacity;
+ return getTraceFromCd(d).opacity;
});
contours.each(function(d) {
var c = d3.select(this);
- var trace = d[0].trace;
+ var trace = getTraceFromCd(d);
var contours = trace.contours;
var line = trace.line;
var cs = contours.size || 1;
diff --git a/src/traces/contourcarpet/plot.js b/src/traces/contourcarpet/plot.js
index 2b2181c9a84..a6b9c1ed82d 100644
--- a/src/traces/contourcarpet/plot.js
+++ b/src/traces/contourcarpet/plot.js
@@ -1,6 +1,6 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var map1dArray = require('../carpet/map_1d_array');
var makepath = require('../carpet/makepath');
var Drawing = require('../../components/drawing');
@@ -148,11 +148,13 @@ function makeLinesAndLabels(plotgroup, pathinfo, gd, cd0, contours, plotinfo, ca
var lineClip = contourPlot.createLineClip(lineContainer, clipLinesForLabels, gd, cd0.trace.uid);
var labelGroup = plotgroup.selectAll('g.contourlabels')
- .data(showLabels ? [0] : []);
+ .data(showLabels ? [0] : [])
+ .enter()
+ .append('g');
labelGroup.exit().remove();
- labelGroup.enter().append('g')
+ labelGroup
.classed('contourlabels', true);
if(showLabels) {
@@ -301,8 +303,10 @@ function makeBackground(plotgroup, clipsegments, xaxis, yaxis, isConstraint, col
var bggroup = Lib.ensureSingle(plotgroup, 'g', 'contourbg');
var bgfill = bggroup.selectAll('path')
- .data((coloring === 'fill' && !isConstraint) ? [0] : []);
- bgfill.enter().append('path');
+ .data((coloring === 'fill' && !isConstraint) ? [0] : [])
+ .enter()
+ .append('path');
+
bgfill.exit().remove();
var segs = [];
@@ -327,9 +331,13 @@ function makeFills(trace, plotgroup, xa, ya, pathinfo, perimeter, ab2p, carpet,
}
var fillgroup = Lib.ensureSingle(plotgroup, 'g', 'contourfill');
- var fillitems = fillgroup.selectAll('path').data(hasFills ? pathinfo : []);
- fillitems.enter().append('path');
+ var fillitems = fillgroup.selectAll('path')
+ .data(hasFills ? pathinfo : [])
+ .enter()
+ .append('path');
+
fillitems.exit().remove();
+
fillitems.each(function(pi) {
// join all paths for this level together into a single path
// first follow clockwise around the perimeter to close any open paths
diff --git a/src/traces/densitymapbox/convert.js b/src/traces/densitymapbox/convert.js
index 5dc11b89a30..525182d47cb 100644
--- a/src/traces/densitymapbox/convert.js
+++ b/src/traces/densitymapbox/convert.js
@@ -3,6 +3,7 @@
var isNumeric = require('fast-isnumeric');
var Lib = require('../../lib');
+var getTraceFromCd = require('../../lib/trace_from_cd');
var Color = require('../../components/color');
var Colorscale = require('../../components/colorscale');
@@ -10,7 +11,7 @@ var BADNUM = require('../../constants/numerical').BADNUM;
var makeBlank = require('../../lib/geojson_utils').makeBlank;
module.exports = function convert(calcTrace) {
- var trace = calcTrace[0].trace;
+ var trace = getTraceFromCd(calcTrace);
var isVisible = (trace.visible === true && trace._length !== 0);
var heatmap = {
diff --git a/src/traces/densitymapbox/hover.js b/src/traces/densitymapbox/hover.js
index 2128ba96f69..e3f93ccd24d 100644
--- a/src/traces/densitymapbox/hover.js
+++ b/src/traces/densitymapbox/hover.js
@@ -1,5 +1,6 @@
'use strict';
+var getTraceFromCd = require('../../lib/trace_from_cd');
var Axes = require('../../plots/cartesian/axes');
var scatterMapboxHoverPoints = require('../scattermapbox/hover').hoverPoints;
var getExtraText = require('../scattermapbox/hover').getExtraText;
@@ -10,7 +11,7 @@ module.exports = function hoverPoints(pointData, xval, yval) {
var newPointData = pts[0];
var cd = newPointData.cd;
- var trace = cd[0].trace;
+ var trace = getTraceFromCd(cd);
var di = cd[newPointData.index];
// let Fx.hover pick the color
diff --git a/src/traces/densitymapbox/plot.js b/src/traces/densitymapbox/plot.js
index a4ff5e685ee..b5d8d8e099a 100644
--- a/src/traces/densitymapbox/plot.js
+++ b/src/traces/densitymapbox/plot.js
@@ -1,6 +1,7 @@
'use strict';
var convert = require('./convert');
+var getTraceFromCd = require('../../lib/trace_from_cd');
var LAYER_PREFIX = require('../../plots/mapbox/constants').traceLayerPrefix;
function DensityMapbox(subplot, uid) {
@@ -87,7 +88,7 @@ proto.dispose = function() {
};
module.exports = function createDensityMapbox(subplot, calcTrace) {
- var trace = calcTrace[0].trace;
+ var trace = getTraceFromCd(calcTrace);
var densityMapbox = new DensityMapbox(subplot, trace.uid);
var sourceId = densityMapbox.sourceId;
var optsAll = convert(calcTrace);
diff --git a/src/traces/funnel/hover.js b/src/traces/funnel/hover.js
index 21493dcb208..290d11d7af1 100644
--- a/src/traces/funnel/hover.js
+++ b/src/traces/funnel/hover.js
@@ -2,14 +2,16 @@
var opacity = require('../../components/color').opacity;
var hoverOnBars = require('../bar/hover').hoverOnBars;
-var formatPercent = require('../../lib').formatPercent;
+var Lib = require('../../lib');
+var formatPercent = Lib.formatPercent;
+var getTraceFromCd = require('../../lib/trace_from_cd');
module.exports = function hoverPoints(pointData, xval, yval, hovermode, opts) {
var point = hoverOnBars(pointData, xval, yval, hovermode, opts);
if(!point) return;
var cd = point.cd;
- var trace = cd[0].trace;
+ var trace = getTraceFromCd(cd);
var isHorizontal = (trace.orientation === 'h');
// the closest data point
diff --git a/src/traces/funnel/plot.js b/src/traces/funnel/plot.js
index 43f23723e48..c5f18287fe4 100644
--- a/src/traces/funnel/plot.js
+++ b/src/traces/funnel/plot.js
@@ -1,7 +1,8 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var Lib = require('../../lib');
+var getTraceFromCd = require('../../lib/trace_from_cd');
var Drawing = require('../../components/drawing');
var BADNUM = require('../../constants/numerical').BADNUM;
var barPlot = require('../bar/plot');
@@ -29,7 +30,7 @@ function plotConnectorRegions(gd, plotinfo, cdModule, traceLayer) {
Lib.makeTraceGroups(traceLayer, cdModule, 'trace bars').each(function(cd) {
var plotGroup = d3.select(this);
- var trace = cd[0].trace;
+ var trace = getTraceFromCd(cd);
var group = Lib.ensureSingle(plotGroup, 'g', 'regions');
@@ -40,13 +41,15 @@ function plotConnectorRegions(gd, plotinfo, cdModule, traceLayer) {
var isHorizontal = (trace.orientation === 'h');
- var connectors = group.selectAll('g.region').data(Lib.identity);
-
- connectors.enter().append('g')
- .classed('region', true);
+ var connectors = group.selectAll('g.region').data(Lib.identity)
+ .enter()
+ .append('g');
connectors.exit().remove();
+ connectors
+ .classed('region', true);
+
var len = connectors.size();
connectors.each(function(di, i) {
@@ -87,7 +90,7 @@ function plotConnectorLines(gd, plotinfo, cdModule, traceLayer) {
Lib.makeTraceGroups(traceLayer, cdModule, 'trace bars').each(function(cd) {
var plotGroup = d3.select(this);
- var trace = cd[0].trace;
+ var trace = getTraceFromCd(cd);
var group = Lib.ensureSingle(plotGroup, 'g', 'lines');
@@ -98,13 +101,15 @@ function plotConnectorLines(gd, plotinfo, cdModule, traceLayer) {
var isHorizontal = (trace.orientation === 'h');
- var connectors = group.selectAll('g.line').data(Lib.identity);
-
- connectors.enter().append('g')
- .classed('line', true);
+ var connectors = group.selectAll('g.line').data(Lib.identity)
+ .enter()
+ .append('g');
connectors.exit().remove();
+ connectors
+ .classed('line', true);
+
var len = connectors.size();
connectors.each(function(di, i) {
diff --git a/src/traces/funnel/style.js b/src/traces/funnel/style.js
index 2a393fd15a6..bb27e4d76c9 100644
--- a/src/traces/funnel/style.js
+++ b/src/traces/funnel/style.js
@@ -1,7 +1,7 @@
'use strict';
-var d3 = require('@plotly/d3');
-
+var d3 = require('../../lib/d3');
+var getTraceFromCd = require('../../lib/trace_from_cd');
var Drawing = require('../../components/drawing');
var Color = require('../../components/color');
var DESELECTDIM = require('../../constants/interactions').DESELECTDIM;
@@ -13,11 +13,11 @@ function style(gd, cd, sel) {
var s = sel ? sel : d3.select(gd).selectAll('g.funnellayer').selectAll('g.trace');
resizeText(gd, s, 'funnel');
- s.style('opacity', function(d) { return d[0].trace.opacity; });
+ s.style('opacity', function(d) { return getTraceFromCd(d).opacity; });
s.each(function(d) {
var gTrace = d3.select(this);
- var trace = d[0].trace;
+ var trace = getTraceFromCd(d);
gTrace.selectAll('.point > path').each(function(di) {
if(!di.isBlank) {
diff --git a/src/traces/funnelarea/plot.js b/src/traces/funnelarea/plot.js
index dbf790a0f4b..cb7ef983dfa 100644
--- a/src/traces/funnelarea/plot.js
+++ b/src/traces/funnelarea/plot.js
@@ -1,6 +1,6 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var Drawing = require('../../components/drawing');
var Lib = require('../../lib');
@@ -40,12 +40,16 @@ module.exports = function plot(gd, cdModule) {
setCoords(cd);
plotGroup.each(function() {
- var slices = d3.select(this).selectAll('g.slice').data(cd);
+ var slices = d3.select(this).selectAll('g.slice')
+ .data(cd)
+ .enter()
+ .append('g');
- slices.enter().append('g')
- .classed('slice', true);
slices.exit().remove();
+ slices
+ .classed('slice', true);
+
slices.each(function(pt, i) {
if(pt.hidden) {
d3.select(this).selectAll('path,g').remove();
@@ -58,14 +62,6 @@ module.exports = function plot(gd, cdModule) {
var cx = cd0.cx;
var cy = cd0.cy;
- var sliceTop = d3.select(this);
- var slicePath = sliceTop.selectAll('path.surface').data([pt]);
-
- slicePath.enter().append('path')
- .classed('surface', true)
- .style({'pointer-events': 'all'});
-
- sliceTop.call(attachFxHandlers, gd, cd);
var shape =
'M' + (cx + pt.TR[0]) + ',' + (cy + pt.TR[1]) +
@@ -74,18 +70,33 @@ module.exports = function plot(gd, cdModule) {
line(pt.BL, pt.TL) +
'Z';
- slicePath.attr('d', shape);
+ var sliceTop = d3.select(this);
+ var slicePath = sliceTop.selectAll('path.surface')
+ .data([pt])
+ .enter()
+ .append('path');
+
+ slicePath.exit().remove();
+
+ slicePath
+ .classed('surface', true)
+ .styles({'pointer-events': 'all'})
+ .call(attachFxHandlers, gd, cd)
+ .attr('d', shape);
// add text
formatSliceLabel(gd, pt, cd0);
var textPosition = pieHelpers.castOption(trace.textposition, pt.pts);
var sliceTextGroup = sliceTop.selectAll('g.slicetext')
- .data(pt.text && (textPosition !== 'none') ? [0] : []);
+ .data(pt.text && (textPosition !== 'none') ? [0] : [])
+ .enter()
+ .append('g');
- sliceTextGroup.enter().append('g')
- .classed('slicetext', true);
sliceTextGroup.exit().remove();
+ sliceTextGroup
+ .classed('slicetext', true);
+
sliceTextGroup.each(function() {
var sliceText = Lib.ensureSingle(d3.select(this), 'text', '', function(s) {
// prohibit tex interpretation until we can handle
@@ -96,7 +107,7 @@ module.exports = function plot(gd, cdModule) {
var font = Lib.ensureUniformFontSize(gd, determineInsideTextFont(trace, pt, fullLayout.font));
sliceText.text(pt.text)
- .attr({
+ .attrs({
'class': 'slicetext',
transform: '',
'text-anchor': 'middle'
@@ -132,12 +143,15 @@ module.exports = function plot(gd, cdModule) {
// add the title
var titleTextGroup = d3.select(this).selectAll('g.titletext')
- .data(trace.title.text ? [0] : []);
+ .data(trace.title.text ? [0] : [])
+ .enter()
+ .append('g');
- titleTextGroup.enter().append('g')
- .classed('titletext', true);
titleTextGroup.exit().remove();
+ titleTextGroup
+ .classed('titletext', true);
+
titleTextGroup.each(function() {
var titleText = Lib.ensureSingle(d3.select(this), 'text', '', function(s) {
// prohibit tex interpretation as above
@@ -150,7 +164,7 @@ module.exports = function plot(gd, cdModule) {
}
titleText.text(txt)
- .attr({
+ .attrs({
'class': 'titletext',
transform: '',
'text-anchor': 'middle',
diff --git a/src/traces/funnelarea/style.js b/src/traces/funnelarea/style.js
index 40f5b36cde9..aea577f032e 100644
--- a/src/traces/funnelarea/style.js
+++ b/src/traces/funnelarea/style.js
@@ -1,6 +1,6 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var styleOne = require('../pie/style_one');
var resizeText = require('../bar/uniform_text').resizeText;
@@ -14,7 +14,7 @@ module.exports = function style(gd) {
var trace = cd0.trace;
var traceSelection = d3.select(this);
- traceSelection.style({opacity: trace.opacity});
+ traceSelection.styles({opacity: trace.opacity});
traceSelection.selectAll('path.surface').each(function(pt) {
d3.select(this).call(styleOne, pt, trace);
diff --git a/src/traces/heatmap/plot.js b/src/traces/heatmap/plot.js
index e511866bb07..8e80df9b4cb 100644
--- a/src/traces/heatmap/plot.js
+++ b/src/traces/heatmap/plot.js
@@ -1,6 +1,6 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var tinycolor = require('tinycolor2');
var Registry = require('../../registry');
@@ -317,15 +317,15 @@ module.exports = function(gd, plotinfo, cdheatmaps, heatmapLayer) {
gd._hmpixcount = (gd._hmpixcount||0) + pixcount;
gd._hmlumcount = (gd._hmlumcount||0) + pixcount * avgColor.getLuminance();
- var image3 = plotGroup.selectAll('image')
- .data(cd);
+ var image3 = plotGroup.selectAll('image').data(cd)
+ .enter()
+ .append('svg:image');
- image3.enter().append('svg:image').attr({
- xmlns: xmlnsNamespaces.svg,
- preserveAspectRatio: 'none'
- });
+ image3.exit().remove();
- image3.attr({
+ image3.attrs({
+ xmlns: xmlnsNamespaces.svg,
+ preserveAspectRatio: 'none',
height: imageHeight,
width: imageWidth,
x: left,
diff --git a/src/traces/heatmap/style.js b/src/traces/heatmap/style.js
index 0e6e1bd4a31..eac56c4901d 100644
--- a/src/traces/heatmap/style.js
+++ b/src/traces/heatmap/style.js
@@ -1,6 +1,6 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
module.exports = function style(gd) {
d3.select(gd).selectAll('.hm image')
diff --git a/src/traces/histogram/hover.js b/src/traces/histogram/hover.js
index 8b3f26e20c1..1faaf8aaae5 100644
--- a/src/traces/histogram/hover.js
+++ b/src/traces/histogram/hover.js
@@ -1,5 +1,6 @@
'use strict';
+var getTraceFromCd = require('../../lib/trace_from_cd');
var barHover = require('../bar/hover').hoverPoints;
var hoverLabelText = require('../../plots/cartesian/axes').hoverLabelText;
@@ -10,7 +11,7 @@ module.exports = function hoverPoints(pointData, xval, yval, hovermode, opts) {
pointData = pts[0];
var di = pointData.cd[pointData.index];
- var trace = pointData.cd[0].trace;
+ var trace = getTraceFromCd(pointData.cd);
if(!trace.cumulative.enabled) {
var posLetter = trace.orientation === 'h' ? 'y' : 'x';
diff --git a/src/traces/icicle/draw_descendants.js b/src/traces/icicle/draw_descendants.js
index feec1ce4386..e5b7d529d20 100644
--- a/src/traces/icicle/draw_descendants.js
+++ b/src/traces/icicle/draw_descendants.js
@@ -1,6 +1,6 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var Lib = require('../../lib');
var Drawing = require('../../components/drawing');
var svgTextUtils = require('../../lib/svg_text_utils');
@@ -65,15 +65,18 @@ module.exports = function drawDescendants(gd, cd, entry, slices, opts) {
}
});
- slices = slices.data(sliceData, helpers.getPtId);
-
trace._maxVisibleLayers = isFinite(maxVisibleDepth) ? maxVisibleDepth - minVisibleDepth + 1 : 0;
- slices.enter().append('g')
- .classed('slice', true);
+ slices = slices
+ .data(sliceData, helpers.getPtId)
+ .enter()
+ .append('g');
handleSlicesExit(slices, onPathbar, refRect, [width, height], pathSlice);
+ slices
+ .classed('slice', true);
+
slices.order();
// next coords of previous entry
diff --git a/src/traces/icicle/style.js b/src/traces/icicle/style.js
index d4c429df953..99113b67166 100644
--- a/src/traces/icicle/style.js
+++ b/src/traces/icicle/style.js
@@ -1,6 +1,6 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var Color = require('../../components/color');
var Lib = require('../../lib');
var resizeText = require('../bar/uniform_text').resizeText;
diff --git a/src/traces/image/plot.js b/src/traces/image/plot.js
index e182df8db81..f2ca69606f3 100644
--- a/src/traces/image/plot.js
+++ b/src/traces/image/plot.js
@@ -1,6 +1,6 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var Lib = require('../../lib');
var strTranslate = Lib.strTranslate;
var xmlnsNamespaces = require('../../constants/xmlns_namespaces');
@@ -122,17 +122,19 @@ module.exports = function plot(gd, plotinfo, cdimage, imageLayer) {
}
var image3 = plotGroup.selectAll('image')
- .data([cd]);
-
- image3.enter().append('svg:image').attr({
- xmlns: xmlnsNamespaces.svg,
- preserveAspectRatio: 'none'
- });
+ .data([cd])
+ .enter()
+ .append('svg:image');
image3.exit().remove();
- var style = (trace.zsmooth === false) ? constants.pixelatedStyle : '';
+ image3
+ .attrs({
+ xmlns: xmlnsNamespaces.svg,
+ preserveAspectRatio: 'none'
+ });
+ var style = (trace.zsmooth === false) ? constants.pixelatedStyle : '';
if(realImage) {
var xRange = Lib.simpleMap(xa.range, xa.r2l);
var yRange = Lib.simpleMap(ya.range, ya.r2l);
@@ -207,7 +209,7 @@ module.exports = function plot(gd, plotinfo, cdimage, imageLayer) {
}
}
- image3.attr({
+ image3.attrs({
'xlink:href': href,
height: imageHeight,
width: imageWidth,
diff --git a/src/traces/image/style.js b/src/traces/image/style.js
index e6363239f04..22fa4b86565 100644
--- a/src/traces/image/style.js
+++ b/src/traces/image/style.js
@@ -1,10 +1,11 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
+var getTraceFromCd = require('../../lib/trace_from_cd');
module.exports = function style(gd) {
d3.select(gd).selectAll('.im image')
.style('opacity', function(d) {
- return d[0].trace.opacity;
+ return getTraceFromCd(d).opacity;
});
};
diff --git a/src/traces/indicator/plot.js b/src/traces/indicator/plot.js
index 88b9d5019b1..472454654f6 100644
--- a/src/traces/indicator/plot.js
+++ b/src/traces/indicator/plot.js
@@ -1,10 +1,11 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var interpolate = require('d3-interpolate').interpolate;
var interpolateNumber = require('d3-interpolate').interpolateNumber;
var Lib = require('../../lib');
+var getTraceFromCd = require('../../lib/trace_from_cd');
var strScale = Lib.strScale;
var strTranslate = Lib.strTranslate;
var rad2deg = Lib.rad2deg;
@@ -141,9 +142,18 @@ module.exports = function plot(gd, cdModule, transitionOpts, makeOnCompleteCallb
}
// Prepare angular gauge layers
- var angularGauge = plotGroup.selectAll('g.angular').data(isAngular ? cd : []);
+ var angularGauge = plotGroup.selectAll('g.angular')
+ .data(isAngular ? cd : [])
+ .enter()
+ .append('g');
+
angularGauge.exit().remove();
- var angularaxisLayer = plotGroup.selectAll('g.angularaxis').data(isAngular ? cd : []);
+
+ var angularaxisLayer = plotGroup.selectAll('g.angularaxis')
+ .data(isAngular ? cd : [])
+ .enter()
+ .append('g');
+
angularaxisLayer.exit().remove();
if(isAngular) {
@@ -180,10 +190,15 @@ module.exports = function plot(gd, cdModule, transitionOpts, makeOnCompleteCallb
}
// title
- var title = plotGroup.selectAll('text.title').data(cd);
+ var title = plotGroup.selectAll('text.title')
+ .data(cd)
+ .enter()
+ .append('text');
+
title.exit().remove();
- title.enter().append('text').classed('title', true);
+
title
+ .classed('title', true)
.attr('text-anchor', function() {
return isBullet ? anchor.right : anchor[trace.title.align];
})
@@ -222,7 +237,7 @@ module.exports = function plot(gd, cdModule, transitionOpts, makeOnCompleteCallb
};
function drawBulletGauge(gd, plotGroup, cd, opts) {
- var trace = cd[0].trace;
+ var trace = getTraceFromCd(cd);
var bullet = opts.gauge;
var axisLayer = opts.layer;
@@ -232,18 +247,20 @@ function drawBulletGauge(gd, plotGroup, cd, opts) {
var domain = trace.domain;
var transitionOpts = opts.transitionOpts;
+ var d3EaseFn = Lib.whichD3EaseFn(transitionOpts);
+
var onComplete = opts.onComplete;
// preparing axis
var ax, vals, transFn, tickSign, shift;
- // Enter bullet, axis
- bullet.enter().append('g').classed('bullet', true);
+ bullet.classed('bullet', true);
bullet.attr('transform', strTranslate(size.l, size.t));
- axisLayer.enter().append('g')
+ axisLayer
.classed('bulletaxis', true)
.classed('crisp', true);
+
axisLayer.selectAll('g.' + 'xbulletaxis' + 'tick,path,text').remove();
// Draw bullet
@@ -288,16 +305,29 @@ function drawBulletGauge(gd, plotGroup, cd, opts) {
// Draw bullet background, steps
var boxes = [gaugeBg].concat(trace.gauge.steps);
- var bgBullet = bullet.selectAll('g.bg-bullet').data(boxes);
- bgBullet.enter().append('g').classed('bg-bullet', true).append('rect');
+ var bgBullet = bullet.selectAll('g.bg-bullet')
+ .data(boxes)
+ .enter()
+ .append('g');
+
+ bgBullet.exit().remove();
+
+ bgBullet
+ .classed('bg-bullet', true).append('rect');
+
bgBullet.select('rect')
.call(drawRect)
.call(styleShape);
- bgBullet.exit().remove();
// Draw value bar with transitions
- var fgBullet = bullet.selectAll('g.value-bullet').data([trace.gauge.bar]);
- fgBullet.enter().append('g').classed('value-bullet', true).append('rect');
+ var fgBullet = bullet.selectAll('g.value-bullet')
+ .data([trace.gauge.bar])
+ .enter()
+ .append('g');
+
+ fgBullet.exit().remove();
+
+ fgBullet.classed('value-bullet', true).append('rect');
fgBullet.select('rect')
.attr('height', innerBulletHeight)
.attr('y', (bulletHeight - innerBulletHeight) / 2)
@@ -306,7 +336,7 @@ function drawBulletGauge(gd, plotGroup, cd, opts) {
fgBullet.select('rect')
.transition()
.duration(transitionOpts.duration)
- .ease(transitionOpts.easing)
+ .ease(d3EaseFn)
.each('end', function() { onComplete && onComplete(); })
.each('interrupt', function() { onComplete && onComplete(); })
.attr('width', Math.max(0, ax.c2p(Math.min(trace.gauge.axis.range[1], cd[0].y))));
@@ -316,11 +346,16 @@ function drawBulletGauge(gd, plotGroup, cd, opts) {
Math.max(0, ax.c2p(Math.min(trace.gauge.axis.range[1], cd[0].y))) :
0);
}
- fgBullet.exit().remove();
var data = cd.filter(function() {return trace.gauge.threshold.value || trace.gauge.threshold.value === 0;});
- var threshold = bullet.selectAll('g.threshold-bullet').data(data);
- threshold.enter().append('g').classed('threshold-bullet', true).append('line');
+ var threshold = bullet.selectAll('g.threshold-bullet')
+ .data(data)
+ .enter()
+ .append('g');
+
+ threshold.exit().remove();
+
+ threshold.classed('threshold-bullet', true).append('line');
threshold.select('line')
.attr('x1', ax.c2p(trace.gauge.threshold.value))
.attr('x2', ax.c2p(trace.gauge.threshold.value))
@@ -328,18 +363,22 @@ function drawBulletGauge(gd, plotGroup, cd, opts) {
.attr('y2', (1 - (1 - trace.gauge.threshold.thickness) / 2) * bulletHeight)
.call(Color.stroke, trace.gauge.threshold.line.color)
.style('stroke-width', trace.gauge.threshold.line.width);
- threshold.exit().remove();
- var bulletOutline = bullet.selectAll('g.gauge-outline').data([gaugeOutline]);
- bulletOutline.enter().append('g').classed('gauge-outline', true).append('rect');
+ var bulletOutline = bullet.selectAll('g.gauge-outline')
+ .data([gaugeOutline])
+ .enter()
+ .append('g');
+
+ bulletOutline.exit().remove();
+
+ bulletOutline.classed('gauge-outline', true).append('rect');
bulletOutline.select('rect')
.call(drawRect)
.call(styleShape);
- bulletOutline.exit().remove();
}
function drawAngularGauge(gd, plotGroup, cd, opts) {
- var trace = cd[0].trace;
+ var trace = getTraceFromCd(cd);
var size = opts.size;
var radius = opts.radius;
@@ -351,6 +390,7 @@ function drawAngularGauge(gd, plotGroup, cd, opts) {
var axisLayer = opts.layer;
var transitionOpts = opts.transitionOpts;
+ var d3EaseFn = Lib.whichD3EaseFn(transitionOpts);
var onComplete = opts.onComplete;
// circular gauge
@@ -365,7 +405,7 @@ function drawAngularGauge(gd, plotGroup, cd, opts) {
}
function arcPathGenerator(size) {
- return d3.svg.arc()
+ return d3.arc()
.innerRadius((innerRadius + radius) / 2 - size / 2 * (radius - innerRadius))
.outerRadius((innerRadius + radius) / 2 + size / 2 * (radius - innerRadius))
.startAngle(-theta);
@@ -384,10 +424,10 @@ function drawAngularGauge(gd, plotGroup, cd, opts) {
var ax, vals, transFn, tickSign;
// Enter gauge and axis
- gauge.enter().append('g').classed('angular', true);
+ gauge.classed('angular', true);
gauge.attr('transform', strTranslate(gaugePosition[0], gaugePosition[1]));
- axisLayer.enter().append('g')
+ axisLayer
.classed('angularaxis', true)
.classed('crisp', true);
axisLayer.selectAll('g.' + 'xangularaxis' + 'tick,path,text').remove();
@@ -462,21 +502,32 @@ function drawAngularGauge(gd, plotGroup, cd, opts) {
// Draw background + steps
var arcs = [gaugeBg].concat(trace.gauge.steps);
- var bgArc = gauge.selectAll('g.bg-arc').data(arcs);
- bgArc.enter().append('g').classed('bg-arc', true).append('path');
- bgArc.select('path').call(drawArc).call(styleShape);
+ var bgArc = gauge.selectAll('g.bg-arc')
+ .data(arcs)
+ .enter()
+ .append('g');
+
bgArc.exit().remove();
+ bgArc.classed('bg-arc', true).append('path');
+ bgArc.select('path').call(drawArc).call(styleShape);
+
// Draw foreground with transition
var valueArcPathGenerator = arcPathGenerator(trace.gauge.bar.thickness);
- var valueArc = gauge.selectAll('g.value-arc').data([trace.gauge.bar]);
- valueArc.enter().append('g').classed('value-arc', true).append('path');
+ var valueArc = gauge.selectAll('g.value-arc')
+ .data([trace.gauge.bar])
+ .enter()
+ .append('g');
+
+ valueArc.exit().remove();
+
+ valueArc.classed('value-arc', true).append('path');
var valueArcPath = valueArc.select('path');
if(hasTransition(transitionOpts)) {
valueArcPath
.transition()
.duration(transitionOpts.duration)
- .ease(transitionOpts.easing)
+ .ease(d3EaseFn)
.each('end', function() { onComplete && onComplete(); })
.each('interrupt', function() { onComplete && onComplete(); })
.attrTween('d', arcTween(valueArcPathGenerator, valueToAngle(cd[0].lastY), valueToAngle(cd[0].y)));
@@ -487,7 +538,6 @@ function drawAngularGauge(gd, plotGroup, cd, opts) {
'M0,0Z');
}
valueArcPath.call(styleShape);
- valueArc.exit().remove();
// Draw threshold
arcs = [];
@@ -503,20 +553,30 @@ function drawAngularGauge(gd, plotGroup, cd, opts) {
thickness: trace.gauge.threshold.thickness
});
}
- var thresholdArc = gauge.selectAll('g.threshold-arc').data(arcs);
- thresholdArc.enter().append('g').classed('threshold-arc', true).append('path');
- thresholdArc.select('path').call(drawArc).call(styleShape);
+ var thresholdArc = gauge.selectAll('g.threshold-arc')
+ .data(arcs)
+ .enter()
+ .append('g');
+
thresholdArc.exit().remove();
+ thresholdArc.classed('threshold-arc', true).append('path');
+ thresholdArc.select('path').call(drawArc).call(styleShape);
+
// Draw border last
- var gaugeBorder = gauge.selectAll('g.gauge-outline').data([gaugeOutline]);
- gaugeBorder.enter().append('g').classed('gauge-outline', true).append('path');
- gaugeBorder.select('path').call(drawArc).call(styleShape);
+ var gaugeBorder = gauge.selectAll('g.gauge-outline')
+ .data([gaugeOutline])
+ .enter()
+ .append('g');
+
gaugeBorder.exit().remove();
+
+ gaugeBorder.classed('gauge-outline', true).append('path');
+ gaugeBorder.select('path').call(drawArc).call(styleShape);
}
function drawNumbers(gd, plotGroup, cd, opts) {
- var trace = cd[0].trace;
+ var trace = getTraceFromCd(cd);
var numbersX = opts.numbersX;
var numbersY = opts.numbersY;
@@ -524,6 +584,7 @@ function drawNumbers(gd, plotGroup, cd, opts) {
var numbersAnchor = anchor[numbersAlign];
var transitionOpts = opts.transitionOpts;
+ var d3EaseFn = Lib.whichD3EaseFn(transitionOpts);
var onComplete = opts.onComplete;
var numbers = Lib.ensureSingle(plotGroup, 'g', 'numbers');
@@ -536,8 +597,13 @@ function drawNumbers(gd, plotGroup, cd, opts) {
data.push('delta');
if(trace.delta.position === 'left') data.reverse();
}
- var sel = numbers.selectAll('text').data(data);
- sel.enter().append('text');
+ var sel = numbers.selectAll('text')
+ .data(data)
+ .enter()
+ .append('text');
+
+ sel.exit().remove();
+
sel
.attr('text-anchor', function() {return numbersAnchor;})
.attr('class', function(d) { return d;})
@@ -545,7 +611,6 @@ function drawNumbers(gd, plotGroup, cd, opts) {
.attr('y', null)
.attr('dx', null)
.attr('dy', null);
- sel.exit().remove();
// Function to override the number formatting used during transitions
function transitionFormat(valueformat, fmt, from, to) {
@@ -590,7 +655,7 @@ function drawNumbers(gd, plotGroup, cd, opts) {
number
.transition()
.duration(transitionOpts.duration)
- .ease(transitionOpts.easing)
+ .ease(d3EaseFn)
.each('end', function() { writeNumber(); onComplete && onComplete(); })
.each('interrupt', function() { writeNumber(); onComplete && onComplete(); })
.attrTween('text', function() {
@@ -646,7 +711,7 @@ function drawNumbers(gd, plotGroup, cd, opts) {
delta
.transition()
.duration(transitionOpts.duration)
- .ease(transitionOpts.easing)
+ .ease(d3EaseFn)
.tween('text', function() {
var that = d3.select(this);
var to = deltaValue(cd[0]);
@@ -749,7 +814,7 @@ function drawNumbers(gd, plotGroup, cd, opts) {
};
}
- delta.attr({dx: dx, dy: dy});
+ delta.attrs({dx: dx, dy: dy});
}
// Resize numbers to fit within space and position
diff --git a/src/traces/ohlc/hover.js b/src/traces/ohlc/hover.js
index 5800303db40..ecb17ac8c18 100644
--- a/src/traces/ohlc/hover.js
+++ b/src/traces/ohlc/hover.js
@@ -2,6 +2,7 @@
var Axes = require('../../plots/cartesian/axes');
var Lib = require('../../lib');
+var getTraceFromCd = require('../../lib/trace_from_cd');
var Fx = require('../../components/fx');
var Color = require('../../components/color');
var fillText = require('../../lib').fillText;
@@ -14,7 +15,7 @@ var DIRSYMBOL = {
function hoverPoints(pointData, xval, yval, hovermode) {
var cd = pointData.cd;
- var trace = cd[0].trace;
+ var trace = getTraceFromCd(cd);
if(trace.hoverlabel.split) {
return hoverSplit(pointData, xval, yval, hovermode);
@@ -26,7 +27,7 @@ function hoverPoints(pointData, xval, yval, hovermode) {
function _getClosestPoint(pointData, xval, yval, hovermode) {
var cd = pointData.cd;
var xa = pointData.xa;
- var trace = cd[0].trace;
+ var trace = getTraceFromCd(cd);
var t = cd[0].t;
var type = trace.type;
@@ -91,7 +92,7 @@ function _getClosestPoint(pointData, xval, yval, hovermode) {
function hoverSplit(pointData, xval, yval, hovermode) {
var cd = pointData.cd;
var ya = pointData.ya;
- var trace = cd[0].trace;
+ var trace = getTraceFromCd(cd);
var t = cd[0].t;
var closeBoxData = [];
@@ -147,7 +148,7 @@ function hoverSplit(pointData, xval, yval, hovermode) {
function hoverOnPoints(pointData, xval, yval, hovermode) {
var cd = pointData.cd;
var ya = pointData.ya;
- var trace = cd[0].trace;
+ var trace = getTraceFromCd(cd);
var t = cd[0].t;
var closestPoint = _getClosestPoint(pointData, xval, yval, hovermode);
diff --git a/src/traces/ohlc/plot.js b/src/traces/ohlc/plot.js
index d2c36fdda20..d090ba0cdcd 100644
--- a/src/traces/ohlc/plot.js
+++ b/src/traces/ohlc/plot.js
@@ -1,6 +1,6 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var Lib = require('../../lib');
@@ -22,9 +22,10 @@ module.exports = function plot(gd, plotinfo, cdOHLC, ohlcLayer) {
var tickLen = t.tickLen;
- var paths = plotGroup.selectAll('path').data(Lib.identity);
-
- paths.enter().append('path');
+ var paths = plotGroup.selectAll('path')
+ .data(Lib.identity)
+ .enter()
+ .append('path');
paths.exit().remove();
diff --git a/src/traces/ohlc/style.js b/src/traces/ohlc/style.js
index 4b7273415a2..bae584b6dc6 100644
--- a/src/traces/ohlc/style.js
+++ b/src/traces/ohlc/style.js
@@ -1,6 +1,7 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
+var getTraceFromCd = require('../../lib/trace_from_cd');
var Drawing = require('../../components/drawing');
var Color = require('../../components/color');
@@ -8,11 +9,11 @@ module.exports = function style(gd, cd, sel) {
var s = sel ? sel : d3.select(gd).selectAll('g.ohlclayer').selectAll('g.trace');
s.style('opacity', function(d) {
- return d[0].trace.opacity;
+ return getTraceFromCd(d).opacity;
});
s.each(function(d) {
- var trace = d[0].trace;
+ var trace = getTraceFromCd(d);
d3.select(this).selectAll('path').each(function(di) {
if(di.empty) return;
diff --git a/src/traces/parcats/parcats.js b/src/traces/parcats/parcats.js
index 357b199080f..ed208213e2a 100644
--- a/src/traces/parcats/parcats.js
+++ b/src/traces/parcats/parcats.js
@@ -1,6 +1,6 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var interpolateNumber = require('d3-interpolate').interpolateNumber;
var Plotly = require('../../plot_api/plot_api');
var Fx = require('../../components/fx');
@@ -14,81 +14,55 @@ function performPlot(parcatsModels, graphDiv, layout, svg) {
var viewModels = parcatsModels.map(createParcatsViewModel.bind(0, graphDiv, layout));
// Get (potentially empty) parcatslayer selection with bound data to single element array
- var layerSelection = svg.selectAll('g.parcatslayer').data([null]);
+ var layerSelection = svg.selectAll('g.parcatslayer')
+ .data([null])
+ .enter()
+ .append('g');
- // Initialize single parcatslayer group if it doesn't exist
- layerSelection.enter()
- .append('g')
+ layerSelection.exit().remove();
+
+ layerSelection
.attr('class', 'parcatslayer')
.style('pointer-events', 'all');
// Bind data to children of layerSelection and get reference to traceSelection
- var traceSelection = layerSelection
- .selectAll('g.trace.parcats')
- .data(viewModels, key);
+ var traceSelection = layerSelection.selectAll('g.trace.parcats')
+ .data(viewModels, key)
+ .enter()
+ .append('g');
- // Initialize group for each trace/dimensions
- var traceEnter = traceSelection.enter()
- .append('g')
- .attr('class', 'trace parcats');
+ traceSelection.exit().remove();
- // Update properties for each trace
traceSelection
- .attr('transform', function(d) {
- return strTranslate(d.x, d.y);
- });
-
- // Initialize paths group
- traceEnter
+ .attr('class', 'trace parcats')
+ .attr('transform', function(d) { return strTranslate(d.x, d.y); })
.append('g')
.attr('class', 'paths');
// Update paths transform
- var pathsSelection = traceSelection
- .select('g.paths');
+ var pathSelection = traceSelection.select('g.paths').selectAll('path.path')
+ .data(function(d) { return d.paths; }, key)
+ .enter()
+ .append('path');
- // Get paths selection
- var pathSelection = pathsSelection
- .selectAll('path.path')
- .data(function(d) {
- return d.paths;
- }, key);
+ pathSelection.exit().remove();
- // Update existing path colors
pathSelection
- .attr('fill', function(d) {
- return d.model.color;
- });
-
- // Create paths
- var pathSelectionEnter = pathSelection
- .enter()
- .append('path')
.attr('class', 'path')
.attr('stroke-opacity', 0)
- .attr('fill', function(d) {
- return d.model.color;
- })
- .attr('fill-opacity', 0);
+ .attr('fill', function(d) { return d.model.color; })
+ .attr('fill-opacity', 0)
+ .attr('d', function(d) { return d.svgD; });
- stylePathsNoHover(pathSelectionEnter);
-
- // Set path geometry
- pathSelection
- .attr('d', function(d) {
- return d.svgD;
- });
+ stylePathsNoHover(pathSelection);
// sort paths
- if(!pathSelectionEnter.empty()) {
+ if(!pathSelection.empty()) {
// Only sort paths if there has been a change.
// Otherwise paths are already sorted or a hover operation may be in progress
pathSelection.sort(compareRawColor);
}
- // Remove any old paths
- pathSelection.exit().remove();
-
// Path hover
pathSelection
.on('mouseover', mouseoverPath)
@@ -96,129 +70,72 @@ function performPlot(parcatsModels, graphDiv, layout, svg) {
.on('click', clickPath);
// Initialize dimensions group
- traceEnter.append('g').attr('class', 'dimensions');
-
- // Update dimensions transform
- var dimensionsSelection = traceSelection
- .select('g.dimensions');
+ traceSelection.append('g').attr('class', 'dimensions');
// Get dimension selection
- var dimensionSelection = dimensionsSelection
- .selectAll('g.dimension')
- .data(function(d) {
- return d.dimensions;
- }, key);
-
- // Create dimension groups
- dimensionSelection.enter()
- .append('g')
- .attr('class', 'dimension');
-
- // Update dimension group transforms
- dimensionSelection.attr('transform', function(d) {
- return strTranslate(d.x, 0);
- });
+ var dimensionSelection = traceSelection.select('g.dimensions').selectAll('g.dimension')
+ .data(function(d) { return d.dimensions; }, key)
+ .enter()
+ .append('g');
- // Remove any old dimensions
dimensionSelection.exit().remove();
- // Get category selection
- var categorySelection = dimensionSelection
- .selectAll('g.category')
- .data(function(d) {
- return d.categories;
- }, key);
+ dimensionSelection
+ .attr('class', 'dimension')
+ .attr('transform', function(d) { return strTranslate(d.x, 0); });
- // Initialize category groups
- var categoryGroupEnterSelection = categorySelection
+ // Get category selection
+ var categorySelection = dimensionSelection.selectAll('g.category')
+ .data(function(d) { return d.categories; }, key)
.enter()
- .append('g')
- .attr('class', 'category');
+ .append('g');
- // Update category transforms
categorySelection
- .attr('transform', function(d) {
- return strTranslate(0, d.y);
- });
-
-
- // Initialize rectangle
- categoryGroupEnterSelection
+ .attr('class', 'category')
+ .attr('transform', function(d) { return strTranslate(0, d.y); })
.append('rect')
.attr('class', 'catrect')
- .attr('pointer-events', 'none');
-
-
- // Update rectangle
- categorySelection.select('rect.catrect')
+ .attr('pointer-events', 'none')
+ .select('rect.catrect')
.attr('fill', 'none')
- .attr('width', function(d) {
- return d.width;
- })
- .attr('height', function(d) {
- return d.height;
- });
+ .attr('width', function(d) { return d.width; })
+ .attr('height', function(d) { return d.height; });
- styleCategoriesNoHover(categoryGroupEnterSelection);
+ styleCategoriesNoHover(categorySelection);
// Initialize color band rects
- var bandSelection = categorySelection
- .selectAll('rect.bandrect')
- .data(
- /** @param {CategoryViewModel} catViewModel*/
- function(catViewModel) {
- return catViewModel.bands;
- }, key);
+ var bandSelection = categorySelection.selectAll('rect.bandrect')
+ .data(function(catViewModel) { return catViewModel.bands; }, key)
+ // Raise all update bands to the top so that fading enter/exit bands will be behind
+ .each(function() {Lib.raiseToTop(this);})
+ .enter()
+ .append('rect');
- // Raise all update bands to the top so that fading enter/exit bands will be behind
- bandSelection.each(function() {Lib.raiseToTop(this);});
+ bandSelection.exit().remove();
- // Update band color
bandSelection
- .attr('fill', function(d) {
- return d.color;
- });
-
- var bandsSelectionEnter = bandSelection.enter()
- .append('rect')
.attr('class', 'bandrect')
.attr('stroke-opacity', 0)
- .attr('fill', function(d) {
- return d.color;
- })
- .attr('fill-opacity', 0);
-
- bandSelection
- .attr('fill', function(d) {
- return d.color;
- })
- .attr('width', function(d) {
- return d.width;
- })
- .attr('height', function(d) {
- return d.height;
- })
- .attr('y', function(d) {
- return d.y;
- })
- .attr('cursor',
- /** @param {CategoryBandViewModel} bandModel*/
- function(bandModel) {
- if(bandModel.parcatsViewModel.arrangement === 'fixed') {
- return 'default';
- } else if(bandModel.parcatsViewModel.arrangement === 'perpendicular') {
- return 'ns-resize';
- } else {
- return 'move';
- }
- });
-
- styleBandsNoHover(bandsSelectionEnter);
+ .attr('fill', function(d) { return d.color; })
+ .attr('fill-opacity', 0)
+ .attr('fill', function(d) { return d.color; })
+ .attr('width', function(d) { return d.width; })
+ .attr('height', function(d) { return d.height; })
+ .attr('y', function(d) { return d.y; })
+ .attr('cursor', function(bandModel) {
+ if(bandModel.parcatsViewModel.arrangement === 'fixed') {
+ return 'default';
+ } else if(bandModel.parcatsViewModel.arrangement === 'perpendicular') {
+ return 'ns-resize';
+ } else {
+ return 'move';
+ }
+ });
- bandSelection.exit().remove();
+ styleBandsNoHover(bandSelection);
// Initialize category label
- categoryGroupEnterSelection
+ categorySelection
.append('text')
.attr('class', 'catlabel')
.attr('pointer-events', 'none');
@@ -227,45 +144,37 @@ function performPlot(parcatsModels, graphDiv, layout, svg) {
// Update category label
categorySelection.select('text.catlabel')
- .attr('text-anchor',
- function(d) {
- if(catInRightDim(d)) {
- // Place label to the right of category
- return 'start';
- } else {
- // Place label to the left of category
- return 'end';
- }
- })
+ .attr('text-anchor', function(d) {
+ if(catInRightDim(d)) {
+ // Place label to the right of category
+ return 'start';
+ } else {
+ // Place label to the left of category
+ return 'end';
+ }
+ })
.attr('alignment-baseline', 'middle')
.style('text-shadow', svgTextUtils.makeTextShadow(paperColor))
.style('fill', 'rgb(0, 0, 0)')
- .attr('x',
- function(d) {
- if(catInRightDim(d)) {
- // Place label to the right of category
- return d.width + 5;
- } else {
- // Place label to the left of category
- return -5;
- }
- })
- .attr('y', function(d) {
- return d.height / 2;
- })
- .text(function(d) {
- return d.model.categoryLabel;
+ .attr('x', function(d) {
+ if(catInRightDim(d)) {
+ // Place label to the right of category
+ return d.width + 5;
+ } else {
+ // Place label to the left of category
+ return -5;
+ }
})
- .each(
- /** @param {CategoryViewModel} catModel*/
- function(catModel) {
- Drawing.font(d3.select(this), catModel.parcatsViewModel.categorylabelfont);
- svgTextUtils.convertToTspans(d3.select(this), graphDiv);
- });
+ .attr('y', function(d) { return d.height / 2; })
+ .text(function(d) { return d.model.categoryLabel; })
+ .each(function(catModel) {
+ Drawing.font(d3.select(this), catModel.parcatsViewModel.categorylabelfont);
+ svgTextUtils.convertToTspans(d3.select(this), graphDiv);
+ });
// Initialize dimension label
- categoryGroupEnterSelection
+ categorySelection
.append('text')
.attr('class', 'dimlabel');
@@ -273,18 +182,14 @@ function performPlot(parcatsModels, graphDiv, layout, svg) {
categorySelection.select('text.dimlabel')
.attr('text-anchor', 'middle')
.attr('alignment-baseline', 'baseline')
- .attr('cursor',
- /** @param {CategoryViewModel} catModel*/
- function(catModel) {
- if(catModel.parcatsViewModel.arrangement === 'fixed') {
- return 'default';
- } else {
- return 'ew-resize';
- }
- })
- .attr('x', function(d) {
- return d.width / 2;
+ .attr('cursor', function(catModel) {
+ if(catModel.parcatsViewModel.arrangement === 'fixed') {
+ return 'default';
+ } else {
+ return 'ew-resize';
+ }
})
+ .attr('x', function(d) { return d.width / 2; })
.attr('y', -5)
.text(function(d, i) {
if(i === 0) {
@@ -294,11 +199,9 @@ function performPlot(parcatsModels, graphDiv, layout, svg) {
return null;
}
})
- .each(
- /** @param {CategoryViewModel} catModel*/
- function(catModel) {
- Drawing.font(d3.select(this), catModel.parcatsViewModel.labelfont);
- });
+ .each(function(catModel) {
+ Drawing.font(d3.select(this), catModel.parcatsViewModel.labelfont);
+ });
// Category hover
// categorySelection.select('rect.catrect')
@@ -310,13 +213,13 @@ function performPlot(parcatsModels, graphDiv, layout, svg) {
categorySelection.exit().remove();
// Setup drag
- dimensionSelection.call(d3.behavior.drag()
- .origin(function(d) {
+ dimensionSelection.call(d3.drag()
+ .subject(function(d) {
return {x: d.x, y: 0};
})
- .on('dragstart', dragDimensionStart)
+ .on('start', dragDimensionStart)
.on('drag', dragDimension)
- .on('dragend', dragDimensionEnd));
+ .on('end', dragDimensionEnd));
// Save off selections to view models
@@ -622,12 +525,10 @@ function selectPathsThroughCategoryBandColor(catBandViewModel) {
var catInd = catBandViewModel.categoryViewModel.model.categoryInd;
return allPaths
- .filter(
- /** @param {PathViewModel} pathViewModel */
- function(pathViewModel) {
- return pathViewModel.model.categoryInds[dimInd] === catInd &&
- pathViewModel.model.color === catBandViewModel.color;
- });
+ .filter(function(pathViewModel) {
+ return pathViewModel.model.categoryInds[dimInd] === catInd &&
+ pathViewModel.model.color === catBandViewModel.color;
+ });
}
@@ -906,13 +807,11 @@ function createHoverLabelForColorHovermode(gd, rootBBox, bandElement) {
var catCount = catViewModel.model.count;
var colorCount = 0;
- parcatsViewModel.pathSelection.each(
- /** @param {PathViewModel} pathViewModel */
- function(pathViewModel) {
- if(pathViewModel.model.color === bandViewModel.color) {
- colorCount += pathViewModel.model.count;
- }
- });
+ parcatsViewModel.pathSelection.each(function(pathViewModel) {
+ if(pathViewModel.model.color === bandViewModel.color) {
+ colorCount += pathViewModel.model.count;
+ }
+ });
var pColorAndCat = bandColorCount / totalCount;
var pCatGivenColor = bandColorCount / colorCount;
@@ -1083,38 +982,36 @@ function dragDimensionStart(d) {
d3.select(this)
.selectAll('g.category')
.select('rect.catrect')
- .each(
- /** @param {CategoryViewModel} catViewModel */
- function(catViewModel) {
- var catMouseX = d3.mouse(this)[0];
- var catMouseY = d3.mouse(this)[1];
-
-
- if(-2 <= catMouseX && catMouseX <= catViewModel.width + 2 &&
- -2 <= catMouseY && catMouseY <= catViewModel.height + 2) {
- // Save off initial drag indexes for categories
- d.dragCategoryDisplayInd = catViewModel.model.displayInd;
- d.initialDragCategoryDisplayInds = d.model.categories.map(function(c) {
- return c.displayInd;
- });
+ .each(function(catViewModel) {
+ var catMouseX = d3.mouse(this)[0];
+ var catMouseY = d3.mouse(this)[1];
- // Initialize categories dragY to be the current y position
- catViewModel.model.dragY = catViewModel.y;
-
- // Raise category
- Lib.raiseToTop(this.parentNode);
-
- // Get band element
- d3.select(this.parentNode)
- .selectAll('rect.bandrect')
- /** @param {CategoryBandViewModel} bandViewModel */
- .each(function(bandViewModel) {
- if(bandViewModel.y < catMouseY && catMouseY <= bandViewModel.y + bandViewModel.height) {
- d.potentialClickBand = this;
- }
- });
- }
- });
+
+ if(-2 <= catMouseX && catMouseX <= catViewModel.width + 2 &&
+ -2 <= catMouseY && catMouseY <= catViewModel.height + 2) {
+ // Save off initial drag indexes for categories
+ d.dragCategoryDisplayInd = catViewModel.model.displayInd;
+ d.initialDragCategoryDisplayInds = d.model.categories.map(function(c) {
+ return c.displayInd;
+ });
+
+ // Initialize categories dragY to be the current y position
+ catViewModel.model.dragY = catViewModel.y;
+
+ // Raise category
+ Lib.raiseToTop(this.parentNode);
+
+ // Get band element
+ d3.select(this.parentNode)
+ .selectAll('rect.bandrect')
+ /** @param {CategoryBandViewModel} bandViewModel */
+ .each(function(bandViewModel) {
+ if(bandViewModel.y < catMouseY && catMouseY <= bandViewModel.y + bandViewModel.height) {
+ d.potentialClickBand = this;
+ }
+ });
+ }
+ });
// Update toplevel drag dimension
d.parcatsViewModel.dragDimension = d;
@@ -1427,26 +1324,24 @@ function updateSvgCategories(parcatsViewModel, hasTransition) {
// the right, all others on the left
var catLabelSelection = categorySelection.select('.catlabel');
catLabelSelection
- .attr('text-anchor',
- function(d) {
- if(catInRightDim(d)) {
- // Place label to the right of category
- return 'start';
- } else {
- // Place label to the left of category
- return 'end';
- }
- })
- .attr('x',
- function(d) {
- if(catInRightDim(d)) {
- // Place label to the right of category
- return d.width + 5;
- } else {
- // Place label to the left of category
- return -5;
- }
- })
+ .attr('text-anchor', function(d) {
+ if(catInRightDim(d)) {
+ // Place label to the right of category
+ return 'start';
+ } else {
+ // Place label to the left of category
+ return 'end';
+ }
+ })
+ .attr('x', function(d) {
+ if(catInRightDim(d)) {
+ // Place label to the right of category
+ return d.width + 5;
+ } else {
+ // Place label to the left of category
+ return -5;
+ }
+ })
.each(function(d) {
// Update attriubutes of elements
var newX;
@@ -1470,37 +1365,24 @@ function updateSvgCategories(parcatsViewModel, hasTransition) {
// Initialize color band rects
var bandSelection = categorySelection
.selectAll('rect.bandrect')
- .data(
- /** @param {CategoryViewModel} catViewModel*/
- function(catViewModel) {
- return catViewModel.bands;
- }, key);
+ .data(function(catViewModel) { return catViewModel.bands; }, key)
+ .enter()
+ .append('rect');
- var bandsSelectionEnter = bandSelection.enter()
- .append('rect')
+ bandSelection
.attr('class', 'bandrect')
.attr('cursor', 'move')
.attr('stroke-opacity', 0)
- .attr('fill', function(d) {
- return d.color;
- })
+ .attr('fill', function(d) { return d.color; })
.attr('fill-opacity', 0);
bandSelection
- .attr('fill', function(d) {
- return d.color;
- })
- .attr('width', function(d) {
- return d.width;
- })
- .attr('height', function(d) {
- return d.height;
- })
- .attr('y', function(d) {
- return d.y;
- });
+ .attr('fill', function(d) { return d.color; })
+ .attr('width', function(d) { return d.width; })
+ .attr('height', function(d) { return d.height; })
+ .attr('y', function(d) { return d.y; });
- styleBandsNoHover(bandsSelectionEnter);
+ styleBandsNoHover(bandSelection);
// Raise bands to the top
bandSelection.each(function() {Lib.raiseToTop(this);});
diff --git a/src/traces/parcoords/axisbrush.js b/src/traces/parcoords/axisbrush.js
index 975c60c0396..8cb1666976e 100644
--- a/src/traces/parcoords/axisbrush.js
+++ b/src/traces/parcoords/axisbrush.js
@@ -1,7 +1,7 @@
'use strict';
var c = require('./constants');
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var keyFun = require('../../lib/gup').keyFun;
var repeat = require('../../lib/gup').repeat;
var sortAsc = require('../../lib').sorterAsc;
@@ -199,7 +199,7 @@ function getInterval(d, y) {
return out;
}
-function dragstart(lThis, d) {
+function start(lThis, d) {
d3.event.sourceEvent.stopPropagation();
var y = d.height - d3.mouse(lThis)[1] - 2 * c.verticalPadding;
var unitLocation = d.unitToPaddedPx.invert(y);
@@ -245,7 +245,7 @@ function drag(lThis, d) {
renderHighlight(lThis.parentNode);
}
-function dragend(lThis, d) {
+function end(lThis, d) {
var brush = d.brush;
var filter = brush.filter;
var s = brush.svgBrush;
@@ -345,20 +345,24 @@ function attachDragBehavior(selection) {
.on('mouseleave', function(d) {
if(!d.parent.inBrushDrag) clearCursor();
})
- .call(d3.behavior.drag()
- .on('dragstart', function(d) { dragstart(this, d); })
+ .call(d3.drag()
+ .on('start', function(d) { start(this, d); })
.on('drag', function(d) { drag(this, d); })
- .on('dragend', function(d) { dragend(this, d); })
+ .on('end', function(d) { end(this, d); })
);
}
function startAsc(a, b) { return a[0] - b[0]; }
function renderAxisBrush(axisBrush, paperColor) {
- var background = axisBrush.selectAll('.background').data(repeat);
+ var background = axisBrush.selectAll('.background')
+ .data(repeat)
+ .enter()
+ .append('rect');
- background.enter()
- .append('rect')
+ background.exit().remove();
+
+ background
.classed('background', true)
.call(barHorizontalSetup)
.call(backgroundBarHorizontalSetup)
@@ -371,10 +375,14 @@ function renderAxisBrush(axisBrush, paperColor) {
return d.height - c.verticalPadding;
});
- var highlightShadow = axisBrush.selectAll('.highlight-shadow').data(repeat); // we have a set here, can't call it `extent`
+ var highlightShadow = axisBrush.selectAll('.highlight-shadow')
+ .data(repeat) // we have a set here, can't call it `extent`
+ .enter()
+ .append('line');
- highlightShadow.enter()
- .append('line')
+ highlightShadow.exit().remove();
+
+ highlightShadow
.classed('highlight-shadow', true)
.attr('x', -c.bar.width / 2)
.attr('stroke-width', c.bar.width + c.bar.strokeWidth)
@@ -386,10 +394,14 @@ function renderAxisBrush(axisBrush, paperColor) {
.attr('y1', function(d) { return d.height; })
.call(styleHighlight);
- var highlight = axisBrush.selectAll('.highlight').data(repeat); // we have a set here, can't call it `extent`
+ var highlight = axisBrush.selectAll('.highlight')
+ .data(repeat) // we have a set here, can't call it `extent`
+ .enter()
+ .append('line');
- highlight.enter()
- .append('line')
+ highlight.exit().remove();
+
+ highlight
.classed('highlight', true)
.attr('x', -c.bar.width / 2)
.attr('stroke-width', c.bar.width - c.bar.strokeWidth)
@@ -404,10 +416,13 @@ function renderAxisBrush(axisBrush, paperColor) {
function ensureAxisBrush(axisOverlays, paperColor) {
var axisBrush = axisOverlays.selectAll('.' + c.cn.axisBrush)
- .data(repeat, keyFun);
+ .data(repeat, keyFun)
+ .enter()
+ .append('g');
+
+ axisBrush.exit().remove();
- axisBrush.enter()
- .append('g')
+ axisBrush
.classed(c.cn.axisBrush, true);
renderAxisBrush(axisBrush, paperColor);
diff --git a/src/traces/parcoords/base_plot.js b/src/traces/parcoords/base_plot.js
index 7de1cdbd313..319f015f2f1 100644
--- a/src/traces/parcoords/base_plot.js
+++ b/src/traces/parcoords/base_plot.js
@@ -1,6 +1,6 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var getModuleCalcData = require('../../plots/get_data').getModuleCalcData;
var parcoordsPlot = require('./plot');
var xmlnsNamespaces = require('../../constants/xmlns_namespaces');
@@ -33,7 +33,7 @@ exports.toSVG = function(gd) {
var imageData = canvas.toDataURL('image/png');
var image = imageRoot.append('svg:image');
- image.attr({
+ image.attrs({
xmlns: xmlnsNamespaces.svg,
'xlink:href': imageData,
preserveAspectRatio: 'none',
diff --git a/src/traces/parcoords/parcoords.js b/src/traces/parcoords/parcoords.js
index 17ab829bc14..96aa672fe07 100644
--- a/src/traces/parcoords/parcoords.js
+++ b/src/traces/parcoords/parcoords.js
@@ -1,6 +1,6 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var Lib = require('../../lib');
var numberFormat = Lib.numberFormat;
var rgba = require('color-rgba');
@@ -79,7 +79,7 @@ function toText(formatter, texts) {
function domainScale(height, padding, dimension, tickvals, ticktext) {
var extent = dimensionExtent(dimension);
if(tickvals) {
- return d3.scale.ordinal()
+ return d3.scaleOrdinal()
.domain(tickvals.map(toText(numberFormat(dimension.tickformat), ticktext)))
.range(tickvals
.map(function(d) {
@@ -88,17 +88,17 @@ function domainScale(height, padding, dimension, tickvals, ticktext) {
})
);
}
- return d3.scale.linear()
+ return d3.scaleLinear()
.domain(extent)
.range([height - padding, padding]);
}
function unitToPaddedPx(height, padding) {
- return d3.scale.linear().range([padding, height - padding]);
+ return d3.scaleLinear().range([padding, height - padding]);
}
function domainToPaddedUnitScale(dimension, padFraction) {
- return d3.scale.linear()
+ return d3.scaleLinear()
.domain(dimensionExtent(dimension))
.range([padFraction, 1 - padFraction]);
}
@@ -107,7 +107,7 @@ function ordinalScale(dimension) {
if(!dimension.tickvals) return;
var extent = dimensionExtent(dimension);
- return d3.scale.ordinal()
+ return d3.scaleOrdinal()
.domain(dimension.tickvals)
.range(dimension.tickvals.map(function(d) {
return (d - extent[0]) / (extent[1] - extent[0]);
@@ -125,7 +125,7 @@ function unitToColorScale(cscale) {
// We can't use d3 color interpolation as we may have non-uniform color palette raster
// (various color stop distances).
var polylinearUnitScales = 'rgb'.split('').map(function(key) {
- return d3.scale.linear()
+ return d3.scaleLinear()
.clamp(true)
.domain(colorStops)
.range(colorTuples.map(prop(key)));
@@ -162,7 +162,7 @@ function model(layout, d, i) {
var rangeFont = trace.rangefont;
var lines = Lib.extendDeepNoArrays({}, line, {
- color: lineColor.map(d3.scale.linear().domain(
+ color: lineColor.map(d3.scaleLinear().domain(
dimensionExtent({
values: lineColor,
range: [cOpts.min, cOpts.max],
@@ -507,12 +507,13 @@ module.exports = function parcoords(gd, cdModule, layout, callbacks) {
svg.style('background', 'rgba(255, 255, 255, 0)');
var controlOverlay = svg.selectAll('.' + c.cn.parcoords)
- .data(vm, keyFun);
+ .data(vm, keyFun)
+ .enter()
+ .append('g');
controlOverlay.exit().remove();
- controlOverlay.enter()
- .append('g')
+ controlOverlay
.classed(c.cn.parcoords, true)
.style('shape-rendering', 'crispEdges')
.style('pointer-events', 'none');
@@ -522,10 +523,13 @@ module.exports = function parcoords(gd, cdModule, layout, callbacks) {
});
var parcoordsControlView = controlOverlay.selectAll('.' + c.cn.parcoordsControlView)
- .data(repeat, keyFun);
+ .data(repeat, keyFun)
+ .enter()
+ .append('g');
- parcoordsControlView.enter()
- .append('g')
+ parcoordsControlView.exit().remove();
+
+ parcoordsControlView
.classed(c.cn.parcoordsControlView, true);
parcoordsControlView.attr('transform', function(d) {
@@ -533,10 +537,13 @@ module.exports = function parcoords(gd, cdModule, layout, callbacks) {
});
var yAxis = parcoordsControlView.selectAll('.' + c.cn.yAxis)
- .data(function(p) { return p.dimensions; }, keyFun);
+ .data(function(p) { return p.dimensions; }, keyFun)
+ .enter()
+ .append('g');
+
+ yAxis.exit().remove();
- yAxis.enter()
- .append('g')
+ yAxis
.classed(c.cn.yAxis, true);
parcoordsControlView.each(function(p) {
@@ -564,8 +571,8 @@ module.exports = function parcoords(gd, cdModule, layout, callbacks) {
});
// drag column for reordering columns
- yAxis.call(d3.behavior.drag()
- .origin(function(d) { return d; })
+ yAxis.call(d3.drag()
+ .subject(function(d) { return d; })
.on('drag', function(d) {
var p = d.parent;
state.linePickActive(false);
@@ -588,7 +595,7 @@ module.exports = function parcoords(gd, cdModule, layout, callbacks) {
p.contextLayer && p.contextLayer.render(p.panels, false, !someFiltersActive(p));
p.focusLayer.render && p.focusLayer.render(p.panels);
})
- .on('dragend', function(d) {
+ .on('end', function(d) {
var p = d.parent;
d.x = d.xScale(d.xIndex);
d.canvasX = d.x * d.model.canvasPixelRatio;
@@ -606,23 +613,26 @@ module.exports = function parcoords(gd, cdModule, layout, callbacks) {
})
);
- yAxis.exit()
- .remove();
-
var axisOverlays = yAxis.selectAll('.' + c.cn.axisOverlays)
- .data(repeat, keyFun);
+ .data(repeat, keyFun)
+ .enter()
+ .append('g');
- axisOverlays.enter()
- .append('g')
+ axisOverlays.exit().remove();
+
+ axisOverlays
.classed(c.cn.axisOverlays, true);
axisOverlays.selectAll('.' + c.cn.axis).remove();
var axis = axisOverlays.selectAll('.' + c.cn.axis)
- .data(repeat, keyFun);
+ .data(repeat, keyFun)
+ .enter()
+ .append('g');
+
+ axis.exit().remove();
- axis.enter()
- .append('g')
+ axis
.classed(c.cn.axis, true);
axis
@@ -631,10 +641,9 @@ module.exports = function parcoords(gd, cdModule, layout, callbacks) {
var scale = d.domainScale;
var sdom = scale.domain();
d3.select(this)
- .call(d3.svg.axis()
- .orient('left')
+ .call(d3.axisLeft()
.tickSize(4)
- .outerTickSize(2)
+ .tickSizeOuter(2)
.ticks(wantedTickCount, d.tickFormat) // works for continuous scales only...
.tickValues(d.ordinal ? // and this works for ordinal scales
sdom :
@@ -657,17 +666,23 @@ module.exports = function parcoords(gd, cdModule, layout, callbacks) {
.style('cursor', 'default');
var axisHeading = axisOverlays.selectAll('.' + c.cn.axisHeading)
- .data(repeat, keyFun);
+ .data(repeat, keyFun)
+ .enter()
+ .append('g');
+
+ axisHeading.exit().remove();
- axisHeading.enter()
- .append('g')
+ axisHeading
.classed(c.cn.axisHeading, true);
var axisTitle = axisHeading.selectAll('.' + c.cn.axisTitle)
- .data(repeat, keyFun);
+ .data(repeat, keyFun)
+ .enter()
+ .append('text');
- axisTitle.enter()
- .append('text')
+ axisTitle.exit().remove();
+
+ axisTitle
.classed(c.cn.axisTitle, true)
.attr('text-anchor', 'middle')
.style('cursor', 'ew-resize')
@@ -702,27 +717,36 @@ module.exports = function parcoords(gd, cdModule, layout, callbacks) {
});
var axisExtent = axisOverlays.selectAll('.' + c.cn.axisExtent)
- .data(repeat, keyFun);
+ .data(repeat, keyFun)
+ .enter()
+ .append('g');
- axisExtent.enter()
- .append('g')
+ axisExtent.exit().remove();
+
+ axisExtent
.classed(c.cn.axisExtent, true);
var axisExtentTop = axisExtent.selectAll('.' + c.cn.axisExtentTop)
- .data(repeat, keyFun);
+ .data(repeat, keyFun)
+ .enter()
+ .append('g');
+
+ axisExtentTop.exit().remove();
- axisExtentTop.enter()
- .append('g')
+ axisExtentTop
.classed(c.cn.axisExtentTop, true);
axisExtentTop
.attr('transform', strTranslate(0, -c.axisExtentOffset));
var axisExtentTopText = axisExtentTop.selectAll('.' + c.cn.axisExtentTopText)
- .data(repeat, keyFun);
+ .data(repeat, keyFun)
+ .enter()
+ .append('text');
- axisExtentTopText.enter()
- .append('text')
+ axisExtentTopText.exit().remove();
+
+ axisExtentTopText
.classed(c.cn.axisExtentTopText, true)
.call(styleExtentTexts);
@@ -731,10 +755,13 @@ module.exports = function parcoords(gd, cdModule, layout, callbacks) {
.each(function(d) { Drawing.font(d3.select(this), d.model.rangeFont); });
var axisExtentBottom = axisExtent.selectAll('.' + c.cn.axisExtentBottom)
- .data(repeat, keyFun);
+ .data(repeat, keyFun)
+ .enter()
+ .append('g');
- axisExtentBottom.enter()
- .append('g')
+ axisExtentBottom.exit().remove();
+
+ axisExtentBottom
.classed(c.cn.axisExtentBottom, true);
axisExtentBottom
@@ -743,10 +770,13 @@ module.exports = function parcoords(gd, cdModule, layout, callbacks) {
});
var axisExtentBottomText = axisExtentBottom.selectAll('.' + c.cn.axisExtentBottomText)
- .data(repeat, keyFun);
+ .data(repeat, keyFun)
+ .enter()
+ .append('text');
- axisExtentBottomText.enter()
- .append('text')
+ axisExtentBottomText.exit().remove();
+
+ axisExtentBottomText
.classed(c.cn.axisExtentBottomText, true)
.attr('dy', '0.75em')
.call(styleExtentTexts);
diff --git a/src/traces/parcoords/plot.js b/src/traces/parcoords/plot.js
index 7ae5be63323..f838882480a 100644
--- a/src/traces/parcoords/plot.js
+++ b/src/traces/parcoords/plot.js
@@ -1,6 +1,7 @@
'use strict';
var parcoords = require('./parcoords');
+var getTraceFromCd = require('../../lib/trace_from_cd');
var prepareRegl = require('../../lib/prepare_regl');
var isVisible = require('./helpers').isVisible;
@@ -37,7 +38,7 @@ module.exports = function plot(gd, cdModule) {
var size = fullLayout._size;
cdModule.forEach(function(d, i) {
- var trace = d[0].trace;
+ var trace = getTraceFromCd(d);
fullIndices[i] = trace.index;
var iIn = inputIndices[i] = trace._fullInput.index;
currentDims[i] = gd.data[iIn].dimensions;
diff --git a/src/traces/pie/calc.js b/src/traces/pie/calc.js
index 6f9208b0144..8584bfe63dc 100644
--- a/src/traces/pie/calc.js
+++ b/src/traces/pie/calc.js
@@ -3,6 +3,7 @@
var isNumeric = require('fast-isnumeric');
var tinycolor = require('tinycolor2');
+var getTraceFromCd = require('../../lib/trace_from_cd');
var Color = require('../../components/color');
var extendedColorWayList = {};
@@ -122,7 +123,7 @@ function crossTraceCalc(gd, plotinfo) { // TODO: should we name the second argum
for(var i = 0; i < calcdata.length; i++) {
var cd = calcdata[i];
- var traceType = cd[0].trace.type;
+ var traceType = getTraceFromCd(cd).type;
if(traceType !== desiredType) continue;
for(var j = 0; j < cd.length; j++) {
diff --git a/src/traces/pie/plot.js b/src/traces/pie/plot.js
index 8d2cd2d39ee..e3ac51e89cd 100644
--- a/src/traces/pie/plot.js
+++ b/src/traces/pie/plot.js
@@ -1,6 +1,6 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var Plots = require('../../plots/plots');
var Fx = require('../../components/fx');
@@ -40,12 +40,16 @@ function plot(gd, cdModule) {
plotGroup.attr('stroke-linejoin', 'round');
plotGroup.each(function() {
- var slices = d3.select(this).selectAll('g.slice').data(cd);
+ var slices = d3.select(this).selectAll('g.slice')
+ .data(cd)
+ .enter()
+ .append('g');
- slices.enter().append('g')
- .classed('slice', true);
slices.exit().remove();
+ slices
+ .classed('slice', true);
+
var quadrants = [
[[], []], // y<0: x<0, x>=0
[[], []] // y>=0: x<0, x>=0
@@ -67,11 +71,16 @@ function plot(gd, cdModule) {
var cx = cd0.cx;
var cy = cd0.cy;
var sliceTop = d3.select(this);
- var slicePath = sliceTop.selectAll('path.surface').data([pt]);
+ var slicePath = sliceTop.selectAll('path.surface')
+ .data([pt])
+ .enter()
+ .append('path');
+
+ slicePath.exit().remove();
- slicePath.enter().append('path')
+ slicePath
.classed('surface', true)
- .style({'pointer-events': 'all'});
+ .styles({'pointer-events': 'all'});
sliceTop.call(attachFxHandlers, gd, cd);
@@ -131,12 +140,15 @@ function plot(gd, cdModule) {
formatSliceLabel(gd, pt, cd0);
var textPosition = helpers.castOption(trace.textposition, pt.pts);
var sliceTextGroup = sliceTop.selectAll('g.slicetext')
- .data(pt.text && (textPosition !== 'none') ? [0] : []);
+ .data(pt.text && (textPosition !== 'none') ? [0] : [])
+ .enter()
+ .append('g');
- sliceTextGroup.enter().append('g')
- .classed('slicetext', true);
sliceTextGroup.exit().remove();
+ sliceTextGroup
+ .classed('slicetext', true);
+
sliceTextGroup.each(function() {
var sliceText = Lib.ensureSingle(d3.select(this), 'text', '', function(s) {
// prohibit tex interpretation until we can handle
@@ -150,7 +162,7 @@ function plot(gd, cdModule) {
);
sliceText.text(pt.text)
- .attr({
+ .attrs({
'class': 'slicetext',
transform: '',
'text-anchor': 'middle'
@@ -203,12 +215,14 @@ function plot(gd, cdModule) {
// add the title
var titleTextGroup = d3.select(this).selectAll('g.titletext')
- .data(trace.title.text ? [0] : []);
+ .data(trace.title.text ? [0] : [])
+ .enter()
+ .append('g');
- titleTextGroup.enter().append('g')
- .classed('titletext', true);
titleTextGroup.exit().remove();
+ titleTextGroup.classed('titletext', true);
+
titleTextGroup.each(function() {
var titleText = Lib.ensureSingle(d3.select(this), 'text', '', function(s) {
// prohibit tex interpretation as above
@@ -221,7 +235,7 @@ function plot(gd, cdModule) {
}
titleText.text(txt)
- .attr({
+ .attrs({
'class': 'titletext',
transform: '',
'text-anchor': 'middle',
@@ -334,7 +348,7 @@ function plotTextLines(slices, trace) {
Lib.ensureSingle(sliceTop, 'path', 'textline')
.call(Color.stroke, trace.outsidetextfont.color)
- .attr({
+ .attrs({
'stroke-width': Math.min(2, trace.outsidetextfont.size / 8),
d: textLinePath,
fill: 'none'
diff --git a/src/traces/pie/style.js b/src/traces/pie/style.js
index 9a1929a5311..4117fa98f2e 100644
--- a/src/traces/pie/style.js
+++ b/src/traces/pie/style.js
@@ -1,6 +1,6 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var styleOne = require('./style_one');
var resizeText = require('../bar/uniform_text').resizeText;
@@ -14,7 +14,7 @@ module.exports = function style(gd) {
var trace = cd0.trace;
var traceSelection = d3.select(this);
- traceSelection.style({opacity: trace.opacity});
+ traceSelection.styles({opacity: trace.opacity});
traceSelection.selectAll('path.surface').each(function(pt) {
d3.select(this).call(styleOne, pt, trace);
diff --git a/src/traces/sankey/constants.js b/src/traces/sankey/constants.js
index c7eda8ca65b..cb21edd2a07 100644
--- a/src/traces/sankey/constants.js
+++ b/src/traces/sankey/constants.js
@@ -8,7 +8,7 @@ module.exports = {
forceIterations: 5,
forceTicksPerFrame: 10,
duration: 500,
- ease: 'linear',
+ easing: 'linear',
cn: {
sankey: 'sankey',
sankeyLinks: 'sankey-links',
diff --git a/src/traces/sankey/plot.js b/src/traces/sankey/plot.js
index 715a47ff36c..12cc71e9fc2 100644
--- a/src/traces/sankey/plot.js
+++ b/src/traces/sankey/plot.js
@@ -1,6 +1,6 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var Lib = require('../../lib');
var numberFormat = Lib.numberFormat;
var render = require('./render');
diff --git a/src/traces/sankey/render.js b/src/traces/sankey/render.js
index ced03a514f5..01041b58d83 100644
--- a/src/traces/sankey/render.js
+++ b/src/traces/sankey/render.js
@@ -2,17 +2,18 @@
var d3Force = require('d3-force');
var interpolateNumber = require('d3-interpolate').interpolateNumber;
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var d3Sankey = require('@plotly/d3-sankey');
var d3SankeyCircular = require('@plotly/d3-sankey-circular');
-var c = require('./constants');
var tinycolor = require('tinycolor2');
+var c = require('./constants');
var Color = require('../../components/color');
var Drawing = require('../../components/drawing');
var Lib = require('../../lib');
var strTranslate = Lib.strTranslate;
var strRotate = Lib.strRotate;
+var d3EaseFn = Lib.whichD3EaseFn(c);
var gup = require('../../lib/gup');
var keyFun = gup.keyFun;
var repeat = gup.repeat;
@@ -589,15 +590,15 @@ function attachPointerEvents(selection, sankey, eventSet) {
}
function attachDragHandler(sankeyNode, sankeyLink, callbacks, gd) {
- var dragBehavior = d3.behavior.drag()
- .origin(function(d) {
+ var dragBehavior = d3.drag()
+ .subject(function(d) {
return {
x: d.node.x0 + d.visibleWidth / 2,
y: d.node.y0 + d.visibleHeight / 2
};
})
- .on('dragstart', function(d) {
+ .on('start', function(d) {
if(d.arrangement === 'fixed') return;
Lib.ensureSingle(gd._fullLayout._infolayer, 'g', 'dragcover', function(s) {
gd._fullLayout._dragCover = s;
@@ -647,7 +648,7 @@ function attachDragHandler(sankeyNode, sankeyLink, callbacks, gd) {
}
})
- .on('dragend', function(d) {
+ .on('end', function(d) {
if(d.arrangement === 'fixed') return;
d.interactionState.dragInProgress = false;
for(var i = 0; i < d.node.childrenNodes.length; i++) {
@@ -807,13 +808,13 @@ module.exports = function(gd, svg, calcData, layout, callbacks) {
.map(sankeyModel.bind(null, layout));
var sankey = svg.selectAll('.' + c.cn.sankey)
- .data(styledData, keyFun);
+ .data(styledData, keyFun)
+ .enter()
+ .append('g');
- sankey.exit()
- .remove();
+ sankey.exit().remove();
- sankey.enter()
- .append('g')
+ sankey
.classed(c.cn.sankey, true)
.style('box-sizing', 'content-box')
.style('position', 'absolute')
@@ -838,33 +839,43 @@ module.exports = function(gd, svg, calcData, layout, callbacks) {
.attr('x', d.translateX)
.attr('y', d.translateY)
.classed('bgsankey', true)
- .style({fill: 'transparent', 'stroke-width': 0});
+ .styles({fill: 'transparent', 'stroke-width': 0});
});
sankey.transition()
- .ease(c.ease).duration(c.duration)
+ .ease(d3EaseFn).duration(c.duration)
.attr('transform', sankeyTransform);
var sankeyLinks = sankey.selectAll('.' + c.cn.sankeyLinks)
- .data(repeat, keyFun);
+ .data(repeat, keyFun)
+ .enter()
+ .append('g');
- sankeyLinks.enter()
- .append('g')
+ sankeyLinks.exit().remove();
+
+ sankeyLinks
.classed(c.cn.sankeyLinks, true)
.style('fill', 'none');
var sankeyLink = sankeyLinks.selectAll('.' + c.cn.sankeyLink)
- .data(function(d) {
- var links = d.graph.links;
- return links
- .filter(function(l) {return l.value;})
- .map(linkModel.bind(null, d));
- }, keyFun);
+ .data(function(d) {
+ var links = d.graph.links;
+ return links
+ .filter(function(l) {return l.value;})
+ .map(linkModel.bind(null, d));
+ }, keyFun)
+ .enter()
+ .append('path');
+
+ sankeyLink.exit()
+ .transition()
+ .ease(d3EaseFn).duration(c.duration)
+ .style('opacity', 0)
+ .remove();
sankeyLink
- .enter().append('path')
- .classed(c.cn.sankeyLink, true)
- .call(attachPointerEvents, sankey, callbacks.linkEvents);
+ .classed(c.cn.sankeyLink, true)
+ .call(attachPointerEvents, sankey, callbacks.linkEvents);
sankeyLink
.style('stroke', function(d) {
@@ -887,20 +898,15 @@ module.exports = function(gd, svg, calcData, layout, callbacks) {
sankeyLink
.style('opacity', function() { return (gd._context.staticPlot || firstRender || dragcover) ? 1 : 0;})
.transition()
- .ease(c.ease).duration(c.duration)
+ .ease(d3EaseFn).duration(c.duration)
.style('opacity', 1);
- sankeyLink.exit()
- .transition()
- .ease(c.ease).duration(c.duration)
- .style('opacity', 0)
- .remove();
-
var sankeyNodeSet = sankey.selectAll('.' + c.cn.sankeyNodeSet)
- .data(repeat, keyFun);
+ .data(repeat, keyFun)
+ .enter()
+ .append('g');
- sankeyNodeSet.enter()
- .append('g')
+ sankeyNodeSet
.classed(c.cn.sankeyNodeSet, true);
sankeyNodeSet
@@ -918,10 +924,17 @@ module.exports = function(gd, svg, calcData, layout, callbacks) {
persistOriginalPlace(nodes);
return nodes
.map(nodeModel.bind(null, d));
- }, keyFun);
+ }, keyFun)
+ .enter()
+ .append('g');
+
+ sankeyNode.exit()
+ .transition()
+ .ease(d3EaseFn).duration(c.duration)
+ .style('opacity', 0)
+ .remove();
- sankeyNode.enter()
- .append('g')
+ sankeyNode
.classed(c.cn.sankeyNode, true)
.call(updateNodePositions)
.style('opacity', function(n) { return ((gd._context.staticPlot || firstRender) && !n.partOfGroup) ? 1 : 0;});
@@ -932,21 +945,16 @@ module.exports = function(gd, svg, calcData, layout, callbacks) {
sankeyNode
.transition()
- .ease(c.ease).duration(c.duration)
+ .ease(d3EaseFn).duration(c.duration)
.call(updateNodePositions)
.style('opacity', function(n) { return n.partOfGroup ? 0 : 1;});
- sankeyNode.exit()
- .transition()
- .ease(c.ease).duration(c.duration)
- .style('opacity', 0)
- .remove();
-
var nodeRect = sankeyNode.selectAll('.' + c.cn.nodeRect)
- .data(repeat);
+ .data(repeat)
+ .enter()
+ .append('rect');
- nodeRect.enter()
- .append('rect')
+ nodeRect
.classed(c.cn.nodeRect, true)
.call(sizeNode);
@@ -958,14 +966,15 @@ module.exports = function(gd, svg, calcData, layout, callbacks) {
.style('fill-opacity', function(d) {return d.tinyColorAlpha;});
nodeRect.transition()
- .ease(c.ease).duration(c.duration)
+ .ease(d3EaseFn).duration(c.duration)
.call(sizeNode);
var nodeLabel = sankeyNode.selectAll('.' + c.cn.nodeLabel)
- .data(repeat);
+ .data(repeat)
+ .enter()
+ .append('text');
- nodeLabel.enter()
- .append('text')
+ nodeLabel
.classed(c.cn.nodeLabel, true)
.style('cursor', 'default');
@@ -1011,5 +1020,5 @@ module.exports = function(gd, svg, calcData, layout, callbacks) {
nodeLabel
.transition()
- .ease(c.ease).duration(c.duration);
+ .ease(d3EaseFn).duration(c.duration);
};
diff --git a/src/traces/sankey/select.js b/src/traces/sankey/select.js
index c2af9dc6227..f052798008e 100644
--- a/src/traces/sankey/select.js
+++ b/src/traces/sankey/select.js
@@ -1,9 +1,11 @@
'use strict';
+var getTraceFromCd = require('../../lib/trace_from_cd');
+
module.exports = function selectPoints(searchInfo, selectionTester) {
var cd = searchInfo.cd;
var selection = [];
- var fullData = cd[0].trace;
+ var fullData = getTraceFromCd(cd);
var nodes = fullData._sankey.graph.nodes;
diff --git a/src/traces/scatter/cross_trace_calc.js b/src/traces/scatter/cross_trace_calc.js
index 69006d8d45a..e6c80fea718 100644
--- a/src/traces/scatter/cross_trace_calc.js
+++ b/src/traces/scatter/cross_trace_calc.js
@@ -1,5 +1,6 @@
'use strict';
+var getTraceFromCd = require('../../lib/trace_from_cd');
var calc = require('./calc');
/*
@@ -103,7 +104,7 @@ module.exports = function crossTraceCalc(gd, plotinfo) {
// autorange
for(i = 0; i < indices.length; i++) {
cd = calcTraces[indices[i]];
- var trace = cd[0].trace;
+ var trace = getTraceFromCd(cd);
var ppad = calc.calcMarkerSize(trace, trace._rawLength);
var arrayPad = Array.isArray(ppad);
if((ppad && hasAnyBlanks[i]) || arrayPad) {
diff --git a/src/traces/scatter/hover.js b/src/traces/scatter/hover.js
index c86a5b902f8..35d2962bd65 100644
--- a/src/traces/scatter/hover.js
+++ b/src/traces/scatter/hover.js
@@ -1,6 +1,7 @@
'use strict';
var Lib = require('../../lib');
+var getTraceFromCd = require('../../lib/trace_from_cd');
var Fx = require('../../components/fx');
var Registry = require('../../registry');
var getTraceColor = require('./get_trace_color');
@@ -9,7 +10,7 @@ var fillText = Lib.fillText;
module.exports = function hoverPoints(pointData, xval, yval, hovermode) {
var cd = pointData.cd;
- var trace = cd[0].trace;
+ var trace = getTraceFromCd(cd);
var xa = pointData.xa;
var ya = pointData.ya;
var xpx = xa.c2p(xval);
diff --git a/src/traces/scatter/link_traces.js b/src/traces/scatter/link_traces.js
index 31c5cc69eb1..fa5ab705c35 100644
--- a/src/traces/scatter/link_traces.js
+++ b/src/traces/scatter/link_traces.js
@@ -1,5 +1,7 @@
'use strict';
+var getTraceFromCd = require('../../lib/trace_from_cd');
+
var LINKEDFILLS = {tonextx: 1, tonexty: 1, tonext: 1};
module.exports = function linkTraces(gd, plotinfo, cdscatter) {
@@ -35,8 +37,8 @@ module.exports = function linkTraces(gd, plotinfo, cdscatter) {
var cdscatterSorted = cdscatter.slice();
if(needsSort) {
cdscatterSorted.sort(function(a, b) {
- var traceA = a[0].trace;
- var traceB = b[0].trace;
+ var traceA = getTraceFromCd(a);
+ var traceB = getTraceFromCd(b);
return (traceA._groupIndex - traceB._groupIndex) ||
(traceA.index - traceB.index);
});
diff --git a/src/traces/scatter/plot.js b/src/traces/scatter/plot.js
index 88671f53481..14bda0f52aa 100644
--- a/src/traces/scatter/plot.js
+++ b/src/traces/scatter/plot.js
@@ -1,9 +1,10 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var Registry = require('../../registry');
var Lib = require('../../lib');
+var getTraceFromCd = require('../../lib/trace_from_cd');
var ensureSingle = Lib.ensureSingle;
var identity = Lib.identity;
var Drawing = require('../../components/drawing');
@@ -14,6 +15,7 @@ var linkTraces = require('./link_traces');
var polygonTester = require('../../lib/polygon').tester;
module.exports = function plot(gd, plotinfo, cdscatter, scatterLayer, transitionOpts, makeOnCompleteCallback) {
+ var d3EaseFn = Lib.whichD3EaseFn(transitionOpts);
var join, onComplete;
// If transition config is provided, then it is only a partial replot and traces not
@@ -25,14 +27,16 @@ module.exports = function plot(gd, plotinfo, cdscatter, scatterLayer, transition
var cdscatterSorted = linkTraces(gd, plotinfo, cdscatter);
join = scatterLayer.selectAll('g.trace')
- .data(cdscatterSorted, function(d) { return d[0].trace.uid; });
+ .data(cdscatterSorted, function(d) { return getTraceFromCd(d).uid; })
+ .enter()
+ .append('g');
- // Append new traces:
- join.enter().append('g')
+ join
.attr('class', function(d) {
- return 'trace scatter trace' + d[0].trace.uid;
+ return 'trace scatter trace' + getTraceFromCd(d).uid;
})
.style('stroke-miterlimit', 2);
+
join.order();
createFills(gd, join, plotinfo);
@@ -47,7 +51,7 @@ module.exports = function plot(gd, plotinfo, cdscatter, scatterLayer, transition
var transition = d3.transition()
.duration(transitionOpts.duration)
- .ease(transitionOpts.easing)
+ .ease(d3EaseFn)
.each('end', function() {
onComplete && onComplete();
})
@@ -81,19 +85,16 @@ function createFills(gd, traceJoin, plotinfo) {
var fills = ensureSingle(d3.select(this), 'g', 'fills');
Drawing.setClipUrl(fills, plotinfo.layerClipId, gd);
- var trace = d[0].trace;
+ var trace = getTraceFromCd(d);
var fillData = [];
if(trace._ownfill) fillData.push('_ownFill');
if(trace._nexttrace) fillData.push('_nextFill');
- var fillJoin = fills.selectAll('g').data(fillData, identity);
-
- fillJoin.enter().append('g');
-
- fillJoin.exit()
- .each(function(d) { trace[d] = null; })
- .remove();
+ var fillJoin = fills.selectAll('g')
+ .data(fillData, identity)
+ .enter()
+ .append('g');
fillJoin.order().each(function(d) {
// make a path element inside the fill group, just so
@@ -101,6 +102,10 @@ function createFills(gd, traceJoin, plotinfo) {
// keep its simple '_*Fill' data
trace[d] = ensureSingle(d3.select(this), 'path', 'js-fill');
});
+
+ fillJoin.exit()
+ .each(function(d) { trace[d] = null; })
+ .remove();
});
}
@@ -121,7 +126,7 @@ function plotOne(gd, idx, plotinfo, cdscatter, cdscatterAll, element, transition
var xa = plotinfo.xaxis;
var ya = plotinfo.yaxis;
- var trace = cdscatter[0].trace;
+ var trace = getTraceFromCd(cdscatter);
var line = trace.line;
var tr = d3.select(element);
@@ -267,7 +272,16 @@ function plotOne(gd, idx, plotinfo, cdscatter, cdscatterAll, element, transition
};
}
- var lineJoin = lines.selectAll('.js-line').data(segments);
+ var lineJoin = lines.selectAll('.js-line')
+ .data(segments)
+ .enter()
+ .append('path');
+
+ lineJoin
+ .classed('js-line', true)
+ .style('vector-effect', 'non-scaling-stroke')
+ .call(Drawing.lineGroupStyle);
+ // .each(makeUpdate(true));
transition(lineJoin.exit())
.style('opacity', 0)
@@ -275,12 +289,6 @@ function plotOne(gd, idx, plotinfo, cdscatter, cdscatterAll, element, transition
lineJoin.each(makeUpdate(false));
- lineJoin.enter().append('path')
- .classed('js-line', true)
- .style('vector-effect', 'non-scaling-stroke')
- .call(Drawing.lineGroupStyle)
- .each(makeUpdate(true));
-
Drawing.setClipUrl(lineJoin, plotinfo.layerClipId, gd);
function clearFill(selection) {
@@ -375,7 +383,7 @@ function plotOne(gd, idx, plotinfo, cdscatter, cdscatterAll, element, transition
function makePoints(points, text, cdscatter) {
var join, selection, hasNode;
- var trace = cdscatter[0].trace;
+ var trace = getTraceFromCd(cdscatter);
var showMarkers = subTypes.hasMarkers(trace);
var showText = subTypes.hasText(trace);
@@ -406,13 +414,23 @@ function plotOne(gd, idx, plotinfo, cdscatter, cdscatterAll, element, transition
selection = points.selectAll('path.point');
- join = selection.data(markerFilter, keyFunc);
+ join = selection.data(markerFilter, keyFunc)
+ .enter()
+ .append('path');
+
+ if(hasTransition) {
+ join.exit().transition()
+ .style('opacity', 0)
+ .remove();
+ } else {
+ join.exit().remove();
+ }
- var enter = join.enter().append('path')
+ join
.classed('point', true);
if(hasTransition) {
- enter
+ join
.call(Drawing.pointStyle, trace, gd)
.call(Drawing.translatePoints, xa, ya)
.style('opacity', 0)
@@ -447,21 +465,19 @@ function plotOne(gd, idx, plotinfo, cdscatter, cdscatterAll, element, transition
}
});
- if(hasTransition) {
- join.exit().transition()
- .style('opacity', 0)
- .remove();
- } else {
- join.exit().remove();
- }
-
// text points
selection = text.selectAll('g');
- join = selection.data(textFilter, keyFunc);
+ join = selection.data(textFilter, keyFunc)
+ // each text needs to go in its own 'g' in case
+ // it gets converted to mathjax
+ .enter()
+ .append('g');
- // each text needs to go in its own 'g' in case
- // it gets converted to mathjax
- join.enter().append('g').classed('textpoint', true).append('text');
+ join.exit().remove();
+
+ join
+ .classed('textpoint', true)
+ .append('text');
join.order();
@@ -488,11 +504,9 @@ function plotOne(gd, idx, plotinfo, cdscatter, cdscatterAll, element, transition
var y = ya.c2p(d.y);
d3.select(this).selectAll('tspan.line').each(function() {
- transition(d3.select(this)).attr({x: x, y: y});
+ transition(d3.select(this)).attrs({x: x, y: y});
});
});
-
- join.exit().remove();
}
points.datum(cdscatter);
@@ -513,7 +527,7 @@ function selectMarkers(gd, idx, plotinfo, cdscatter, cdscatterAll) {
var xr = d3.extent(Lib.simpleMap(xa.range, xa.r2c));
var yr = d3.extent(Lib.simpleMap(ya.range, ya.r2c));
- var trace = cdscatter[0].trace;
+ var trace = getTraceFromCd(cdscatter);
if(!subTypes.hasMarkers(trace)) return;
// if marker.maxdisplayed is used, select a maximum of
// mnum markers to show, from the set that are in the viewport
diff --git a/src/traces/scatter/select.js b/src/traces/scatter/select.js
index 01f757a779e..c5f7f4e7731 100644
--- a/src/traces/scatter/select.js
+++ b/src/traces/scatter/select.js
@@ -1,5 +1,6 @@
'use strict';
+var getTraceFromCd = require('../../lib/trace_from_cd');
var subtypes = require('./subtypes');
module.exports = function selectPoints(searchInfo, selectionTester) {
@@ -7,7 +8,7 @@ module.exports = function selectPoints(searchInfo, selectionTester) {
var xa = searchInfo.xaxis;
var ya = searchInfo.yaxis;
var selection = [];
- var trace = cd[0].trace;
+ var trace = getTraceFromCd(cd);
var i;
var di;
var x;
diff --git a/src/traces/scatter/style.js b/src/traces/scatter/style.js
index 64bfac1416e..8dee9ce21ff 100644
--- a/src/traces/scatter/style.js
+++ b/src/traces/scatter/style.js
@@ -1,6 +1,7 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
+var getTraceFromCd = require('../../lib/trace_from_cd');
var Drawing = require('../../components/drawing');
var Registry = require('../../registry');
@@ -8,18 +9,19 @@ function style(gd) {
var s = d3.select(gd).selectAll('g.trace.scatter');
s.style('opacity', function(d) {
- return d[0].trace.opacity;
+ var trace = getTraceFromCd(d);
+ return trace.opacity;
});
s.selectAll('g.points').each(function(d) {
var sel = d3.select(this);
- var trace = d.trace || d[0].trace;
+ var trace = getTraceFromCd(d);
stylePoints(sel, trace, gd);
});
s.selectAll('g.text').each(function(d) {
var sel = d3.select(this);
- var trace = d.trace || d[0].trace;
+ var trace = getTraceFromCd(d);
styleText(sel, trace, gd);
});
@@ -41,7 +43,7 @@ function styleText(sel, trace, gd) {
}
function styleOnSelect(gd, cd, sel) {
- var trace = cd[0].trace;
+ var trace = getTraceFromCd(cd);
if(trace.selectedpoints) {
Drawing.selectedPointStyle(sel.selectAll('path.point'), trace);
diff --git a/src/traces/scattergeo/hover.js b/src/traces/scattergeo/hover.js
index b9d54ae6f7d..4102a15239d 100644
--- a/src/traces/scattergeo/hover.js
+++ b/src/traces/scattergeo/hover.js
@@ -1,5 +1,6 @@
'use strict';
+var getTraceFromCd = require('../../lib/trace_from_cd');
var Fx = require('../../components/fx');
var BADNUM = require('../../constants/numerical').BADNUM;
@@ -9,7 +10,7 @@ var attributes = require('./attributes');
module.exports = function hoverPoints(pointData, xval, yval) {
var cd = pointData.cd;
- var trace = cd[0].trace;
+ var trace = getTraceFromCd(cd);
var xa = pointData.xa;
var ya = pointData.ya;
var geo = pointData.subplot;
diff --git a/src/traces/scattergeo/plot.js b/src/traces/scattergeo/plot.js
index 29d57b2c95a..c3e67eb2512 100644
--- a/src/traces/scattergeo/plot.js
+++ b/src/traces/scattergeo/plot.js
@@ -1,8 +1,9 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var Lib = require('../../lib');
+var getTraceFromCd = require('../../lib/trace_from_cd');
var getTopojsonFeatures = require('../../lib/topojson_utils').getTopojsonFeatures;
var geoJsonUtils = require('../../lib/geojson_utils');
var geoUtils = require('../../lib/geo_location_utils');
@@ -28,7 +29,7 @@ function plot(gd, geo, calcData) {
gTraces.each(function(calcTrace) {
var s = d3.select(this);
- var trace = calcTrace[0].trace;
+ var trace = getTraceFromCd(calcTrace);
if(subTypes.hasLines(trace) || trace.fill !== 'none') {
var lineCoords = geoJsonUtils.calcTraceToLineCoords(calcTrace);
@@ -39,7 +40,8 @@ function plot(gd, geo, calcData) {
s.selectAll('path.js-line')
.data([{geojson: lineData, trace: trace}])
- .enter().append('path')
+ .enter()
+ .append('path')
.classed('js-line', true)
.style('stroke-miterlimit', 2);
}
@@ -47,7 +49,8 @@ function plot(gd, geo, calcData) {
if(subTypes.hasMarkers(trace)) {
s.selectAll('path.point')
.data(Lib.identity)
- .enter().append('path')
+ .enter()
+ .append('path')
.classed('point', true)
.each(function(calcPt) { removeBADNUM(calcPt, this); });
}
@@ -55,7 +58,8 @@ function plot(gd, geo, calcData) {
if(subTypes.hasText(trace)) {
s.selectAll('g')
.data(Lib.identity)
- .enter().append('g')
+ .enter()
+ .append('g')
.append('text')
.each(function(calcPt) { removeBADNUM(calcPt, this); });
}
@@ -66,7 +70,7 @@ function plot(gd, geo, calcData) {
}
function calcGeoJSON(calcTrace, fullLayout) {
- var trace = calcTrace[0].trace;
+ var trace = getTraceFromCd(calcTrace);
var geoLayout = fullLayout[trace.geo];
var geo = geoLayout._subplot;
var len = trace._length;
diff --git a/src/traces/scattergeo/select.js b/src/traces/scattergeo/select.js
index 37c70c565aa..f3327fc8c6c 100644
--- a/src/traces/scattergeo/select.js
+++ b/src/traces/scattergeo/select.js
@@ -1,5 +1,6 @@
'use strict';
+var getTraceFromCd = require('../../lib/trace_from_cd');
var subtypes = require('../scatter/subtypes');
var BADNUM = require('../../constants/numerical').BADNUM;
@@ -8,7 +9,7 @@ module.exports = function selectPoints(searchInfo, selectionTester) {
var xa = searchInfo.xaxis;
var ya = searchInfo.yaxis;
var selection = [];
- var trace = cd[0].trace;
+ var trace = getTraceFromCd(cd);
var di, lonlat, x, y, i;
diff --git a/src/traces/scattergeo/style.js b/src/traces/scattergeo/style.js
index 03f2a29ada6..4ff536ed065 100644
--- a/src/traces/scattergeo/style.js
+++ b/src/traces/scattergeo/style.js
@@ -1,6 +1,7 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
+var getTraceFromCd = require('../../lib/trace_from_cd');
var Drawing = require('../../components/drawing');
var Color = require('../../components/color');
@@ -13,10 +14,10 @@ module.exports = function style(gd, calcTrace) {
};
function styleTrace(gd, calcTrace) {
- var trace = calcTrace[0].trace;
+ var trace = getTraceFromCd(calcTrace);
var s = calcTrace[0].node3;
- s.style('opacity', calcTrace[0].trace.opacity);
+ s.style('opacity', getTraceFromCd(calcTrace).opacity);
stylePoints(s, trace, gd);
styleText(s, trace, gd);
diff --git a/src/traces/scattergl/hover.js b/src/traces/scattergl/hover.js
index 41e25458f6f..8170b61cfbd 100644
--- a/src/traces/scattergl/hover.js
+++ b/src/traces/scattergl/hover.js
@@ -2,12 +2,13 @@
var Registry = require('../../registry');
var Lib = require('../../lib');
+var getTraceFromCd = require('../../lib/trace_from_cd');
var getTraceColor = require('../scatter/get_trace_color');
function hoverPoints(pointData, xval, yval, hovermode) {
var cd = pointData.cd;
var stash = cd[0].t;
- var trace = cd[0].trace;
+ var trace = getTraceFromCd(cd);
var xa = pointData.xa;
var ya = pointData.ya;
var x = stash.x;
diff --git a/src/traces/scattergl/select.js b/src/traces/scattergl/select.js
index 6cd16c34a49..f0c57560203 100644
--- a/src/traces/scattergl/select.js
+++ b/src/traces/scattergl/select.js
@@ -1,5 +1,6 @@
'use strict';
+var getTraceFromCd = require('../../lib/trace_from_cd');
var subTypes = require('../scatter/subtypes');
var styleTextSelection = require('./edit_style').styleTextSelection;
@@ -8,7 +9,7 @@ module.exports = function select(searchInfo, selectionTester) {
var xa = searchInfo.xaxis;
var ya = searchInfo.yaxis;
var selection = [];
- var trace = cd[0].trace;
+ var trace = getTraceFromCd(cd);
var stash = cd[0].t;
var len = trace._length;
var x = stash.x;
diff --git a/src/traces/scattermapbox/convert.js b/src/traces/scattermapbox/convert.js
index 130db2b80af..e5d4dbda68f 100644
--- a/src/traces/scattermapbox/convert.js
+++ b/src/traces/scattermapbox/convert.js
@@ -3,6 +3,7 @@
var isNumeric = require('fast-isnumeric');
var Lib = require('../../lib');
+var getTraceFromCd = require('../../lib/trace_from_cd');
var BADNUM = require('../../constants/numerical').BADNUM;
var geoJsonUtils = require('../../lib/geojson_utils');
@@ -17,7 +18,7 @@ var NEWLINES = require('../../lib/svg_text_utils').NEWLINES;
var BR_TAG_ALL = require('../../lib/svg_text_utils').BR_TAG_ALL;
module.exports = function convert(gd, calcTrace) {
- var trace = calcTrace[0].trace;
+ var trace = getTraceFromCd(calcTrace);
var isVisible = (trace.visible === true && trace._length !== 0);
var hasFill = (trace.fill !== 'none');
@@ -151,7 +152,7 @@ function initContainer() {
}
function makeCircleOpts(calcTrace) {
- var trace = calcTrace[0].trace;
+ var trace = getTraceFromCd(calcTrace);
var marker = trace.marker;
var selectedpoints = trace.selectedpoints;
var arrayColor = Lib.isArrayOrTypedArray(marker.color);
@@ -240,7 +241,7 @@ function makeCircleOpts(calcTrace) {
function makeSymbolGeoJSON(calcTrace, gd) {
var fullLayout = gd._fullLayout;
- var trace = calcTrace[0].trace;
+ var trace = getTraceFromCd(calcTrace);
var marker = trace.marker || {};
var symbol = marker.symbol;
diff --git a/src/traces/scattermapbox/hover.js b/src/traces/scattermapbox/hover.js
index a582cf4b4b2..6f7abcf4aab 100644
--- a/src/traces/scattermapbox/hover.js
+++ b/src/traces/scattermapbox/hover.js
@@ -2,13 +2,14 @@
var Fx = require('../../components/fx');
var Lib = require('../../lib');
+var getTraceFromCd = require('../../lib/trace_from_cd');
var getTraceColor = require('../scatter/get_trace_color');
var fillText = Lib.fillText;
var BADNUM = require('../../constants/numerical').BADNUM;
function hoverPoints(pointData, xval, yval) {
var cd = pointData.cd;
- var trace = cd[0].trace;
+ var trace = getTraceFromCd(cd);
var xa = pointData.xa;
var ya = pointData.ya;
var subplot = pointData.subplot;
diff --git a/src/traces/scattermapbox/index.js b/src/traces/scattermapbox/index.js
index 5a93d8e2c70..e58b8138a28 100644
--- a/src/traces/scattermapbox/index.js
+++ b/src/traces/scattermapbox/index.js
@@ -1,5 +1,7 @@
'use strict';
+var getTraceFromCd = require('../../lib/trace_from_cd');
+
module.exports = {
attributes: require('./attributes'),
supplyDefaults: require('./defaults'),
@@ -13,7 +15,7 @@ module.exports = {
styleOnSelect: function(_, cd) {
if(cd) {
- var trace = cd[0].trace;
+ var trace = getTraceFromCd(cd);
trace._glTrace.update(cd);
}
},
diff --git a/src/traces/scattermapbox/plot.js b/src/traces/scattermapbox/plot.js
index 21e95b36c0a..0b00020e4e0 100644
--- a/src/traces/scattermapbox/plot.js
+++ b/src/traces/scattermapbox/plot.js
@@ -1,6 +1,7 @@
'use strict';
var convert = require('./convert');
+var getTraceFromCd = require('../../lib/trace_from_cd');
var LAYER_PREFIX = require('../../plots/mapbox/constants').traceLayerPrefix;
var ORDER = ['fill', 'line', 'circle', 'symbol'];
@@ -90,7 +91,7 @@ proto.update = function update(calcTrace) {
}
// link ref for quick update during selections
- calcTrace[0].trace._glTrace = this;
+ getTraceFromCd(calcTrace)._glTrace = this;
};
proto.dispose = function dispose() {
@@ -104,7 +105,7 @@ proto.dispose = function dispose() {
};
module.exports = function createScatterMapbox(subplot, calcTrace) {
- var trace = calcTrace[0].trace;
+ var trace = getTraceFromCd(calcTrace);
var scatterMapbox = new ScatterMapbox(subplot, trace.uid);
var optsAll = convert(subplot.gd, calcTrace);
var below = scatterMapbox.below = subplot.belowLookup['trace-' + trace.uid];
@@ -117,7 +118,7 @@ module.exports = function createScatterMapbox(subplot, calcTrace) {
}
// link ref for quick update during selections
- calcTrace[0].trace._glTrace = scatterMapbox;
+ getTraceFromCd(calcTrace)._glTrace = scatterMapbox;
return scatterMapbox;
};
diff --git a/src/traces/scattermapbox/select.js b/src/traces/scattermapbox/select.js
index 4bf52b8e69c..0c67778a27d 100644
--- a/src/traces/scattermapbox/select.js
+++ b/src/traces/scattermapbox/select.js
@@ -1,6 +1,7 @@
'use strict';
var Lib = require('../../lib');
+var getTraceFromCd = require('../../lib/trace_from_cd');
var subtypes = require('../scatter/subtypes');
var BADNUM = require('../../constants/numerical').BADNUM;
@@ -9,7 +10,7 @@ module.exports = function selectPoints(searchInfo, selectionTester) {
var xa = searchInfo.xaxis;
var ya = searchInfo.yaxis;
var selection = [];
- var trace = cd[0].trace;
+ var trace = getTraceFromCd(cd);
var i;
if(!subtypes.hasMarkers(trace)) return [];
diff --git a/src/traces/splom/hover.js b/src/traces/splom/hover.js
index 1ae60244525..3900a2f1466 100644
--- a/src/traces/splom/hover.js
+++ b/src/traces/splom/hover.js
@@ -1,11 +1,12 @@
'use strict';
var helpers = require('./helpers');
+var getTraceFromCd = require('../../lib/trace_from_cd');
var calcHover = require('../scattergl/hover').calcHover;
function hoverPoints(pointData, xval, yval) {
var cd = pointData.cd;
- var trace = cd[0].trace;
+ var trace = getTraceFromCd(cd);
var scene = pointData.scene;
var cdata = scene.matrixOptions.cdata;
var xa = pointData.xa;
diff --git a/src/traces/splom/select.js b/src/traces/splom/select.js
index 84e24fb2ec8..44796c9a97a 100644
--- a/src/traces/splom/select.js
+++ b/src/traces/splom/select.js
@@ -1,12 +1,13 @@
'use strict';
var Lib = require('../../lib');
+var getTraceFromCd = require('../../lib/trace_from_cd');
var subTypes = require('../scatter/subtypes');
var helpers = require('./helpers');
module.exports = function select(searchInfo, selectionTester) {
var cd = searchInfo.cd;
- var trace = cd[0].trace;
+ var trace = getTraceFromCd(cd);
var stash = cd[0].t;
var scene = searchInfo.scene;
var cdata = scene.matrixOptions.cdata;
diff --git a/src/traces/sunburst/fx.js b/src/traces/sunburst/fx.js
index 931541b3929..185011f185b 100644
--- a/src/traces/sunburst/fx.js
+++ b/src/traces/sunburst/fx.js
@@ -1,6 +1,6 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var Registry = require('../../registry');
var appendArrayPointValue = require('../../components/fx/helpers').appendArrayPointValue;
var Fx = require('../../components/fx');
diff --git a/src/traces/sunburst/plot.js b/src/traces/sunburst/plot.js
index bcbddfbe4e8..c404204d524 100644
--- a/src/traces/sunburst/plot.js
+++ b/src/traces/sunburst/plot.js
@@ -1,11 +1,12 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var d3Hierarchy = require('d3-hierarchy');
var interpolate = require('d3-interpolate').interpolate;
var Drawing = require('../../components/drawing');
var Lib = require('../../lib');
+var getTraceFromCd = require('../../lib/trace_from_cd');
var svgTextUtils = require('../../lib/svg_text_utils');
var uniformText = require('../bar/uniform_text');
var recordMinTextSize = uniformText.recordMinTextSize;
@@ -21,6 +22,7 @@ var constants = require('./constants');
var helpers = require('./helpers');
exports.plot = function(gd, cdmodule, transitionOpts, makeOnCompleteCallback) {
+ var d3EaseFn = Lib.whichD3EaseFn(transitionOpts);
var fullLayout = gd._fullLayout;
var layer = fullLayout._sunburstlayer;
var join, onComplete;
@@ -33,13 +35,14 @@ exports.plot = function(gd, cdmodule, transitionOpts, makeOnCompleteCallback) {
clearMinTextSize('sunburst', fullLayout);
join = layer.selectAll('g.trace.sunburst')
- .data(cdmodule, function(cd) { return cd[0].trace.uid; });
+ .data(cdmodule, function(cd) { return getTraceFromCd(cd).uid; })
+ .enter()
+ .append('g');
- // using same 'stroke-linejoin' as pie traces
- join.enter().append('g')
+ join
.classed('trace', true)
.classed('sunburst', true)
- .attr('stroke-linejoin', 'round');
+ .attr('stroke-linejoin', 'round'); // using same 'stroke-linejoin' as pie traces
join.order();
@@ -53,7 +56,7 @@ exports.plot = function(gd, cdmodule, transitionOpts, makeOnCompleteCallback) {
var transition = d3.transition()
.duration(transitionOpts.duration)
- .ease(transitionOpts.easing)
+ .ease(d3EaseFn)
.each('end', function() { onComplete && onComplete(); })
.each('interrupt', function() { onComplete && onComplete(); });
@@ -164,10 +167,10 @@ function plotOne(gd, cd, element, transitionOpts) {
var getTargetX = function(d) { return cx + getTextXY(d)[0] * (d.transform.rCenter || 0) + (d.transform.x || 0); };
var getTargetY = function(d) { return cy + getTextXY(d)[1] * (d.transform.rCenter || 0) + (d.transform.y || 0); };
- slices = slices.data(sliceData, helpers.getPtId);
-
- slices.enter().append('g')
- .classed('slice', true);
+ slices = slices
+ .data(sliceData, helpers.getPtId)
+ .enter()
+ .append('g');
if(hasTransition) {
slices.exit().transition()
@@ -188,6 +191,9 @@ function plotOne(gd, cd, element, transitionOpts) {
slices.exit().remove();
}
+ slices
+ .classed('slice', true);
+
slices.order();
// next x1 (i.e. sector end angle) of previous entry
diff --git a/src/traces/sunburst/style.js b/src/traces/sunburst/style.js
index 5b563f63cc0..26d35a1714a 100644
--- a/src/traces/sunburst/style.js
+++ b/src/traces/sunburst/style.js
@@ -1,6 +1,6 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var Color = require('../../components/color');
var Lib = require('../../lib');
var resizeText = require('../bar/uniform_text').resizeText;
diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js
index 98480fa976a..2e4f21d45de 100644
--- a/src/traces/table/plot.js
+++ b/src/traces/table/plot.js
@@ -1,7 +1,7 @@
'use strict';
var c = require('./constants');
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var Lib = require('../../lib');
var numberFormat = Lib.numberFormat;
var gup = require('../../lib/gup');
@@ -22,12 +22,13 @@ module.exports = function plot(gd, wrappedTraceHolders) {
var traceHolder = gup.unwrap(wrappedTraceHolder);
var trace = traceHolder.trace;
return prepareData(gd, trace);
- }), gup.keyFun);
+ }), gup.keyFun)
+ .enter()
+ .append('g');
table.exit().remove();
- table.enter()
- .append('g')
+ table
.classed(c.cn.table, true)
.attr('overflow', 'visible')
.style('box-sizing', 'content-box')
@@ -45,10 +46,11 @@ module.exports = function plot(gd, wrappedTraceHolders) {
});
var tableControlView = table.selectAll('.' + c.cn.tableControlView)
- .data(gup.repeat, gup.keyFun);
+ .data(gup.repeat, gup.keyFun)
+ .enter()
+ .append('g');
- var cvEnter = tableControlView.enter()
- .append('g')
+ var cvEnter = tableControlView
.classed(c.cn.tableControlView, true)
.style('box-sizing', 'content-box');
if(dynamic) {
@@ -79,10 +81,11 @@ module.exports = function plot(gd, wrappedTraceHolders) {
// scrollBackground merely ensures that mouse events are captured even on crazy fast scrollwheeling
// otherwise rendering glitches may occur
var scrollBackground = tableControlView.selectAll('.' + c.cn.scrollBackground)
- .data(gup.repeat, gup.keyFun);
+ .data(gup.repeat, gup.keyFun)
+ .enter()
+ .append('rect');
- scrollBackground.enter()
- .append('rect')
+ scrollBackground
.classed(c.cn.scrollBackground, true)
.attr('fill', 'none');
@@ -95,19 +98,20 @@ module.exports = function plot(gd, wrappedTraceHolders) {
});
var yColumn = tableControlView.selectAll('.' + c.cn.yColumn)
- .data(function(vm) {return vm.columns;}, gup.keyFun);
-
- yColumn.enter()
- .append('g')
- .classed(c.cn.yColumn, true);
+ .data(function(vm) {return vm.columns;}, gup.keyFun)
+ .enter()
+ .append('g');
yColumn.exit().remove();
+ yColumn
+ .classed(c.cn.yColumn, true);
+
yColumn.attr('transform', function(d) {return strTranslate(d.x, 0);});
if(dynamic) {
- yColumn.call(d3.behavior.drag()
- .origin(function(d) {
+ yColumn.call(d3.drag()
+ .subject(function(d) {
var movedColumn = d3.select(this);
easeColumn(movedColumn, d, -c.uplift);
raiseToTop(this);
@@ -136,7 +140,7 @@ module.exports = function plot(gd, wrappedTraceHolders) {
.call(cancelEeaseColumn)
.attr('transform', strTranslate(d.x, -c.uplift));
})
- .on('dragend', function(d) {
+ .on('end', function(d) {
var movedColumn = d3.select(this);
var p = d.calcdata;
d.x = d.xScale(d);
@@ -152,10 +156,11 @@ module.exports = function plot(gd, wrappedTraceHolders) {
});
var columnBlock = yColumn.selectAll('.' + c.cn.columnBlock)
- .data(splitData.splitToPanels, gup.keyFun);
+ .data(splitData.splitToPanels, gup.keyFun)
+ .enter()
+ .append('g');
- columnBlock.enter()
- .append('g')
+ columnBlock
.classed(c.cn.columnBlock, true)
.attr('id', function(d) {return d.key;});
@@ -168,13 +173,13 @@ module.exports = function plot(gd, wrappedTraceHolders) {
var cellsColumnBlock = columnBlock.filter(cellsBlock);
if(dynamic) {
- cellsColumnBlock.call(d3.behavior.drag()
- .origin(function(d) {
+ cellsColumnBlock.call(d3.drag()
+ .subject(function(d) {
d3.event.stopPropagation();
return d;
})
.on('drag', makeDragRow(gd, tableControlView, -1))
- .on('dragend', function() {
+ .on('end', function() {
// fixme emit plotly notification
})
);
@@ -186,18 +191,20 @@ module.exports = function plot(gd, wrappedTraceHolders) {
renderColumnCellTree(gd, tableControlView, cellsColumnBlock, columnBlock);
var scrollAreaClip = tableControlView.selectAll('.' + c.cn.scrollAreaClip)
- .data(gup.repeat, gup.keyFun);
+ .data(gup.repeat, gup.keyFun)
+ .enter()
+ .append('clipPath');
- scrollAreaClip.enter()
- .append('clipPath')
+ scrollAreaClip
.classed(c.cn.scrollAreaClip, true)
.attr('id', function(d) {return scrollAreaBottomClipKey(gd, d);});
var scrollAreaClipRect = scrollAreaClip.selectAll('.' + c.cn.scrollAreaClipRect)
- .data(gup.repeat, gup.keyFun);
+ .data(gup.repeat, gup.keyFun)
+ .enter()
+ .append('rect');
- scrollAreaClipRect.enter()
- .append('rect')
+ scrollAreaClipRect
.classed(c.cn.scrollAreaClipRect, true)
.attr('x', -c.overdrag)
.attr('y', -c.uplift)
@@ -208,28 +215,31 @@ module.exports = function plot(gd, wrappedTraceHolders) {
.attr('height', function(d) {return d.height + c.uplift;});
var columnBoundary = yColumn.selectAll('.' + c.cn.columnBoundary)
- .data(gup.repeat, gup.keyFun);
+ .data(gup.repeat, gup.keyFun)
+ .enter()
+ .append('g');
- columnBoundary.enter()
- .append('g')
+ columnBoundary
.classed(c.cn.columnBoundary, true);
var columnBoundaryClippath = yColumn.selectAll('.' + c.cn.columnBoundaryClippath)
- .data(gup.repeat, gup.keyFun);
+ .data(gup.repeat, gup.keyFun)
+ .enter()
+ .append('clipPath');
// SVG spec doesn't mandate wrapping into a and doesn't seem to cause a speed difference
- columnBoundaryClippath.enter()
- .append('clipPath')
+ columnBoundaryClippath
.classed(c.cn.columnBoundaryClippath, true);
columnBoundaryClippath
.attr('id', function(d) {return columnBoundaryClipKey(gd, d);});
var columnBoundaryRect = columnBoundaryClippath.selectAll('.' + c.cn.columnBoundaryRect)
- .data(gup.repeat, gup.keyFun);
+ .data(gup.repeat, gup.keyFun)
+ .enter()
+ .append('rect');
- columnBoundaryRect.enter()
- .append('rect')
+ columnBoundaryRect
.classed(c.cn.columnBoundaryRect, true)
.attr('fill', 'none');
@@ -255,8 +265,7 @@ function columnBoundaryClipKey(gd, d) {
}
function flatData(selection) {
- return [].concat.apply([], selection.map(function(g) {return g;}))
- .map(function(g) {return g.__data__;});
+ return [].concat.apply([], selection.data());
}
function renderScrollbarKit(tableControlView, gd, bypassVisibleBar) {
@@ -266,10 +275,11 @@ function renderScrollbarKit(tableControlView, gd, bypassVisibleBar) {
}
var scrollbarKit = tableControlView.selectAll('.' + c.cn.scrollbarKit)
- .data(gup.repeat, gup.keyFun);
+ .data(gup.repeat, gup.keyFun)
+ .enter()
+ .append('g');
- scrollbarKit.enter()
- .append('g')
+ scrollbarKit
.classed(c.cn.scrollbarKit, true)
.style('shape-rendering', 'geometricPrecision');
@@ -293,17 +303,19 @@ function renderScrollbarKit(tableControlView, gd, bypassVisibleBar) {
});
var scrollbar = scrollbarKit.selectAll('.' + c.cn.scrollbar)
- .data(gup.repeat, gup.keyFun);
+ .data(gup.repeat, gup.keyFun)
+ .enter()
+ .append('g');
- scrollbar.enter()
- .append('g')
+ scrollbar
.classed(c.cn.scrollbar, true);
var scrollbarSlider = scrollbar.selectAll('.' + c.cn.scrollbarSlider)
- .data(gup.repeat, gup.keyFun);
+ .data(gup.repeat, gup.keyFun)
+ .enter()
+ .append('g');
- scrollbarSlider.enter()
- .append('g')
+ scrollbarSlider
.classed(c.cn.scrollbarSlider, true);
scrollbarSlider
@@ -312,10 +324,11 @@ function renderScrollbarKit(tableControlView, gd, bypassVisibleBar) {
});
var scrollbarGlyph = scrollbarSlider.selectAll('.' + c.cn.scrollbarGlyph)
- .data(gup.repeat, gup.keyFun);
+ .data(gup.repeat, gup.keyFun)
+ .enter()
+ .append('line');
- scrollbarGlyph.enter()
- .append('line')
+ scrollbarGlyph
.classed(c.cn.scrollbarGlyph, true)
.attr('stroke', 'black')
.attr('stroke-width', c.scrollbarWidth)
@@ -339,10 +352,11 @@ function renderScrollbarKit(tableControlView, gd, bypassVisibleBar) {
.attr('stroke-opacity', 0);
var scrollbarCaptureZone = scrollbar.selectAll('.' + c.cn.scrollbarCaptureZone)
- .data(gup.repeat, gup.keyFun);
+ .data(gup.repeat, gup.keyFun)
+ .enter()
+ .append('line');
- scrollbarCaptureZone.enter()
- .append('line')
+ scrollbarCaptureZone
.classed(c.cn.scrollbarCaptureZone, true)
.attr('stroke', 'white')
.attr('stroke-opacity', 0.01) // some browser might get rid of a 0 opacity element
@@ -354,19 +368,19 @@ function renderScrollbarKit(tableControlView, gd, bypassVisibleBar) {
var bbox = this.getBoundingClientRect();
var s = d.scrollbarState;
var pixelVal = y - bbox.top;
- var inverseScale = d3.scale.linear().domain([0, s.scrollableAreaHeight]).range([0, s.totalHeight]).clamp(true);
+ var inverseScale = d3.scaleLinear().domain([0, s.scrollableAreaHeight]).range([0, s.totalHeight]).clamp(true);
if(!(s.topY <= pixelVal && pixelVal <= s.bottomY)) {
makeDragRow(gd, tableControlView, null, inverseScale(pixelVal - s.barLength / 2))(d);
}
})
- .call(d3.behavior.drag()
- .origin(function(d) {
+ .call(d3.drag()
+ .subject(function(d) {
d3.event.stopPropagation();
d.scrollbarState.scrollbarScrollInProgress = true;
return d;
})
.on('drag', makeDragRow(gd, tableControlView))
- .on('dragend', function() {
+ .on('end', function() {
// fixme emit Plotly event
})
);
@@ -414,10 +428,11 @@ function renderColumnCellTree(gd, tableControlView, columnBlock, allColumnBlock)
function renderColumnCells(columnBlock) {
var columnCells = columnBlock.selectAll('.' + c.cn.columnCells)
- .data(gup.repeat, gup.keyFun);
+ .data(gup.repeat, gup.keyFun)
+ .enter()
+ .append('g');
- columnCells.enter()
- .append('g')
+ columnCells
.classed(c.cn.columnCells, true);
columnCells.exit()
@@ -428,10 +443,11 @@ function renderColumnCells(columnBlock) {
function renderColumnCell(columnCells) {
var columnCell = columnCells.selectAll('.' + c.cn.columnCell)
- .data(splitData.splitToCells, function(d) {return d.keyWithinBlock;});
+ .data(splitData.splitToCells, function(d) {return d.keyWithinBlock;})
+ .enter()
+ .append('g');
- columnCell.enter()
- .append('g')
+ columnCell
.classed(c.cn.columnCell, true);
columnCell.exit()
@@ -442,10 +458,11 @@ function renderColumnCell(columnCells) {
function renderCellRect(columnCell) {
var cellRect = columnCell.selectAll('.' + c.cn.cellRect)
- .data(gup.repeat, function(d) {return d.keyWithinBlock;});
+ .data(gup.repeat, function(d) {return d.keyWithinBlock;})
+ .enter()
+ .append('rect');
- cellRect.enter()
- .append('rect')
+ cellRect
.classed(c.cn.cellRect, true);
return cellRect;
@@ -453,10 +470,11 @@ function renderCellRect(columnCell) {
function renderCellText(cellTextHolder) {
var cellText = cellTextHolder.selectAll('.' + c.cn.cellText)
- .data(gup.repeat, function(d) {return d.keyWithinBlock;});
+ .data(gup.repeat, function(d) {return d.keyWithinBlock;})
+ .enter()
+ .append('text');
- cellText.enter()
- .append('text')
+ cellText
.classed(c.cn.cellText, true)
.style('cursor', function() {return 'auto';})
.on('mousedown', function() {d3.event.stopPropagation();});
@@ -466,10 +484,11 @@ function renderCellText(cellTextHolder) {
function renderCellTextHolder(columnCell) {
var cellTextHolder = columnCell.selectAll('.' + c.cn.cellTextHolder)
- .data(gup.repeat, function(d) {return d.keyWithinBlock;});
+ .data(gup.repeat, function(d) {return d.keyWithinBlock;})
+ .enter()
+ .append('g');
- cellTextHolder.enter()
- .append('g')
+ cellTextHolder
.classed(c.cn.cellTextHolder, true)
.style('shape-rendering', 'geometricPrecision');
diff --git a/src/traces/treemap/draw.js b/src/traces/treemap/draw.js
index 9fa5a7126c2..20497ecd405 100644
--- a/src/traces/treemap/draw.js
+++ b/src/traces/treemap/draw.js
@@ -1,7 +1,8 @@
'use strict';
-var d3 = require('@plotly/d3');
-
+var Lib = require('../../lib');
+var d3 = require('../../lib/d3');
+var getTraceFromCd = require('../../lib/trace_from_cd');
var helpers = require('../sunburst/helpers');
var uniformText = require('../bar/uniform_text');
var clearMinTextSize = uniformText.clearMinTextSize;
@@ -10,6 +11,7 @@ var resizeText = require('../bar/style').resizeText;
var plotOne = require('./plot_one');
module.exports = function _plot(gd, cdmodule, transitionOpts, makeOnCompleteCallback, opts) {
+ var d3EaseFn = Lib.whichD3EaseFn(transitionOpts);
var type = opts.type;
var drawDescendants = opts.drawDescendants;
@@ -24,9 +26,11 @@ module.exports = function _plot(gd, cdmodule, transitionOpts, makeOnCompleteCall
clearMinTextSize(type, fullLayout);
join = layer.selectAll('g.trace.' + type)
- .data(cdmodule, function(cd) { return cd[0].trace.uid; });
+ .data(cdmodule, function(cd) { return getTraceFromCd(cd).uid; })
+ .enter()
+ .append('g');
- join.enter().append('g')
+ join
.classed('trace', true)
.classed(type, true);
@@ -42,7 +46,7 @@ module.exports = function _plot(gd, cdmodule, transitionOpts, makeOnCompleteCall
var transition = d3.transition()
.duration(transitionOpts.duration)
- .ease(transitionOpts.easing)
+ .ease(d3EaseFn)
.each('end', function() { onComplete && onComplete(); })
.each('interrupt', function() { onComplete && onComplete(); });
diff --git a/src/traces/treemap/draw_ancestors.js b/src/traces/treemap/draw_ancestors.js
index a25bcfea236..8cff64b6337 100644
--- a/src/traces/treemap/draw_ancestors.js
+++ b/src/traces/treemap/draw_ancestors.js
@@ -1,6 +1,6 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var Lib = require('../../lib');
var Drawing = require('../../components/drawing');
var svgTextUtils = require('../../lib/svg_text_utils');
@@ -65,13 +65,15 @@ module.exports = function drawAncestors(gd, cd, entry, slices, opts) {
sliceData.reverse();
- slices = slices.data(sliceData, helpers.getPtId);
-
- slices.enter().append('g')
- .classed('pathbar', true);
+ slices = slices.data(sliceData, helpers.getPtId)
+ .enter()
+ .append('g');
handleSlicesExit(slices, onPathbar, refRect, [width, height], pathSlice);
+ slices
+ .classed('pathbar', true);
+
slices.order();
var updateSlices = slices;
diff --git a/src/traces/treemap/draw_descendants.js b/src/traces/treemap/draw_descendants.js
index d34296e8d05..4cc0adc86bc 100644
--- a/src/traces/treemap/draw_descendants.js
+++ b/src/traces/treemap/draw_descendants.js
@@ -1,6 +1,6 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var Lib = require('../../lib');
var Drawing = require('../../components/drawing');
var svgTextUtils = require('../../lib/svg_text_utils');
@@ -71,15 +71,17 @@ module.exports = function drawDescendants(gd, cd, entry, slices, opts) {
}
});
- slices = slices.data(sliceData, helpers.getPtId);
-
trace._maxVisibleLayers = isFinite(maxVisibleDepth) ? maxVisibleDepth - minVisibleDepth + 1 : 0;
- slices.enter().append('g')
- .classed('slice', true);
+ slices = slices.data(sliceData, helpers.getPtId)
+ .enter()
+ .append('g');
handleSlicesExit(slices, onPathbar, refRect, [width, height], pathSlice);
+ slices
+ .classed('slice', true);
+
slices.order();
// next coords of previous entry
diff --git a/src/traces/treemap/plot_one.js b/src/traces/treemap/plot_one.js
index cc244fce43f..9ac3a7a2f61 100644
--- a/src/traces/treemap/plot_one.js
+++ b/src/traces/treemap/plot_one.js
@@ -1,6 +1,6 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var interpolate = require('d3-interpolate').interpolate;
var helpers = require('../sunburst/helpers');
diff --git a/src/traces/treemap/style.js b/src/traces/treemap/style.js
index 86a18b083cc..40a34baa4a4 100644
--- a/src/traces/treemap/style.js
+++ b/src/traces/treemap/style.js
@@ -1,6 +1,6 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var Color = require('../../components/color');
var Lib = require('../../lib');
var helpers = require('../sunburst/helpers');
diff --git a/src/traces/violin/cross_trace_calc.js b/src/traces/violin/cross_trace_calc.js
index 8a97afcf638..bd738e8fcb1 100644
--- a/src/traces/violin/cross_trace_calc.js
+++ b/src/traces/violin/cross_trace_calc.js
@@ -1,5 +1,6 @@
'use strict';
+var getTraceFromCd = require('../../lib/trace_from_cd');
var setPositionOffset = require('../box/cross_trace_calc').setPositionOffset;
var orientations = ['v', 'h'];
@@ -16,7 +17,7 @@ module.exports = function crossTraceCalc(gd, plotinfo) {
for(var j = 0; j < calcdata.length; j++) {
var cd = calcdata[j];
var t = cd[0].t;
- var trace = cd[0].trace;
+ var trace = getTraceFromCd(cd);
if(trace.visible === true && trace.type === 'violin' &&
!t.empty &&
diff --git a/src/traces/violin/hover.js b/src/traces/violin/hover.js
index eb716dc80ae..02bdb29d7e9 100644
--- a/src/traces/violin/hover.js
+++ b/src/traces/violin/hover.js
@@ -1,6 +1,7 @@
'use strict';
var Lib = require('../../lib');
+var getTraceFromCd = require('../../lib/trace_from_cd');
var Axes = require('../../plots/cartesian/axes');
var boxHoverPoints = require('../box/hover');
var helpers = require('./helpers');
@@ -10,7 +11,7 @@ module.exports = function hoverPoints(pointData, xval, yval, hovermode, opts) {
var hoverLayer = opts.hoverLayer;
var cd = pointData.cd;
- var trace = cd[0].trace;
+ var trace = getTraceFromCd(cd);
var hoveron = trace.hoveron;
var hasHoveronViolins = hoveron.indexOf('violins') !== -1;
var hasHoveronKDE = hoveron.indexOf('kde') !== -1;
@@ -85,12 +86,16 @@ module.exports = function hoverPoints(pointData, xval, yval, hovermode, opts) {
// update violin line (if any)
var violinLine = hoverLayer.selectAll('.violinline-' + trace.uid)
- .data(violinLineAttrs ? [0] : []);
- violinLine.enter().append('line')
- .classed('violinline-' + trace.uid, true)
- .attr('stroke-width', 1.5);
+ .data(violinLineAttrs ? [0] : [])
+ .enter()
+ .append('line');
+
violinLine.exit().remove();
- violinLine.attr(violinLineAttrs);
+
+ violinLine
+ .classed('violinline-' + trace.uid, true)
+ .attr('stroke-width', 1.5)
+ .attrs(violinLineAttrs);
// same combine logic as box hoverPoints
if(hovermode === 'closest') {
diff --git a/src/traces/violin/plot.js b/src/traces/violin/plot.js
index 62f46650266..cdd1b83a026 100644
--- a/src/traces/violin/plot.js
+++ b/src/traces/violin/plot.js
@@ -1,6 +1,6 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var Lib = require('../../lib');
var Drawing = require('../../components/drawing');
@@ -45,14 +45,17 @@ module.exports = function plot(gd, plotinfo, cdViolins, violinLayer) {
var hasPositiveSide = hasBothSides || trace.side === 'positive';
var hasNegativeSide = hasBothSides || trace.side === 'negative';
- var violins = plotGroup.selectAll('path.violin').data(Lib.identity);
+ var violins = plotGroup.selectAll('path.violin')
+ .data(Lib.identity)
+ .enter()
+ .append('path');
- violins.enter().append('path')
+ violins.exit().remove();
+
+ violins
.style('vector-effect', 'non-scaling-stroke')
.attr('class', 'violin');
- violins.exit().remove();
-
violins.each(function(d) {
var pathSel = d3.select(this);
var density = d.density;
@@ -158,12 +161,18 @@ module.exports = function plot(gd, plotinfo, cdViolins, violinLayer) {
// N.B. use different class name than boxPlot.plotBoxMean,
// to avoid selectAll conflict
- var meanPaths = plotGroup.selectAll('path.meanline').data(fn || []);
- meanPaths.enter().append('path')
+ var meanPaths = plotGroup.selectAll('path.meanline')
+ .data(fn || [])
+ .enter()
+ .append('path');
+
+ meanPaths.exit().remove();
+
+ meanPaths
.attr('class', 'meanline')
.style('fill', 'none')
.style('vector-effect', 'non-scaling-stroke');
- meanPaths.exit().remove();
+
meanPaths.each(function(d) {
var v = valAxis.c2p(d.mean, true);
var p = helpers.getPositionOnKdePath(d, trace, v);
diff --git a/src/traces/violin/style.js b/src/traces/violin/style.js
index 697668dfd99..bf5508f0903 100644
--- a/src/traces/violin/style.js
+++ b/src/traces/violin/style.js
@@ -1,16 +1,17 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
+var getTraceFromCd = require('../../lib/trace_from_cd');
var Color = require('../../components/color');
var stylePoints = require('../scatter/style').stylePoints;
module.exports = function style(gd) {
var s = d3.select(gd).selectAll('g.trace.violins');
- s.style('opacity', function(d) { return d[0].trace.opacity; });
+ s.style('opacity', function(d) { return getTraceFromCd(d).opacity; });
s.each(function(d) {
- var trace = d[0].trace;
+ var trace = getTraceFromCd(d);
var sel = d3.select(this);
var box = trace.box || {};
var boxLine = box.line || {};
@@ -33,11 +34,11 @@ module.exports = function style(gd) {
};
sel.selectAll('path.mean')
- .style(meanLineStyle)
+ .styles(meanLineStyle)
.call(Color.stroke, meanline.color);
sel.selectAll('path.meanline')
- .style(meanLineStyle)
+ .styles(meanLineStyle)
.call(Color.stroke, meanline.color);
stylePoints(sel, trace, gd);
diff --git a/src/traces/waterfall/hover.js b/src/traces/waterfall/hover.js
index b7b0ed23444..0e1d57de64d 100644
--- a/src/traces/waterfall/hover.js
+++ b/src/traces/waterfall/hover.js
@@ -1,5 +1,6 @@
'use strict';
+var getTraceFromCd = require('../../lib/trace_from_cd');
var hoverLabelText = require('../../plots/cartesian/axes').hoverLabelText;
var opacity = require('../../components/color').opacity;
var hoverOnBars = require('../bar/hover').hoverOnBars;
@@ -15,7 +16,7 @@ module.exports = function hoverPoints(pointData, xval, yval, hovermode, opts) {
if(!point) return;
var cd = point.cd;
- var trace = cd[0].trace;
+ var trace = getTraceFromCd(cd);
var isHorizontal = (trace.orientation === 'h');
var vLetter = isHorizontal ? 'x' : 'y';
diff --git a/src/traces/waterfall/plot.js b/src/traces/waterfall/plot.js
index a5908f755d3..9efcdb2e526 100644
--- a/src/traces/waterfall/plot.js
+++ b/src/traces/waterfall/plot.js
@@ -1,7 +1,8 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
var Lib = require('../../lib');
+var getTraceFromCd = require('../../lib/trace_from_cd');
var Drawing = require('../../components/drawing');
var BADNUM = require('../../constants/numerical').BADNUM;
var barPlot = require('../bar/plot');
@@ -28,7 +29,7 @@ function plotConnectors(gd, plotinfo, cdModule, traceLayer) {
Lib.makeTraceGroups(traceLayer, cdModule, 'trace bars').each(function(cd) {
var plotGroup = d3.select(this);
- var trace = cd[0].trace;
+ var trace = getTraceFromCd(cd);
var group = Lib.ensureSingle(plotGroup, 'g', 'lines');
@@ -40,13 +41,16 @@ function plotConnectors(gd, plotinfo, cdModule, traceLayer) {
var isHorizontal = (trace.orientation === 'h');
var mode = trace.connector.mode;
- var connectors = group.selectAll('g.line').data(Lib.identity);
-
- connectors.enter().append('g')
- .classed('line', true);
+ var connectors = group.selectAll('g.line')
+ .data(Lib.identity)
+ .enter()
+ .append('g');
connectors.exit().remove();
+ connectors
+ .classed('line', true);
+
var len = connectors.size();
connectors.each(function(di, i) {
diff --git a/src/traces/waterfall/style.js b/src/traces/waterfall/style.js
index 7a0cd005ac4..059f1f38838 100644
--- a/src/traces/waterfall/style.js
+++ b/src/traces/waterfall/style.js
@@ -1,6 +1,7 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../../lib/d3');
+var getTraceFromCd = require('../../lib/trace_from_cd');
var Drawing = require('../../components/drawing');
var Color = require('../../components/color');
@@ -13,11 +14,11 @@ function style(gd, cd, sel) {
var s = sel ? sel : d3.select(gd).selectAll('g.waterfalllayer').selectAll('g.trace');
resizeText(gd, s, 'waterfall');
- s.style('opacity', function(d) { return d[0].trace.opacity; });
+ s.style('opacity', function(d) { return getTraceFromCd(d).opacity; });
s.each(function(d) {
var gTrace = d3.select(this);
- var trace = d[0].trace;
+ var trace = getTraceFromCd(d);
gTrace.selectAll('.point > path').each(function(di) {
if(!di.isBlank) {
diff --git a/test/image/compare_pixels_test.js b/test/image/compare_pixels_test.js
index ac57770a978..c5eb74f9878 100644
--- a/test/image/compare_pixels_test.js
+++ b/test/image/compare_pixels_test.js
@@ -57,6 +57,536 @@ function unique(value, index, self) {
}
allMockList = allMockList.filter(unique);
+// keeping track of the mocks that passed image test in initial attempt to bump d3
+var whiteList = [
+ '0',
+ '1',
+ '10',
+ '12',
+ '13',
+ '14',
+ '17',
+ '18',
+ '20',
+ '21',
+ '25',
+ '26',
+ '27',
+ '2dhistogram_contour_subplots_bingroup',
+ '2dhistogram_contour_subplots',
+ '30',
+ '31',
+ '32',
+ '4',
+ 'animation_bar',
+ 'annotations',
+ 'arrow-markers',
+ 'axes_breaks-dtick_auto',
+ 'axes_breaks-dtick_hourly',
+ 'axes_breaks-gridlines',
+ 'axes_breaks-matches',
+ 'axes_breaks-night_autorange-reversed',
+ 'axes_breaks-ohlc_candlestick_box',
+ 'axes_breaks-overlap',
+ 'axes_breaks-reversed-without-pattern',
+ 'axes_breaks-round-weekdays',
+ 'axes_breaks-tickvals',
+ 'axes_breaks-values',
+ 'axes_breaks-weekends_autorange-reversed',
+ 'axes_breaks-weekends-weeknights',
+ 'axes_breaks',
+ 'axes_category_ascending',
+ 'axes_category_categoryarray_truncated_tails',
+ 'axes_category_categoryarray',
+ 'axes_category_descending_with_gaps',
+ 'axes_category_descending',
+ 'axes_category_null',
+ 'axes_chain_scaleanchor_matches_inside-ticklabels',
+ 'axes_chain_scaleanchor_matches',
+ 'axes_chain_scaleanchor_matches2_inside-ticklabels',
+ 'axes_chain_scaleanchor_matches2',
+ 'axes_custom-ticks_log-date',
+ 'axes_enumerated_ticks',
+ 'axes_free_default',
+ 'axes_line_noticklabels',
+ 'axes_matches-linear-categories',
+ 'axes_range_mode',
+ 'axes_reversed',
+ 'axes_scaleanchor-with-matches',
+ 'axes_scaleanchor',
+ 'axes_visible-false',
+ 'axis-title-standoff',
+ 'axislabel_separatethousands',
+ 'bar_and_histogram',
+ 'bar_annotation_max_range_eq_category',
+ 'bar_bargap0',
+ 'bar_gantt-chart',
+ 'bar_hide_nulls',
+ 'bar_nonnumeric_sizes',
+ 'bar_show_narrow',
+ 'bar_unhidden',
+ 'bar-alignment-offset',
+ 'bar-autotext-log-size-axes',
+ 'bar-grouping-vs-defaults',
+ 'bar-like_traces_no-tozero_stack',
+ 'bar-offsetgroups',
+ 'basic_bar',
+ 'basic_error_bar',
+ 'blank-bar-outsidetext',
+ 'box_grouped-multicategory',
+ 'box_horz_notched',
+ 'box_notched-inverted-end',
+ 'box_notched',
+ 'box_plot_jitter',
+ 'box_precomputed-stats',
+ 'box_single-group',
+ 'box_violin_just_pts',
+ 'box_with-empty-1st-trace',
+ 'box-alignment-offset',
+ 'box-violin-multicategory-on-val-axis',
+ 'box-violin-x0-category-position',
+ 'boxplots_outliercolordflt',
+ 'boxplots_undefined_vals',
+ 'bubblechart',
+ 'canada_geo_projections',
+ 'carpet_axis',
+ 'carpet_ordering-labeling',
+ 'carpet_rounded-off-edgepath-gt',
+ 'carpet_rounded-off-edgepath-lt',
+ 'carpet_rounded-off-edgepath',
+ 'carpet_template',
+ 'category_dtick_3',
+ 'category-autorange',
+ 'cheater_constraint_greater_than_with_hill',
+ 'cheater_constraint_greater_than_with_valley',
+ 'cheater_constraint_greater_than',
+ 'cheater_constraint_inner_range_hi_top_with_hill',
+ 'cheater_constraint_inner_range_hi_top_with_valley',
+ 'cheater_constraint_inner_range_hi_top',
+ 'cheater_constraint_inner_range_lo_top_with_hill',
+ 'cheater_constraint_inner_range_lo_top_with_valley',
+ 'cheater_constraint_inner_range_lo_top',
+ 'cheater_constraint_inner_range_with_hill',
+ 'cheater_constraint_inner_range_with_valley',
+ 'cheater_constraint_inner_range',
+ 'cheater_constraint_less_than_with_hill',
+ 'cheater_constraint_less_than_with_valley',
+ 'cheater_constraint_less_than',
+ 'cheater_constraint_outer_range_hi_top_with_hill',
+ 'cheater_constraint_outer_range_hi_top_with_valley',
+ 'cheater_constraint_outer_range_hi_top',
+ 'cheater_constraint_outer_range_lo_top_with_hill',
+ 'cheater_constraint_outer_range_lo_top_with_valley',
+ 'cheater_constraint_outer_range_lo_top',
+ 'cheater_constraint_outer_range_with_hill',
+ 'cheater_constraint_outer_range_with_valley',
+ 'cheater_constraint_outer_range',
+ 'cheaterslope_noticklabels',
+ 'cheaterslope',
+ 'cliponaxis_false-dates-log',
+ 'cliponaxis_false',
+ 'connectgaps_2d',
+ 'contour_constraints_edge_cases',
+ 'contour_constraints_equal_boundary_minmax',
+ 'contour_constraints',
+ 'contour_heatmap_coloring',
+ 'contour_label-font-size',
+ 'contour_label-reversed-axes',
+ 'contour_label-reversed-xy',
+ 'contour_label-thousands-suffix',
+ 'contour_lines_coloring',
+ 'contour_log',
+ 'contour_match_edges',
+ 'contour_scatter',
+ 'date_axes_period_breaks_automargin',
+ 'date_axes_period',
+ 'date_axes_period2',
+ 'date_axes_side_top',
+ 'date_axes',
+ 'date_histogram',
+ 'distance_satellite',
+ 'domain_refs',
+ 'empty',
+ 'error_bar_asymmetric_array',
+ 'error_bar_asymmetric_constant',
+ 'error_bar_bar_ids',
+ 'error_bar_horizontal',
+ 'error_bar_sqrt',
+ 'fake_violins',
+ 'font-wishlist',
+ 'fonts',
+ 'funnelarea_fonts',
+ 'funnelarea_label0_dlabel',
+ 'funnelarea_labels_colors_text',
+ 'funnelarea_no_scalegroup_various_domain',
+ 'funnelarea_no_scalegroup_various_ratios_and_domain',
+ 'funnelarea_no_scalegroup_various_ratios',
+ 'funnelarea_scalegroup_two',
+ 'funnelarea_scalegroup_various_ratios_and_domain',
+ 'funnelarea_scalegroup_various_ratios',
+ 'funnelarea_simple',
+ 'funnelarea_style',
+ 'geo_across-antimeridian',
+ 'geo_aitoff-sinusoidal',
+ 'geo_big-frame',
+ 'geo_canadian-cities',
+ 'geo_centering',
+ 'geo_country-names-text-chart',
+ 'geo_country-names',
+ 'geo_custom-colorscale',
+ 'geo_custom-geojson',
+ 'geo_featureidkey',
+ 'geo_fill',
+ 'geo_fitbounds-geojson',
+ 'geo_fitbounds-locations',
+ 'geo_fitbounds-scopes',
+ 'geo_lakes-and-rivers',
+ 'geo_miterlimit-base-layers',
+ 'geo_multi-geos',
+ 'geo_multiple-usa-choropleths',
+ 'geo_point-selection',
+ 'geo_scattergeo-locations',
+ 'geo_scattergeo-out-of-usa',
+ 'geo_text_chart_arrays',
+ 'geo_winkel-tripel',
+ 'gl2d_10',
+ 'gl2d_12',
+ 'gl2d_14',
+ 'gl2d_17',
+ 'gl2d_annotations',
+ 'gl2d_axes_labels2',
+ 'gl2d_axes_range_mode',
+ 'gl2d_clean-number',
+ 'gl2d_clustering',
+ 'gl2d_error_bars_log',
+ 'gl2d_fill-ordering',
+ 'gl2d_fonts',
+ 'gl2d_horiz-lines',
+ 'gl2d_line_aligned',
+ 'gl2d_line_dash',
+ 'gl2d_line_limit',
+ 'gl2d_line_select',
+ 'gl2d_marker_line_width',
+ 'gl2d_marker_size',
+ 'gl2d_marker_symbols',
+ 'gl2d_multiple-traces-axes',
+ 'gl2d_no-clustering',
+ 'gl2d_no-clustering2',
+ 'gl2d_open_marker_line_width',
+ 'gl2d_point-selection',
+ 'gl2d_pointcloud-basic',
+ 'gl2d_scatter-color-clustering',
+ 'gl2d_scatter-colorscale-points',
+ 'gl2d_scatter-continuous-clustering',
+ 'gl2d_scatter-marker-line-colorscales',
+ 'gl2d_scatter2d-multiple-colors',
+ 'gl2d_scattergl_gaps',
+ 'gl2d_selectedpoints',
+ 'gl2d_shapes_below_traces',
+ 'gl2d_size_margins',
+ 'gl2d_subplots_anchor',
+ 'gl2d_text_chart_basic',
+ 'gl2d_text_chart_single-string',
+ 'gl2d_text_chart_styling',
+ 'gl2d_texttemplate',
+ 'gl2d_tick-labels',
+ 'gl2d_ultra_zoom',
+ 'gl3d_annotations_orthographic',
+ 'gl3d_annotations',
+ 'gl3d_axes-visible-false',
+ 'gl3d_cone-autorange',
+ 'gl3d_cone-lighting',
+ 'gl3d_cone-with-streamtube',
+ 'gl3d_delaunay',
+ 'gl3d_directions-isosurface1',
+ 'gl3d_directions-isosurface2',
+ 'gl3d_directions-streamtube1',
+ 'gl3d_directions-streamtube2',
+ 'gl3d_directions-volume1',
+ 'gl3d_error_bars_log_2',
+ 'gl3d_error_bars_log',
+ 'gl3d_errorbars_sqrt',
+ 'gl3d_errorbars_xy',
+ 'gl3d_errorbars_zx',
+ 'gl3d_errorbars_zy',
+ 'gl3d_formatted-text-on-multiple-lines',
+ 'gl3d_indicator_scatter3d',
+ 'gl3d_marker_symbols',
+ 'gl3d_marker-arrays',
+ 'gl3d_marker-color',
+ 'gl3d_mesh3d_enable-alpha-with-rgba-color',
+ 'gl3d_mesh3d_surface_lighting',
+ 'gl3d_mesh3d-missing-colors',
+ 'gl3d_mirror-ticks',
+ 'gl3d_opacity-surface',
+ 'gl3d_scatter3d_line3d_error3d_enable-alpha-with-rgba-color',
+ 'gl3d_scatter3d_line3d_error3d_transparent-with-zero-alpha',
+ 'gl3d_scatter3d-different-align-texts',
+ 'gl3d_set-ranges',
+ 'gl3d_snowden_altered',
+ 'gl3d_snowden',
+ 'gl3d_streamtube-wind',
+ 'gl3d_surface_opacity_match_mesh3d',
+ 'gl3d_surface-lighting',
+ 'gl3d_tetrahedra',
+ 'gl3d_text-weirdness',
+ 'gl3d_ticks-milliseconds',
+ 'gl3d_traces-with-opacity',
+ 'gl3d_triangle',
+ 'gl3d_world-cals',
+ 'gl3d_z-range',
+ 'global_font',
+ 'glpolar_scatter',
+ 'groups-over-matching-axes',
+ 'heatmap_brick_padding',
+ 'heatmap_small_aspect-ratio',
+ 'heatmap-with-zero-category',
+ 'hist_0_to_093',
+ 'hist_0_to_1_midpoints',
+ 'hist_003_to_093',
+ 'hist_003_to_1',
+ 'hist_all_integer_n50',
+ 'hist_all_integer',
+ 'hist_almost_integer',
+ 'hist_category',
+ 'hist_cum_stacked',
+ 'hist_summed',
+ 'hist_valid_ses_y',
+ 'hist_valid_ses',
+ 'histogram_colorscale',
+ 'histogram_overlay-bingroup',
+ 'histogram-offsetgroups',
+ 'histogram2d_bingroup',
+ 'hists-on-matching-axes',
+ 'icicle_coffee-maxdepth3-all-directions',
+ 'icicle_coffee-maxdepth3',
+ 'icicle_coffee',
+ 'icicle_first',
+ 'icicle_flare',
+ 'icicle_leaf-opacity-level',
+ 'icicle_root-sort',
+ 'icicle_textposition',
+ 'icicle_with-without_values_template',
+ 'icicle_with-without_values',
+ 'image_adventurer',
+ 'image_astronaut_source',
+ 'image_axis_reverse',
+ 'image_axis_type',
+ 'image_cat',
+ 'image_colormodel',
+ 'image_non_numeric',
+ 'image_opacity',
+ 'image_source_axis_reverse_zsmooth',
+ 'image_source_axis_reverse',
+ 'image_with_gaps',
+ 'image_zmin_zmax',
+ 'indicator_attrs',
+ 'indicator_bignumber',
+ 'indicator_datacard',
+ 'indicator_datacard2',
+ 'indicator_datacard3',
+ 'indicator_format_extremes',
+ 'indicator_scatter',
+ 'japanese',
+ 'legend_horizontal_one_row',
+ 'legend_horizontal_testwrap',
+ 'legend_horizontal',
+ 'legend_inside',
+ 'legend_margin-autoexpand-false',
+ 'legend_mathjax_title_and_items',
+ 'legend_style',
+ 'legendgroup_horizontal_bg_fit',
+ 'legendrank',
+ 'legendrank2',
+ 'line_grid_color',
+ 'line_grid_width',
+ 'log_lines_fills',
+ 'mapbox_angles',
+ 'mapbox_bubbles-text',
+ 'mapbox_carto-style',
+ 'mapbox_choropleth-raw-geojson',
+ 'mapbox_custom-style',
+ 'mapbox_fill',
+ 'mapbox_geojson-attributes',
+ 'mapbox_layers',
+ 'mapbox_stamen-style',
+ 'mapbox_symbol-text',
+ 'mapbox_texttemplate',
+ 'mapbox_white-bg-style',
+ 'marker_line_width',
+ 'marker_symbols',
+ 'matching-categories',
+ 'mathjax',
+ 'mirror-all-vs-allticks',
+ 'multicategory_histograms',
+ 'multicategory-inside-ticks',
+ 'multicategory-sorting',
+ 'multicategory-y',
+ 'percent_error_bar',
+ 'period_positioning8',
+ 'period_positioning9',
+ 'pie_fonts',
+ 'pie_label0_dlabel',
+ 'pie_labels_colors_text',
+ 'pie_scale_textpos_hideslices',
+ 'pie_simple',
+ 'pie_sort_direction',
+ 'pie_style_arrays',
+ 'pie_style',
+ 'pie_textpad_radial',
+ 'pie_textpad_tangential',
+ 'pie_title_pull',
+ 'pie_title_subscript',
+ 'plot_types',
+ 'point-selection',
+ 'point-selection2',
+ 'polar_bar-width-base-offset',
+ 'polar_blank',
+ 'polar_dates',
+ 'polar_direction',
+ 'polar_fills',
+ 'polar_hole',
+ 'polar_line',
+ 'polar_long-category-angular-labels',
+ 'polar_polygon-bars',
+ 'polar_polygon-grids',
+ 'polar_r0dr-theta0dtheta',
+ 'polar_radial-range',
+ 'polar_scatter',
+ 'polar_sector',
+ 'polar_template',
+ 'polar_ticks',
+ 'range_slider_multiple',
+ 'reversed-axis-dividers',
+ 'sankey_circular_large',
+ 'sankey_circular_process',
+ 'sankey_circular_simple',
+ 'sankey_circular_simple2',
+ 'sankey_circular',
+ 'sankey_large_padding',
+ 'sankey_link_concentration',
+ 'sankey_messy',
+ 'sankey_subplots_circular',
+ 'sankey_subplots',
+ 'sankey_x_y',
+ 'scatter_fill_self_opacity',
+ 'scatter-marker-line-colorscales',
+ 'shapes_below_traces',
+ 'shapes',
+ 'simple_annotation',
+ 'size_margins',
+ 'smith_basic',
+ 'smith_blank',
+ 'smith_fills',
+ 'smith_modes',
+ 'smith_template',
+ 'splom_0',
+ 'splom_array-styles',
+ 'splom_dates',
+ 'splom_large',
+ 'splom_lower-nodiag-matching',
+ 'splom_lower-nodiag',
+ 'splom_mismatched-axis-types',
+ 'splom_multi-axis-type',
+ 'splom_nodiag',
+ 'splom_ragged-via-axes',
+ 'splom_ragged-via-visible-false',
+ 'splom_symbol_numbers',
+ 'splom_upper-nodiag',
+ 'splom_with-cartesian',
+ 'stacked_area_groupby',
+ 'style_bar',
+ 'sunburst_branchvalues-total-almost-equal',
+ 'sunburst_coffee-maxdepth3',
+ 'sunburst_coffee',
+ 'sunburst_first',
+ 'sunburst_flare',
+ 'sunburst_inside-text-orientation_clock',
+ 'sunburst_inside-text-orientation',
+ 'sunburst_level-depth',
+ 'sunburst_textfit',
+ 'sunburst_textpad_tangential',
+ 'sunburst_values',
+ 'sunburst_with-without_values',
+ 'sunburst_zero_values_textfit',
+ 'table_plain_birds',
+ 'table_ragged',
+ 'table_wrapped_birds',
+ 'ternary_axis_layers',
+ 'ternary_lines',
+ 'ternary_markers',
+ 'ternary_noticks',
+ 'ternary_simple',
+ 'ternary-mathjax',
+ 'text_chart_basic',
+ 'text_chart_single-string',
+ 'text_chart_styling',
+ 'text_export',
+ 'texttemplate_scatter',
+ 'tick_attributes',
+ 'tick_prefix_suffix_exponent',
+ 'tick_prefix_suffix',
+ 'tick-datafn',
+ 'tickformat',
+ 'tickformatstops',
+ 'ticklabeloverflow-0',
+ 'ticklabeloverflow-1',
+ 'ticklabeloverflow-2',
+ 'ticklabelposition-0',
+ 'ticklabelposition-overlay2',
+ 'tickson_boundaries',
+ 'treemap_coffee-maxdepth3',
+ 'treemap_coffee',
+ 'treemap_first',
+ 'treemap_flare',
+ 'treemap_fonts_nocolor',
+ 'treemap_fonts_withcolor',
+ 'treemap_level-depth',
+ 'treemap_packings',
+ 'treemap_pad_mirror',
+ 'treemap_pad_transpose',
+ 'treemap_root-color',
+ 'treemap_sunburst_basic',
+ 'treemap_sunburst_marker_colors',
+ 'treemap_textposition',
+ 'treemap_transpose_nopad',
+ 'treemap_values',
+ 'treemap_with-without_values_template',
+ 'treemap_with-without_values',
+ 'uniformtext_bar_edgecase1',
+ 'uniformtext_bar_edgecase2',
+ 'uniformtext_bar_edgecase4',
+ 'uniformtext_bar_edgecase5',
+ 'uniformtext_bar_edgecase6',
+ 'uniformtext_bar_edgecase7',
+ 'uniformtext_bar_edgecase8',
+ 'uniformtext_funnelarea',
+ 'uniformtext_icicle',
+ 'uniformtext_pie_outside',
+ 'uniformtext_sunburst_inside-text-orientation',
+ 'uniformtext_sunburst_treemap',
+ 'uniformtext_treemap_coffee-maxdepth3',
+ 'uniformtext_treemap',
+ 'various_geo_projections',
+ 'vertical-tickangles',
+ 'violin_bandwidth-edge-cases',
+ 'violin_box_multiple_widths',
+ 'violin_box_overlay',
+ 'violin_negative_sides_w_points',
+ 'violin_non-linear',
+ 'violin_old-faithful',
+ 'violin_one-sided',
+ 'violin_positive_and_negative',
+ 'violin_positive_sides_w_points',
+ 'violin_side-by-side',
+ 'violin_style',
+ 'violin_zoomed-in',
+ 'violin-offsetgroups',
+ 'waterfall_gap0',
+ 'worldcup'
+];
+
+var succeeded = [];
var skipped = [];
var failed = [];
var fail = function(mockName) {
@@ -141,12 +671,28 @@ for(var i = 0; i < allMockList.length; i++) {
} else {
// remove when identical
fs.unlinkSync(imagePaths.test);
+
+ succeeded.push(mockName);
}
}
+console.log('Total succeeded before:', whiteList.length);
+console.log('Total succeeded now:', succeeded.length);
+console.log(JSON.stringify({ succeeded: succeeded }, null, 2));
+
if(failed.length || skipped.length) {
- throw JSON.stringify({
+ console.error(JSON.stringify({
failed: failed,
skipped: skipped
- }, null, 2);
+ }, null, 2));
+
+ var c = 0;
+ for(var k = 0; k < failed.length; k++) {
+ var f = failed[k];
+ if(whiteList.indexOf(f) !== -1) {
+ console.error('"' + f + '" used to pass; but now it does not pass!');
+ c++;
+ }
+ }
+ if(c) throw 'Reduced success rate!';
}
diff --git a/test/strict-d3.js b/test/strict-d3.js
index b3705cf3ae7..831dd430a45 100644
--- a/test/strict-d3.js
+++ b/test/strict-d3.js
@@ -5,7 +5,7 @@
'use strict';
-var d3 = require('@plotly/d3');
+var d3 = require('../src/lib/d3');
var isNumeric = require('fast-isnumeric');
var selProto = d3.selection.prototype;