Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changes the way Events are handled in the Visualization Library #1773

Merged
merged 22 commits into from
Nov 3, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
b9ed2e5
almost there
stormpython Oct 22, 2014
8eb1696
troubleshooting
stormpython Oct 22, 2014
f345ebd
troubleshooting
stormpython Oct 22, 2014
8bd26e5
more changes, experimenting
stormpython Oct 22, 2014
0b67b78
working thru the issues
stormpython Oct 24, 2014
16d4f39
Merge branch 'master' into feature/fix_events
stormpython Oct 24, 2014
0bc4caf
reorganizing dispatch events class
stormpython Oct 24, 2014
58d83b8
adding more comments
stormpython Oct 27, 2014
fa13df2
Merge branch 'master' into feature/fix_events
stormpython Oct 28, 2014
5cf67cf
making changes to get pie charts working
stormpython Oct 28, 2014
3e19605
Merge branch 'feature/fix_1658' into feature/fix_events
stormpython Oct 28, 2014
31a9b4a
Merge branch 'fix_1720' into feature/fix_events
stormpython Oct 28, 2014
a150ef5
fixing area chart and line chart
stormpython Oct 28, 2014
aaec62c
Merge branch 'master' into feature/fix_events
stormpython Oct 28, 2014
0372e81
restructured the less and css files into separate files which are imp…
stormpython Oct 30, 2014
95635f8
fixing issue where brush svg was being appended twice
stormpython Oct 30, 2014
afeb314
Merge branch 'master' into feature/fix_events
stormpython Oct 30, 2014
adcd177
adding tests for the on and off methods to vis.js
stormpython Oct 30, 2014
b1be135
adding tests for handler.enable and handler.disable methods
stormpython Oct 30, 2014
0b3199a
commenting out render method testing in handler, needs refactoring
stormpython Oct 30, 2014
12a5035
Merge branch 'master' into feature/fix_events
stormpython Nov 3, 2014
6f6e2a8
fixing conflict due to merge with master in legend.js
stormpython Nov 3, 2014
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions src/kibana/components/vislib/lib/data.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ define(function (require) {
}

this.data = data;
this.type = this.getDataType();
this.labels = (this.type === 'series') ? getLabels(data) : this.pieNames();
this.color = color(this.labels);
this._normalizeOrdered();

this._attr = _.defaults(attr || {}, {
Expand All @@ -46,6 +49,21 @@ define(function (require) {
});
}

Data.prototype.getDataType = function () {
var data = this.getVisData();
var type;

data.forEach(function (obj) {
if (obj.series) {
type = 'series';
} else if (obj.slices) {
type = 'slices';
}
});

return type;
};

/**
* Returns an array of the actual x and y data value objects
* from data with series keys
Expand Down
198 changes: 134 additions & 64 deletions src/kibana/components/vislib/lib/dispatch.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,44 +8,42 @@ define(function (require) {
* @class Dispatch
* @constructor
* @param handler {Object} Reference to Handler Class Object
* @param chartData {Object} Elasticsearch data object
*/

function Dispatch(handler, chartData) {
function Dispatch(handler) {
if (!(this instanceof Dispatch)) {
return new Dispatch(handler, chartData);
return new Dispatch(handler);
}
var type = handler._attr.type;

this.handler = handler;
this.chartData = chartData;
this.color = type === 'pie' ? handler.data.getPieColorFunc() : handler.data.getColorFunc();
this._attr = _.defaults(handler._attr || {}, {
yValue: function (d) { return d.y; },
dispatch: d3.dispatch('brush', 'click', 'hover', 'mouseenter', 'mouseleave', 'mouseover', 'mouseout')
});
this.dispatch = d3.dispatch('brush', 'click', 'hover', 'mouseup',
'mousedown', 'mouseover');
}

/**
* Response to click and hover events
*
* @param d {Object} Data point
* @param i {Number} Index number of data point
* @returns {{value: *, point: *, label: *, color: *, pointIndex: *, series: *, config: *, data: (Object|*),
* @returns {{value: *, point: *, label: *, color: *, pointIndex: *,
* series: *, config: *, data: (Object|*),
* e: (d3.event|*), handler: (Object|*)}} Event response object
*/
Dispatch.prototype.eventResponse = function (d, i) {
var isPercentage = (this._attr.mode === 'percentage');
var label = d.label;
var getYValue = this._attr.yValue;
var color = this.color;
var chartData = this.chartData;
var attr = this._attr;
var data = d3.event.target.nearestViewportElement.__data__;
var label = d.label ? d.label : d.name;
var isSeries = !!(data.series);
var isSlices = !!(data.slices);
var series = isSeries ? data.series : undefined;
var slices = isSlices ? data.slices : undefined;
var handler = this.handler;
var color = handler.data.color;
var isPercentage = (handler._attr.mode === 'percentage');

if (isSeries) {

if (chartData.series) {
// Find object with the actual d value and add it to the point object
var object = _.find(chartData.series, { 'label': label });
var object = _.find(series, { 'label': d.label });
d.value = +object.values[i].y;

if (isPercentage) {
Expand All @@ -56,88 +54,160 @@ define(function (require) {
}

return {
value: getYValue(d, i),
value: d.y,
point: d,
label: label,
color: color(label),
pointIndex: i,
series: chartData.series,
config: attr,
data: chartData,
series: series,
slices: slices,
config: handler._attr,
data: data,
e: d3.event,
handler: handler
};
};

/**
* Response to click and hover events for pie charts
* Returns a function that adds events and listeners to a D3 selection
*
* @param d {Object} Data point
* @param i {Number} Index number of data point
* @returns {{value: (d.value|*), point: *, label: (d.name|*), color: *, pointIndex: *, children: *, parent: *,
* appConfig: *, config: *, data: (Object|*), e: (d3.event|*), handler: (Object|*)}} Event response object
* @method addEvent
* @param event {String}
* @param callback {Function}
* @returns {Function}
*/
Dispatch.prototype.pieResponse = function (d, i) {
var label = d.name;
var color = this.color;
var chartData = this.chartData;
var attr = this._attr;
var handler = this.handler;
Dispatch.prototype.addEvent = function (event, callback) {
return function (selection) {
selection.each(function () {
var element = d3.select(this);

return {
value: d.value,
point: d,
label: label,
color: color(label),
pointIndex: i,
children: d.children ? d.children : undefined,
parent: d.parent ? d.parent : undefined,
appConfig: d.appConfig,
config: attr,
data: chartData,
e: d3.event,
handler: handler
if (typeof callback === 'function') {
return element.on(event, callback);
}
});
};
};

/**
*
* @method addHoverEvent
* @returns {Function}
*/
Dispatch.prototype.addHoverEvent = function () {
var self = this;
var isClickable = (this.dispatch.on('click'));
var addEvent = this.addEvent;

function hover(d, i) {
d3.event.stopPropagation();

// Add pointer if item is clickable
if (isClickable) {
self.addMousePointer.call(this, arguments);
}

self.dispatch.hover.call(this, self.eventResponse(d, i));
}

return addEvent('mouseover', hover);
};

/**
*
* @method addClickEvent
* @returns {Function}
*/
Dispatch.prototype.addClickEvent = function () {
var self = this;
var addEvent = this.addEvent;

function click(d, i) {
d3.event.stopPropagation();
self.dispatch.click.call(this, self.eventResponse(d, i));
}

return addEvent('click', click);
};

/**
*
* @param svg
* @returns {Function}
*/
Dispatch.prototype.addBrushEvent = function (svg) {
var dispatch = this.dispatch;
var xScale = this.handler.xAxis.xScale;
var isBrushable = (dispatch.on('brush'));
var brush = this.createBrush(xScale, svg);
var addEvent = this.addEvent;

function brushEnd() {
var bar = d3.select(this);
var startX = d3.mouse(svg.node());
var startXInv = xScale.invert(startX[0]);

// Reset the brush value
brush.extent([startXInv, startXInv]);

// Magic!
// Need to call brush on svg to see brush when brushing
// while on top of bars.
// Need to call brush on bar to allow the click event to be registered
svg.call(brush);
bar.call(brush);
}

if (isBrushable) {
return addEvent('mousedown', brushEnd);
}
};


/**
* Mouse over Behavior
*
* @method addMousePointer
* @returns {D3.Selection}
*/
Dispatch.prototype.addMousePointer = function () {
return d3.select(this).style('cursor', 'pointer');
};

/**
* Adds D3 brush to SVG and returns the brush function
*
* @param xScale {Function} D3 xScale function
* @param svg {HTMLElement} Reference to SVG
* @returns {*} Returns a D3 brush function and a SVG with a brush group attached
*/
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;
Dispatch.prototype.createBrush = function (xScale, svg) {
var dispatch = this.dispatch;
var attr = this.handler._attr;
var height = attr.height;
var margin = 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
data: d3.event.sourceEvent.target.__data__
});
});

// if `addBrushing` is true, add brush canvas
if (isBrush) {
svg.append('g')
.attr('class', 'brush')
.call(brush)
.selectAll('rect')
.attr('height', height - margin.top - margin.bottom);
}
if (dispatch.on('brush')) {
svg.insert('g', 'g')
.attr('class', 'brush')
.call(brush)
.selectAll('rect')
.attr('height', height - margin.top - margin.bottom);

return brush;
return brush;
}
};

return Dispatch;
Expand Down
Loading