Skip to content

Commit

Permalink
feat(data): Pass element arg for data callbacks
Browse files Browse the repository at this point in the history
Pass current element argument to data.onover/out callbacks.

Fix #1100
  • Loading branch information
netil authored Nov 12, 2019
1 parent e0556b7 commit bb9f952
Show file tree
Hide file tree
Showing 6 changed files with 181 additions and 18 deletions.
108 changes: 108 additions & 0 deletions spec/interactions/interaction-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,114 @@ describe("INTERACTION", () => {
});

describe("Different interactions", () => {
describe("check for data.onover/out", () => {
let itemOver = [];
let itemOut = [];

const spyOver = sinon.spy((d, element) => itemOver.push({d, element}));
const spyOut = sinon.spy((d, element) => itemOut.push({d, element}));

before(() => {
args = {
data: {
columns: [
["data1", 300, 350, 300, 0, 0, 0],
["data2", 130, 100, 140, 200, 150, 50]
],
onover: spyOver,
onout: spyOut
}
};
});

afterEach(() => {
itemOver = [];
itemOut = [];
spyOver.resetHistory();
spyOut.resetHistory();
});

it("Callbacks were called correctly with its arguments?", done => {
setTimeout(() => {
const index = 1;
const rect = chart.$.main.select(`.${CLASS.eventRect}-${index}`).node();

util.fireEvent(rect, "mouseover", {
clientX: 174,
clientY: 200
}, chart);

util.fireEvent(rect, "mouseout", {
clientX: 0,
clientY: 0
}, chart);

expect(spyOver.calledTwice).to.be.true;
expect(spyOut.calledTwice).to.be.true;

itemOver.forEach((v, i) => {
expect(v.d.x).to.be.equal(index);
expect(v.element.tagName).to.be.equal("circle");

expect(itemOut[i].d).to.be.deep.equal(v.d);
expect(itemOut[i].element).to.be.deep.equal(v.element);
});

done();
}, 500);
});

it("set options data.groups / tooltip.grouped=false", () => {
args.data.groups = [["data1", "data2"]];
args.tooltip = {grouped: false};
args.point = {r:5};
});

it("Tooltip grouped false: Callbacks were called correctly with its arguments?", done => {
setTimeout(() => {
const index = 2;

util.hoverChart(chart, "mousemove", {clientX: 250, clientY: 311});
util.hoverChart(chart, "mouseout", {clientX: -100, clientY: -100});

expect(spyOver.calledOnce).to.be.true;
expect(spyOut.calledOnce).to.be.true;

itemOver.forEach((v, i) => {
expect(v.d.x).to.be.equal(index);
expect(v.element.tagName).to.be.equal("circle");

expect(itemOut[i].d).to.be.deep.equal(v.d);
expect(itemOut[i].element).to.be.deep.equal(v.element);
});

done();
}, 500);
});

it("Overlapped circles: Callbacks were called correctly with its arguments?", done => {
setTimeout(() => {
const index = 3;

util.hoverChart(chart, "mousemove", {clientX: 360, clientY: 266}, index);
util.hoverChart(chart, "mouseout", {clientX: -100, clientY: -100}, index);

expect(spyOver.calledTwice).to.be.true;
expect(spyOut.calledTwice).to.be.true;

itemOver.forEach((v, i) => {
expect(v.d.x).to.be.equal(index);
expect(v.element.tagName).to.be.equal("circle");

expect(itemOut[i].d).to.be.deep.equal(v.d);
expect(itemOut[i].element).to.be.deep.equal(v.element);
});

done();
}, 500);
});
});

describe("check for data.onclick", () => {
let clicked = false;
let data;
Expand Down
33 changes: 27 additions & 6 deletions src/config/Options.js
Original file line number Diff line number Diff line change
Expand Up @@ -872,42 +872,63 @@ export default class Options {

/**
* Set a callback for click event on each data point.<br><br>
* This callback will be called when each data point clicked and will receive d and element as the arguments. d is the data clicked and element is the element clicked. In this callback, this will be the Chart object.
* This callback will be called when each data point clicked and will receive `d` and element as the arguments.
* - `d` is the data clicked and element is the element clicked.
* - `element` is the current interacting svg element.
* - In this callback, `this` will be the Chart object.
* @name data․onclick
* @memberof Options
* @type {Function}
* @default function() {}
* @example
* data: {
* onclick: function(d, element) { ... }
* onclick: function(d, element) {
* // d - ex) {x: 4, value: 150, id: "data1", index: 4, name: "data1"}
* // element - <circle>
* ...
* }
* }
*/
data_onclick: () => {},

/**
* Set a callback for mouse/touch over event on each data point.<br><br>
* This callback will be called when mouse cursor or via touch moves onto each data point and will receive d as the argument. d is the data where mouse cursor moves onto. In this callback, this will be the Chart object.
* This callback will be called when mouse cursor or via touch moves onto each data point and will receive `d` and `element` as the argument.
* - `d` is the data where mouse cursor moves onto.
* - `element` is the current interacting svg element.
* - In this callback, `this` will be the Chart object.
* @name data․onover
* @memberof Options
* @type {Function}
* @default function() {}
* @example
* data: {
* onover: function(d) { ... }
* onover: function(d, element) {
* // d - ex) {x: 4, value: 150, id: "data1", index: 4}
* // element - <circle>
* ...
* }
* }
*/
data_onover: () => {},

/**
* Set a callback for mouse/touch out event on each data point.<br><br>
* This callback will be called when mouse cursor or via touch moves out each data point and will receive d as the argument. d is the data where mouse cursor moves out. In this callback, this will be the Chart object.
* This callback will be called when mouse cursor or via touch moves out each data point and will receive `d` as the argument.
* - `d` is the data where mouse cursor moves out.
* - `element` is the current interacting svg element.
* - In this callback, `this` will be the Chart object.
* @name data․onout
* @memberof Options
* @type {Function}
* @default function() {}
* @example
* data: {
* onout: function(d) { ... }
* onout: function(d, element) {
* // d - ex) {x: 4, value: 150, id: "data1", index: 4}
* // element - <circle>
* ...
* }
* }
*/
data_onout: () => {},
Expand Down
43 changes: 39 additions & 4 deletions src/interactions/interaction.js
Original file line number Diff line number Diff line change
Expand Up @@ -411,15 +411,44 @@ extend(ChartInternal.prototype, {

// Call event handler
if (isArc || d !== -1) {
const callback = config[isOver ? "data_onover" : "data_onout"].bind($$.api);
let callback = config[isOver ? "data_onover" : "data_onout"].bind($$.api);

config.color_onover && $$.setOverColor(isOver, d, isArc);

if (isArc) {
callback(d);
callback(d, $$.main.select(`.${CLASS.arc}-${d.id}`).node());
} else if (!config.tooltip_grouped) {
const callee = $$.setOverOut;
let last = callee.last || [];

const shape = $$.main.selectAll(`.${CLASS.shape}-${d}`)
.filter(function(d) {
return $$.isWithinShape(this, d);
});

shape
.each(function(d) {
if (last.length === 0 || last.every(v => v !== this)) {
callback(d, this);
last.push(this);
}
});

if (last.length > 0 && shape.empty()) {
callback = config.data_onout.bind($$.api);

last.forEach(v => callback(d3Select(v).datum(), v));
last = [];
}

callee.last = last;
} else {
isOver && $$.expandCirclesBars(d, null, true);
!$$.isMultipleX() && $$.main.selectAll(`.${CLASS.shape}-${d}`).each(callback);

!$$.isMultipleX() && $$.main.selectAll(`.${CLASS.shape}-${d}`)
.each(function(d) {
callback(d, this);
});
}
}
},
Expand Down Expand Up @@ -485,7 +514,7 @@ extend(ChartInternal.prototype, {
return;
}

$$.setOverOut(true, d.index);
$$.config.tooltip_grouped && $$.setOverOut(true, d.index);
})
.on("mousemove", function(d) {
// do nothing while dragging/flowing
Expand All @@ -505,6 +534,12 @@ extend(ChartInternal.prototype, {

index === -1 ?
$$.unselectRect() : $$.selectRectForSingle(this, eventRect, index);

// As of individual data point(or <path>) element can't bind mouseover/out event
// to determine current interacting element, so use 'mousemove' event instead.
if (!$$.config.tooltip_grouped) {
$$.setOverOut(index !== -1, d.index);
}
})
.on("mouseout", d => {
// chart is destroyed
Expand Down
4 changes: 1 addition & 3 deletions src/shape/line.js
Original file line number Diff line number Diff line change
Expand Up @@ -700,11 +700,9 @@ extend(ChartInternal.prototype, {
cy = y;
}

const is = Math.sqrt(
return Math.sqrt(
Math.pow(cx - mouse[0], 2) + Math.pow(cy - mouse[1], 2)
) < (r || this.config.point_sensitivity);

return is;
},

isWithinStep(that, y) {
Expand Down
10 changes: 5 additions & 5 deletions types/options.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1355,31 +1355,31 @@ export interface Data {
* This callback will be called when each data point clicked and will receive d and element as the arguments.
* - d is the data clicked and element is the element clicked. In this callback, this will be the Chart object.
*/
onclick?(d: DataItem, element: any): void;
onclick?(d: DataItem, element: SVGElement): void;

/**
* Set a callback for mouse/touch over event on each data point.
* This callback will be called when mouse cursor or via touch moves onto each data point and will receive d as the argument.
* - d is the data where mouse cursor moves onto. In this callback, this will be the Chart object.
*/
onover?(d: DataItem, element?: any): void;
onover?(d: DataItem, element?: SVGElement): void;

/**
* Set a callback for mouse/touch event on each data point.
* This callback will be called when mouse cursor moves out each data point and will receive d as the argument.
* - d is the data where mouse cursor moves out. In this callback, this will be the Chart object.
*/
onout?(d: DataItem, element?: any): void;
onout?(d: DataItem, element?: SVGElement): void;

/**
* Set a callback for on data selection.
*/
onselected?(d: DataItem, element?: any): void;
onselected?(d: DataItem, element?: SVGElement): void;

/**
* Set a callback for on data un-selection.
*/
onunselected?(d: DataItem, element?: any): void;
onunselected?(d: DataItem, element?: SVGElement): void;

/**
* Set a callback for minimum data
Expand Down
1 change: 1 addition & 0 deletions types/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export interface DataItem {
index: number;
value: number;
x: number;
name?: string;
ratio?: number;
}

Expand Down

0 comments on commit bb9f952

Please sign in to comment.