Skip to content

Commit 3f52a89

Browse files
committed
Merge branch 'master' into hoverlabel-custom
2 parents f8258cb + 9d149c3 commit 3f52a89

File tree

13 files changed

+647
-80
lines changed

13 files changed

+647
-80
lines changed

lib/index.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@ Plotly.register([
5757
//
5858
Plotly.register([
5959
require('./filter'),
60-
require('./groupby')
60+
require('./groupby'),
61+
require('./sort')
6162
]);
6263

6364
// components

lib/sort.js

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/**
2+
* Copyright 2012-2017, Plotly, Inc.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the MIT license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*/
8+
9+
'use strict';
10+
11+
module.exports = require('../src/transforms/sort');

src/components/drawing/index.js

+30
Original file line numberDiff line numberDiff line change
@@ -769,6 +769,36 @@ drawing.setPointGroupScale = function(selection, x, y) {
769769
return scale;
770770
};
771771

772+
var TEXT_POINT_LAST_TRANSLATION_RE = /translate\([^)]*\)\s*$/;
773+
774+
drawing.setTextPointsScale = function(selection, xScale, yScale) {
775+
selection.each(function() {
776+
var transforms;
777+
var el = d3.select(this);
778+
var text = el.select('text');
779+
var x = parseFloat(text.attr('x') || 0);
780+
var y = parseFloat(text.attr('y') || 0);
781+
782+
var existingTransform = (el.attr('transform') || '').match(TEXT_POINT_LAST_TRANSLATION_RE);
783+
784+
if(xScale === 1 && yScale === 1) {
785+
transforms = [];
786+
} else {
787+
transforms = [
788+
'translate(' + x + ',' + y + ')',
789+
'scale(' + xScale + ',' + yScale + ')',
790+
'translate(' + (-x) + ',' + (-y) + ')',
791+
];
792+
}
793+
794+
if(existingTransform) {
795+
transforms.push(existingTransform);
796+
}
797+
798+
el.attr('transform', transforms.join(' '));
799+
});
800+
};
801+
772802
drawing.measureText = function(tester, text, font) {
773803
var dummyText = tester.append('text')
774804
.text(text)

src/lib/index.js

+23
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,29 @@ lib.mergeArray = function(traceAttr, cd, cdAttr) {
344344
}
345345
};
346346

347+
/** Returns target as set by 'target' transform attribute
348+
*
349+
* @param {object} trace : full trace object
350+
* @param {object} transformOpts : transform option object
351+
* - target (string} :
352+
* either an attribute string referencing an array in the trace object, or
353+
* a set array.
354+
*
355+
* @return {array or false} : the target array (NOT a copy!!) or false if invalid
356+
*/
357+
lib.getTargetArray = function(trace, transformOpts) {
358+
var target = transformOpts.target;
359+
360+
if(typeof target === 'string' && target) {
361+
var array = lib.nestedProperty(trace, target).get();
362+
return Array.isArray(array) ? array : false;
363+
} else if(Array.isArray(target)) {
364+
return target;
365+
}
366+
367+
return false;
368+
};
369+
347370
/**
348371
* modified version of jQuery's extend to strip out private objs and functions,
349372
* and cut arrays down to first <arraylen> or 1 elements

src/plots/cartesian/axes.js

+43-2
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,13 @@ var ONEMIN = constants.ONEMIN;
2929
var ONESEC = constants.ONESEC;
3030
var BADNUM = constants.BADNUM;
3131

32-
3332
var axes = module.exports = {};
3433

3534
axes.layoutAttributes = require('./layout_attributes');
3635
axes.supplyLayoutDefaults = require('./layout_defaults');
3736

3837
axes.setConvert = require('./set_convert');
38+
var autoType = require('./axis_autotype');
3939

4040
var axisIds = require('./axis_ids');
4141
axes.id2name = axisIds.id2name;
@@ -45,7 +45,6 @@ axes.listIds = axisIds.listIds;
4545
axes.getFromId = axisIds.getFromId;
4646
axes.getFromTrace = axisIds.getFromTrace;
4747

48-
4948
/*
5049
* find the list of possible axes to reference with an xref or yref attribute
5150
* and coerce it to that list
@@ -130,6 +129,48 @@ axes.coercePosition = function(containerOut, gd, coerce, axRef, attr, dflt) {
130129
containerOut[attr] = isNumeric(pos) ? Number(pos) : dflt;
131130
};
132131

132+
axes.getDataToCoordFunc = function(gd, trace, target, targetArray) {
133+
var ax;
134+
135+
// If target points to an axis, use the type we already have for that
136+
// axis to find the data type. Otherwise use the values to autotype.
137+
var d2cTarget = (target === 'x' || target === 'y' || target === 'z') ?
138+
target :
139+
targetArray;
140+
141+
// In the case of an array target, make a mock data array
142+
// and call supplyDefaults to the data type and
143+
// setup the data-to-calc method.
144+
if(Array.isArray(d2cTarget)) {
145+
ax = {
146+
type: autoType(targetArray),
147+
_categories: []
148+
};
149+
axes.setConvert(ax);
150+
151+
// build up ax._categories (usually done during ax.makeCalcdata()
152+
if(ax.type === 'category') {
153+
for(var i = 0; i < targetArray.length; i++) {
154+
ax.d2c(targetArray[i]);
155+
}
156+
}
157+
} else {
158+
ax = axes.getFromTrace(gd, trace, d2cTarget);
159+
}
160+
161+
// if 'target' has corresponding axis
162+
// -> use setConvert method
163+
if(ax) return ax.d2c;
164+
165+
// special case for 'ids'
166+
// -> cast to String
167+
if(d2cTarget === 'ids') return function(v) { return String(v); };
168+
169+
// otherwise (e.g. numeric-array of 'marker.color' or 'marker.size')
170+
// -> cast to Number
171+
return function(v) { return +v; };
172+
};
173+
133174
// empty out types for all axes containing these traces
134175
// so we auto-set them again
135176
axes.clearTypes = function(gd, traces) {

src/plots/cartesian/dragbox.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ var constants = require('./constants');
3030
var MINDRAG = constants.MINDRAG;
3131
var MINZOOM = constants.MINZOOM;
3232

33-
3433
// flag for showing "doubleclick to zoom out" only at the beginning
3534
var SHOWZOOMOUTTIP = true;
3635

@@ -747,6 +746,10 @@ module.exports = function dragBox(gd, plotinfo, x, y, w, h, ns, ew) {
747746
// as a whole:
748747
.select('.scatterlayer').selectAll('.points').selectAll('.point')
749748
.call(Drawing.setPointGroupScale, xScaleFactor2, yScaleFactor2);
749+
750+
subplot.plot.select('.scatterlayer')
751+
.selectAll('.points').selectAll('.textpoint')
752+
.call(Drawing.setTextPointsScale, xScaleFactor2, yScaleFactor2);
750753
}
751754
}
752755

src/plots/cartesian/transition_axes.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -148,9 +148,11 @@ module.exports = function transitionAxes(gd, newLayout, transitionOpts, makeOnCo
148148
// This is specifically directed at scatter traces, applying an inverse
149149
// scale to individual points to counteract the scale of the trace
150150
// as a whole:
151-
.selectAll('.points').selectAll('.point')
151+
.select('.scatterlayer').selectAll('.points').selectAll('.point')
152152
.call(Drawing.setPointGroupScale, 1, 1);
153153

154+
subplot.plot.select('.scatterlayer').selectAll('.points').selectAll('.textpoint')
155+
.call(Drawing.setTextPointsScale, 1, 1);
154156
}
155157

156158
function updateSubplot(subplot, progress) {
@@ -229,6 +231,8 @@ module.exports = function transitionAxes(gd, newLayout, transitionOpts, makeOnCo
229231
.selectAll('.points').selectAll('.point')
230232
.call(Drawing.setPointGroupScale, 1 / xScaleFactor, 1 / yScaleFactor);
231233

234+
subplot.plot.selectAll('.points').selectAll('.textpoint')
235+
.call(Drawing.setTextPointsScale, 1 / xScaleFactor, 1 / yScaleFactor);
232236
}
233237

234238
var onComplete;

src/traces/sankey/plot.js

+10-8
Original file line numberDiff line numberDiff line change
@@ -133,13 +133,14 @@ module.exports = function plot(gd, calcData) {
133133

134134
var linkHoverFollow = function(element, d) {
135135
var trace = gd._fullData[d.traceId];
136+
var rootBBox = gd.getBoundingClientRect();
136137
var boundingBox = element.getBoundingClientRect();
137138
var hoverCenterX = boundingBox.left + boundingBox.width / 2;
138139
var hoverCenterY = boundingBox.top + boundingBox.height / 2;
139140

140141
var tooltip = Fx.loneHover({
141-
x: hoverCenterX + window.scrollX,
142-
y: hoverCenterY + window.scrollY,
142+
x: hoverCenterX - rootBBox.left,
143+
y: hoverCenterY - rootBBox.top,
143144
name: d3.format(d.valueFormat)(d.link.value) + d.valueSuffix,
144145
text: [
145146
d.link.label,
@@ -185,15 +186,16 @@ module.exports = function plot(gd, calcData) {
185186
var nodeHoverFollow = function(element, d) {
186187
var trace = gd._fullData[d.traceId];
187188
var nodeRect = d3.select(element).select('.nodeRect');
189+
var rootBBox = gd.getBoundingClientRect();
188190
var boundingBox = nodeRect.node().getBoundingClientRect();
189-
var hoverCenterX0 = boundingBox.left - 2;
190-
var hoverCenterX1 = boundingBox.right + 2;
191-
var hoverCenterY = boundingBox.top + boundingBox.height / 4;
191+
var hoverCenterX0 = boundingBox.left - 2 - rootBBox.left;
192+
var hoverCenterX1 = boundingBox.right + 2 - rootBBox.left;
193+
var hoverCenterY = boundingBox.top + boundingBox.height / 4 - rootBBox.top;
192194

193195
var tooltip = Fx.loneHover({
194-
x0: hoverCenterX0 + window.scrollX,
195-
x1: hoverCenterX1 + window.scrollX,
196-
y: hoverCenterY + window.scrollY,
196+
x0: hoverCenterX0,
197+
x1: hoverCenterX1,
198+
y: hoverCenterY,
197199
name: d3.format(d.valueFormat)(d.node.value) + d.valueSuffix,
198200
text: [
199201
d.node.label,

src/traces/scatter/plot.js

+1-2
Original file line numberDiff line numberDiff line change
@@ -455,15 +455,14 @@ function plotOne(gd, idx, plotinfo, cdscatter, cdscatterAll, element, transition
455455

456456
// each text needs to go in its own 'g' in case
457457
// it gets converted to mathjax
458-
join.enter().append('g').append('text');
458+
join.enter().append('g').classed('textpoint', true).append('text');
459459

460460
join.each(function(d) {
461461
var sel = transition(d3.select(this).select('text'));
462462
Drawing.translatePoint(d, sel, xa, ya);
463463
});
464464

465465
join.selectAll('text')
466-
.classed('textpoint', true)
467466
.call(Drawing.textPointStyle, trace)
468467
.each(function(d) {
469468

src/transforms/filter.js

+8-65
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,7 @@
1111
var Lib = require('../lib');
1212
var Registry = require('../registry');
1313
var PlotSchema = require('../plot_api/plot_schema');
14-
var axisIds = require('../plots/cartesian/axis_ids');
15-
var autoType = require('../plots/cartesian/axis_autotype');
16-
var setConvert = require('../plots/cartesian/set_convert');
14+
var Axes = require('../plots/cartesian/axes');
1715

1816
var COMPARISON_OPS = ['=', '!=', '<', '>=', '>', '<='];
1917
var INTERVAL_OPS = ['[]', '()', '[)', '(]', '][', ')(', '](', ')['];
@@ -144,12 +142,11 @@ exports.supplyDefaults = function(transformIn) {
144142
exports.calcTransform = function(gd, trace, opts) {
145143
if(!opts.enabled) return;
146144

147-
var target = opts.target,
148-
filterArray = getFilterArray(trace, target),
149-
len = filterArray.length;
150-
151-
if(!len) return;
145+
var targetArray = Lib.getTargetArray(trace, opts);
146+
if(!targetArray) return;
152147

148+
var target = opts.target;
149+
var len = targetArray.length;
153150
var targetCalendar = opts.targetcalendar;
154151

155152
// even if you provide targetcalendar, if target is a string and there
@@ -159,13 +156,8 @@ exports.calcTransform = function(gd, trace, opts) {
159156
if(attrTargetCalendar) targetCalendar = attrTargetCalendar;
160157
}
161158

162-
// if target points to an axis, use the type we already have for that
163-
// axis to find the data type. Otherwise use the values to autotype.
164-
var d2cTarget = (target === 'x' || target === 'y' || target === 'z') ?
165-
target : filterArray;
166-
167-
var dataToCoord = getDataToCoordFunc(gd, trace, d2cTarget);
168-
var filterFunc = getFilterFunc(opts, dataToCoord, targetCalendar);
159+
var d2c = Axes.getDataToCoordFunc(gd, trace, target, targetArray);
160+
var filterFunc = getFilterFunc(opts, d2c, targetCalendar);
169161
var arrayAttrs = PlotSchema.findArrayAttributes(trace);
170162
var originalArrays = {};
171163

@@ -203,60 +195,11 @@ exports.calcTransform = function(gd, trace, opts) {
203195

204196
// loop through filter array, fill trace arrays if passed
205197
for(var i = 0; i < len; i++) {
206-
var passed = filterFunc(filterArray[i]);
198+
var passed = filterFunc(targetArray[i]);
207199
if(passed) forAllAttrs(fillFn, i);
208200
}
209201
};
210202

211-
function getFilterArray(trace, target) {
212-
if(typeof target === 'string' && target) {
213-
var array = Lib.nestedProperty(trace, target).get();
214-
215-
return Array.isArray(array) ? array : [];
216-
}
217-
else if(Array.isArray(target)) return target.slice();
218-
219-
return false;
220-
}
221-
222-
function getDataToCoordFunc(gd, trace, target) {
223-
var ax;
224-
225-
// In the case of an array target, make a mock data array
226-
// and call supplyDefaults to the data type and
227-
// setup the data-to-calc method.
228-
if(Array.isArray(target)) {
229-
ax = {
230-
type: autoType(target),
231-
_categories: []
232-
};
233-
234-
setConvert(ax);
235-
236-
if(ax.type === 'category') {
237-
// build up ax._categories (usually done during ax.makeCalcdata()
238-
for(var i = 0; i < target.length; i++) {
239-
ax.d2c(target[i]);
240-
}
241-
}
242-
}
243-
else {
244-
ax = axisIds.getFromTrace(gd, trace, target);
245-
}
246-
247-
// if 'target' has corresponding axis
248-
// -> use setConvert method
249-
if(ax) return ax.d2c;
250-
251-
// special case for 'ids'
252-
// -> cast to String
253-
if(target === 'ids') return function(v) { return String(v); };
254-
255-
// otherwise (e.g. numeric-array of 'marker.color' or 'marker.size')
256-
// -> cast to Number
257-
return function(v) { return +v; };
258-
}
259-
260203
function getFilterFunc(opts, d2c, targetCalendar) {
261204
var operation = opts.operation,
262205
value = opts.value,

0 commit comments

Comments
 (0)