Skip to content

Commit 81e33ae

Browse files
authored
Merge pull request #1891 from plotly/hover-fix-colorbars-with-custom-tickvaltext
Hover fix for colorbars with custom tickval / ticktext
2 parents f56e071 + 2050e3f commit 81e33ae

File tree

4 files changed

+117
-6
lines changed

4 files changed

+117
-6
lines changed

src/components/fx/helpers.js

+8-3
Original file line numberDiff line numberDiff line change
@@ -108,9 +108,14 @@ exports.appendArrayPointValue = function(pointData, trace, pointNumber) {
108108

109109
if(pointData[key] === undefined) {
110110
var val = Lib.nestedProperty(trace, astr).get();
111-
pointData[key] = Array.isArray(pointNumber) ?
112-
val[pointNumber[0]][pointNumber[1]] :
113-
val[pointNumber];
111+
112+
if(Array.isArray(pointNumber)) {
113+
if(Array.isArray(val) && Array.isArray(val[pointNumber[0]])) {
114+
pointData[key] = val[pointNumber[0]][pointNumber[1]];
115+
}
116+
} else {
117+
pointData[key] = val[pointNumber];
118+
}
114119
}
115120
}
116121
};

src/plot_api/plot_schema.js

+15-3
Original file line numberDiff line numberDiff line change
@@ -142,13 +142,25 @@ exports.isValObject = function(obj) {
142142
* list of array attributes for the given trace
143143
*/
144144
exports.findArrayAttributes = function(trace) {
145-
var arrayAttributes = [],
146-
stack = [];
145+
var arrayAttributes = [];
146+
var stack = [];
147147

148148
function callback(attr, attrName, attrs, level) {
149149
stack = stack.slice(0, level).concat([attrName]);
150150

151-
var splittableAttr = attr && (attr.valType === 'data_array' || attr.arrayOk === true);
151+
var splittableAttr = (
152+
attr &&
153+
(attr.valType === 'data_array' || attr.arrayOk === true) &&
154+
!(stack[level - 1] === 'colorbar' && (attrName === 'ticktext' || attrName === 'tickvals'))
155+
);
156+
157+
// Manually exclude 'colorbar.tickvals' and 'colorbar.ticktext' for now
158+
// which are declared as `valType: 'data_array'` but scale independently of
159+
// the coordinate arrays.
160+
//
161+
// Down the road, we might want to add a schema field (e.g `uncorrelatedArray: true`)
162+
// to distinguish attributes of the likes.
163+
152164
if(!splittableAttr) return;
153165

154166
var astr = toAttrString(stack);

test/jasmine/tests/cartesian_interact_test.js

+80
Original file line numberDiff line numberDiff line change
@@ -440,3 +440,83 @@ describe('axis zoom/pan and main plot zoom', function() {
440440
.then(done);
441441
});
442442
});
443+
444+
describe('Event data:', function() {
445+
var gd;
446+
447+
beforeEach(function() {
448+
gd = createGraphDiv();
449+
});
450+
451+
afterEach(destroyGraphDiv);
452+
453+
function _hover(px, py) {
454+
return new Promise(function(resolve, reject) {
455+
gd.once('plotly_hover', function(d) {
456+
delete gd._lastHoverTime;
457+
resolve(d);
458+
});
459+
460+
mouseEvent('mousemove', px, py);
461+
462+
setTimeout(function() {
463+
reject('plotly_hover did not get called!');
464+
}, 100);
465+
});
466+
}
467+
468+
it('should have correct content for *scatter* traces', function(done) {
469+
Plotly.plot(gd, [{
470+
y: [1, 2, 1],
471+
marker: {
472+
color: [20, 30, 10],
473+
colorbar: {
474+
tickvals: [25],
475+
ticktext: ['one single tick']
476+
}
477+
}
478+
}], {
479+
width: 500,
480+
height: 500
481+
})
482+
.then(function() { return _hover(200, 200); })
483+
.then(function(d) {
484+
var pt = d.points[0];
485+
486+
expect(pt.y).toBe(2, 'y');
487+
expect(pt['marker.color']).toBe(30, 'marker.color');
488+
expect('marker.colorbar.tickvals' in pt).toBe(false, 'marker.colorbar.tickvals');
489+
expect('marker.colorbar.ticktext' in pt).toBe(false, 'marker.colorbar.ticktext');
490+
})
491+
.catch(fail)
492+
.then(done);
493+
});
494+
495+
it('should have correct content for *heatmap* traces', function(done) {
496+
Plotly.plot(gd, [{
497+
type: 'heatmap',
498+
z: [[1, 2, 1], [2, 3, 1]],
499+
colorbar: {
500+
tickvals: [2],
501+
ticktext: ['one single tick']
502+
},
503+
text: [['incomplete array']],
504+
ids: [['incomplete array']]
505+
}], {
506+
width: 500,
507+
height: 500
508+
})
509+
.then(function() { return _hover(200, 200); })
510+
.then(function(d) {
511+
var pt = d.points[0];
512+
513+
expect(pt.z).toBe(3, 'z');
514+
expect(pt.text).toBe(undefined, 'undefined text items are included');
515+
expect('id' in pt).toBe(false, 'undefined ids items are not included');
516+
expect('marker.colorbar.tickvals' in pt).toBe(false, 'marker.colorbar.tickvals');
517+
expect('marker.colorbar.ticktext' in pt).toBe(false, 'marker.colorbar.ticktext');
518+
})
519+
.catch(fail)
520+
.then(done);
521+
});
522+
});

test/jasmine/tests/gl_plot_interact_test.js

+14
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,20 @@ describe('Test gl3d plots', function() {
245245

246246
expect(label.size()).toEqual(1);
247247
expect(label.select('text').text()).toEqual('2');
248+
249+
return Plotly.restyle(gd, {
250+
'colorbar.tickvals': [[25]],
251+
'colorbar.ticktext': [['single tick!']]
252+
});
253+
})
254+
.then(_hover)
255+
.then(function() {
256+
assertEventData(1, 2, 43, 0, [1, 2], {
257+
'hoverinfo': 'y',
258+
'hoverlabel.font.color': 'cyan',
259+
'colorbar.tickvals': undefined,
260+
'colorbar.ticktext': undefined
261+
});
248262
})
249263
.then(done);
250264
});

0 commit comments

Comments
 (0)