mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
added a dispatch class
This commit is contained in:
parent
1f2aaaaeab
commit
da0007388d
5 changed files with 223 additions and 110 deletions
98
src/kibana/components/vislib/lib/dispatch.js
Normal file
98
src/kibana/components/vislib/lib/dispatch.js
Normal file
|
@ -0,0 +1,98 @@
|
|||
define(function (require) {
|
||||
return function DispatchClass(d3, Private) {
|
||||
var _ = require('lodash');
|
||||
|
||||
/**
|
||||
* Events Class
|
||||
*/
|
||||
function Dispatch(vis, chartData) {
|
||||
if (!(this instanceof Dispatch)) {
|
||||
return new Dispatch(vis, chartData);
|
||||
}
|
||||
var type = vis._attr.type;
|
||||
|
||||
this.chartData = chartData;
|
||||
this.color = type === 'pie' ? vis.data.getPieColorFunc() : vis.data.getColorFunc();
|
||||
this._attr = _.defaults(vis._attr || {}, {
|
||||
yValue: function (d) {
|
||||
return d.y;
|
||||
},
|
||||
dispatch: d3.dispatch('brush', 'click', 'hover', 'mouseenter', 'mouseleave', 'mouseover', 'mouseout')
|
||||
});
|
||||
}
|
||||
|
||||
// Response to `click` and `hover` events
|
||||
Dispatch.prototype.eventResponse = function (d, i) {
|
||||
var label = d.label ? d.label : d.name;
|
||||
var getYValue = this._attr.yValue;
|
||||
var color = this.color;
|
||||
var chartData = this.chartData;
|
||||
var attr = this._attr;
|
||||
var vis = this.vis;
|
||||
|
||||
// Adding a look up for the field. Currently this relies on filtering the
|
||||
// data for the label then using that with the pointIndex to get the aggConfig.
|
||||
// It works for now... but we need something a little more robust. That will
|
||||
// come after the first beta. :)
|
||||
//
|
||||
// TODO: Replace the following code with something more robust for finding the field
|
||||
var field, series, aggConfig;
|
||||
if (d.label) {
|
||||
series = _.find(this.chartData.series, { label: d.label });
|
||||
aggConfig = _.last(series.values[i].aggConfigs);
|
||||
if (aggConfig.aggType.name === 'terms') {
|
||||
field = aggConfig.field.name;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
value : getYValue(d, i),
|
||||
point : d,
|
||||
label : label,
|
||||
color : color(label),
|
||||
pointIndex: i,
|
||||
series : chartData.series,
|
||||
config : attr,
|
||||
data : chartData,
|
||||
e : d3.event,
|
||||
field : field,
|
||||
aggConfig : aggConfig,
|
||||
vis : vis
|
||||
};
|
||||
};
|
||||
|
||||
// Add brush to the svg
|
||||
Dispatch.prototype.addBrush = function (xScale, svg) {
|
||||
var dispatch = this._attr.dispatch;
|
||||
var attr = this._attr;
|
||||
var chartData = this.chartData;
|
||||
var isBrush = this._attr.addBrushing;
|
||||
var height = this._attr.height;
|
||||
var margin = this._attr.margin;
|
||||
|
||||
// Brush scale
|
||||
var brush = d3.svg.brush()
|
||||
.x(xScale)
|
||||
.on('brushend', function brushEnd() {
|
||||
// response returned on brush
|
||||
return dispatch.brush({
|
||||
range: brush.extent(),
|
||||
config: attr,
|
||||
e: d3.event,
|
||||
data: chartData
|
||||
});
|
||||
});
|
||||
|
||||
// if `addBrushing` is true, add brush canvas
|
||||
if (isBrush) {
|
||||
return svg.append('g')
|
||||
.attr('class', 'brush')
|
||||
.call(brush)
|
||||
.selectAll('rect')
|
||||
.attr('height', height - margin.top - margin.bottom);
|
||||
}
|
||||
};
|
||||
|
||||
return Dispatch;
|
||||
};
|
||||
});
|
|
@ -3,6 +3,7 @@ define(function (require) {
|
|||
var _ = require('lodash');
|
||||
|
||||
var Legend = Private(require('components/vislib/lib/legend'));
|
||||
var Dispatch = Private(require('components/vislib/lib/dispatch'));
|
||||
|
||||
/*
|
||||
* Base Class for all visualizations.
|
||||
|
@ -16,6 +17,7 @@ define(function (require) {
|
|||
this.vis = vis;
|
||||
this.chartEl = el;
|
||||
this.chartData = chartData;
|
||||
this.events = new Dispatch(vis, chartData);
|
||||
this._attr = _.defaults(vis._attr || {}, {});
|
||||
}
|
||||
|
||||
|
|
|
@ -22,26 +22,10 @@ define(function (require) {
|
|||
// Column chart specific attributes
|
||||
this._attr = _.defaults(vis._attr || {}, {
|
||||
xValue: function (d, i) { return d.x; },
|
||||
yValue: function (d, i) { return d.y; },
|
||||
dispatch: d3.dispatch('brush', 'click', 'hover', 'mouseenter', 'mouseleave', 'mouseover', 'mouseout'),
|
||||
yValue: function (d, i) { return d.y; }
|
||||
});
|
||||
}
|
||||
|
||||
// Response to `click` and `hover` events
|
||||
ColumnChart.prototype.eventResponse = function (d, i) {
|
||||
return {
|
||||
value: this._attr.yValue(d, i),
|
||||
point: d,
|
||||
label: d.label,
|
||||
color: this.vis.data.getColorFunc()(d.label),
|
||||
pointIndex: i,
|
||||
series : this.chartData.series,
|
||||
config : this._attr,
|
||||
data : this.chartData,
|
||||
e : d3.event
|
||||
};
|
||||
};
|
||||
|
||||
// Stack data
|
||||
// TODO: refactor so that this is called from the data module
|
||||
ColumnChart.prototype.stackData = function (data) {
|
||||
|
@ -59,33 +43,6 @@ define(function (require) {
|
|||
}));
|
||||
};
|
||||
|
||||
// Add brush to the svg
|
||||
ColumnChart.prototype.addBrush = function (xScale, svg) {
|
||||
var self = this;
|
||||
|
||||
// Brush scale
|
||||
var brush = d3.svg.brush()
|
||||
.x(xScale)
|
||||
.on('brushend', function brushEnd() {
|
||||
// response returned on brush
|
||||
return self._attr.dispatch.brush({
|
||||
range: brush.extent(),
|
||||
config: self._attr,
|
||||
e: d3.event,
|
||||
data: self.chartData
|
||||
});
|
||||
});
|
||||
|
||||
// if `addBrushing` is true, add brush canvas
|
||||
if (self._attr.addBrushing) {
|
||||
svg.append('g')
|
||||
.attr('class', 'brush')
|
||||
.call(brush)
|
||||
.selectAll('rect')
|
||||
.attr('height', this._attr.height - this._attr.margin.top - this._attr.margin.bottom);
|
||||
}
|
||||
};
|
||||
|
||||
ColumnChart.prototype.addBars = function (svg, layers) {
|
||||
var data = this.chartData;
|
||||
var color = this.vis.data.getColorFunc();
|
||||
|
@ -124,56 +81,56 @@ define(function (require) {
|
|||
|
||||
// update
|
||||
bars
|
||||
.attr('x', function (d) {
|
||||
return xScale(d.x);
|
||||
})
|
||||
.attr('width', function () {
|
||||
var barWidth;
|
||||
var barSpacing;
|
||||
.attr('x', function (d) {
|
||||
return xScale(d.x);
|
||||
})
|
||||
.attr('width', function () {
|
||||
var barWidth;
|
||||
var barSpacing;
|
||||
|
||||
if (data.ordered && data.ordered.date) {
|
||||
barWidth = xScale(data.ordered.min + data.ordered.interval) - xScale(data.ordered.min);
|
||||
barSpacing = barWidth * 0.25;
|
||||
if (data.ordered && data.ordered.date) {
|
||||
barWidth = xScale(data.ordered.min + data.ordered.interval) - xScale(data.ordered.min);
|
||||
barSpacing = barWidth * 0.25;
|
||||
|
||||
return barWidth - barSpacing;
|
||||
}
|
||||
return barWidth - barSpacing;
|
||||
}
|
||||
|
||||
return xScale.rangeBand();
|
||||
})
|
||||
.attr('y', function (d) {
|
||||
return yScale(d.y0 + d.y);
|
||||
})
|
||||
.attr('height', function (d) {
|
||||
return yScale(d.y0) - yScale(d.y0 + d.y);
|
||||
});
|
||||
return xScale.rangeBand();
|
||||
})
|
||||
.attr('y', function (d) {
|
||||
return yScale(d.y0 + d.y);
|
||||
})
|
||||
.attr('height', function (d) {
|
||||
return yScale(d.y0) - yScale(d.y0 + d.y);
|
||||
});
|
||||
|
||||
return bars;
|
||||
};
|
||||
|
||||
ColumnChart.prototype.addBarEvents = function (bars) {
|
||||
var self = this;
|
||||
var events = this.events;
|
||||
var tooltip = this.vis.tooltip;
|
||||
var isTooltip = this._attr.addTooltip;
|
||||
var dispatch = this._attr.dispatch;
|
||||
var dispatch = this.events._attr.dispatch;
|
||||
|
||||
bars
|
||||
.on('mouseover.bar', function (d, i) {
|
||||
d3.select(this)
|
||||
.classed('hover', true)
|
||||
.style('stroke', '#333')
|
||||
.style('cursor', 'pointer');
|
||||
.on('mouseover.bar', function (d, i) {
|
||||
d3.select(this)
|
||||
.classed('hover', true)
|
||||
.style('stroke', '#333')
|
||||
.style('cursor', 'pointer');
|
||||
|
||||
dispatch.hover(self.eventResponse(d, i));
|
||||
d3.event.stopPropagation();
|
||||
})
|
||||
.on('click.bar', function (d, i) {
|
||||
dispatch.click(self.eventResponse(d, i));
|
||||
d3.event.stopPropagation();
|
||||
})
|
||||
.on('mouseout.bar', function () {
|
||||
d3.select(this).classed('hover', false)
|
||||
.style('stroke', null);
|
||||
});
|
||||
dispatch.hover(events.eventResponse(d, i));
|
||||
d3.event.stopPropagation();
|
||||
})
|
||||
.on('click.bar', function (d, i) {
|
||||
dispatch.click(events.eventResponse(d, i));
|
||||
d3.event.stopPropagation();
|
||||
})
|
||||
.on('mouseout.bar', function () {
|
||||
d3.select(this).classed('hover', false)
|
||||
.style('stroke', null);
|
||||
});
|
||||
|
||||
// Add tooltip
|
||||
if (isTooltip) {
|
||||
|
@ -222,7 +179,7 @@ define(function (require) {
|
|||
.attr('transform', 'translate(0,' + margin.top + ')');
|
||||
|
||||
// addBrush canvas
|
||||
self.addBrush(xScale, svg);
|
||||
self.events.addBrush(xScale, svg);
|
||||
|
||||
// add bars
|
||||
bars = self.addBars(svg, layers);
|
||||
|
|
|
@ -24,31 +24,11 @@ define(function (require) {
|
|||
});
|
||||
}
|
||||
|
||||
PieChart.prototype.eventResponse = function (d, i) {
|
||||
var getSize = this._attr.getSize;
|
||||
var color = this.vis.data.getPieColorFunc();
|
||||
var slices = this.chartData.slices;
|
||||
var config = this._attr;
|
||||
var chartData = this.chartData;
|
||||
|
||||
return {
|
||||
value: getSize(d, i),
|
||||
point: d,
|
||||
label: d.name,
|
||||
color: color(d.name),
|
||||
pointIndex: i,
|
||||
series: slices,
|
||||
config: config,
|
||||
data: chartData,
|
||||
e: d3.event
|
||||
};
|
||||
};
|
||||
|
||||
PieChart.prototype.addPathEvents = function (path) {
|
||||
var self = this;
|
||||
var events = this.events;
|
||||
var tooltip = this.vis.tooltip;
|
||||
var isTooltip = this._attr.addTooltip;
|
||||
var dispatch = this._attr.dispatch;
|
||||
var dispatch = this.events._attr.dispatch;
|
||||
|
||||
path
|
||||
.on('mouseover.pie', function mouseOverPie(d, i) {
|
||||
|
@ -56,11 +36,11 @@ define(function (require) {
|
|||
.classed('hover', true)
|
||||
.style('cursor', 'pointer');
|
||||
|
||||
dispatch.hover(self.eventResponse(d, i));
|
||||
dispatch.hover(events.eventResponse(d, i));
|
||||
d3.event.stopPropagation();
|
||||
})
|
||||
.on('click.pie', function clickPie(d, i) {
|
||||
dispatch.click(self.eventResponse(d, i));
|
||||
dispatch.click(events.eventResponse(d, i));
|
||||
d3.event.stopPropagation();
|
||||
})
|
||||
.on('mouseout.pie', function mouseOutPie() {
|
||||
|
|
|
@ -7,10 +7,77 @@ define(function (require) {
|
|||
describe('VisLib _chart Test Suite', function () {
|
||||
var ColumnChart;
|
||||
var Chart;
|
||||
var Data;
|
||||
var Vis;
|
||||
var chartData = {};
|
||||
var vis;
|
||||
var el;
|
||||
var myChart;
|
||||
var config;
|
||||
var data = {
|
||||
hits : 621,
|
||||
label : '',
|
||||
ordered : {
|
||||
date: true,
|
||||
interval: 30000,
|
||||
max : 1408734982458,
|
||||
min : 1408734082458
|
||||
},
|
||||
series : [
|
||||
{
|
||||
values: [
|
||||
{
|
||||
x: 1408734060000,
|
||||
y: 8
|
||||
},
|
||||
{
|
||||
x: 1408734090000,
|
||||
y: 23
|
||||
},
|
||||
{
|
||||
x: 1408734120000,
|
||||
y: 30
|
||||
},
|
||||
{
|
||||
x: 1408734150000,
|
||||
y: 28
|
||||
},
|
||||
{
|
||||
x: 1408734180000,
|
||||
y: 36
|
||||
},
|
||||
{
|
||||
x: 1408734210000,
|
||||
y: 30
|
||||
},
|
||||
{
|
||||
x: 1408734240000,
|
||||
y: 26
|
||||
},
|
||||
{
|
||||
x: 1408734270000,
|
||||
y: 22
|
||||
},
|
||||
{
|
||||
x: 1408734300000,
|
||||
y: 29
|
||||
},
|
||||
{
|
||||
x: 1408734330000,
|
||||
y: 24
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
tooltipFormatter: function (datapoint) {
|
||||
return datapoint;
|
||||
},
|
||||
xAxisFormatter: function (thing) {
|
||||
return thing;
|
||||
},
|
||||
xAxisLabel: 'Date Histogram',
|
||||
yAxisLabel: 'Count'
|
||||
};
|
||||
|
||||
beforeEach(function () {
|
||||
module('ChartBaseClass');
|
||||
|
@ -19,15 +86,24 @@ define(function (require) {
|
|||
|
||||
beforeEach(function () {
|
||||
inject(function (d3, Private) {
|
||||
Vis = Private(require('components/vislib/vis'));
|
||||
Data = Private(require('components/vislib/lib/data'));
|
||||
ColumnChart = Private(require('components/vislib/visualizations/column_chart'));
|
||||
Chart = Private(require('components/vislib/visualizations/_chart'));
|
||||
|
||||
el = d3.select('body').append('div').attr('class', 'column-chart');
|
||||
vis = {
|
||||
_attr: {
|
||||
stack: d3.layout.stack()
|
||||
}
|
||||
|
||||
config = {
|
||||
type: 'histogram',
|
||||
shareYAxis: true,
|
||||
addTooltip: true,
|
||||
addLegend: true,
|
||||
stack: d3.layout.stack(),
|
||||
};
|
||||
|
||||
vis = new Vis(el[0][0], config);
|
||||
vis.data = new Data(data, config);
|
||||
|
||||
myChart = new ColumnChart(vis, el, chartData);
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue