UNPKG

@spalger/kibana

Version:

Kibana is an open source (Apache Licensed), browser based analytics and search dashboard for Elasticsearch. Kibana is a snap to setup and start using. Kibana strives to be easy to get started with, while also being flexible and powerful, just like Elastic

218 lines (184 loc) 6 kB
define(function (require) { return function HandlerBaseClass(Private) { var d3 = require('d3'); var _ = require('lodash'); var errors = require('ui/errors'); var Data = Private(require('ui/vislib/lib/data')); var Layout = Private(require('ui/vislib/lib/layout/layout')); var Legend = Private(require('ui/vislib/lib/legend')); /** * Handles building all the components of the visualization * * @class Handler * @constructor * @param vis {Object} Reference to the Vis Class Constructor * @param opts {Object} Reference to Visualization constructors needed to * create the visualization */ function Handler(vis, opts) { if (!(this instanceof Handler)) { return new Handler(vis, opts); } this.data = opts.data || new Data(vis.data, vis._attr); this.vis = vis; this.el = vis.el; this.ChartClass = vis.ChartClass; this.charts = []; this._attr = _.defaults(vis._attr || {}, { 'margin' : { top: 10, right: 3, bottom: 5, left: 3 } }); this.xAxis = opts.xAxis; this.yAxis = opts.yAxis; this.chartTitle = opts.chartTitle; this.axisTitle = opts.axisTitle; this.alerts = opts.alerts; if (this._attr.addLegend) { this.legend = opts.legend; } this.layout = new Layout(vis.el, vis.data, vis._attr.type, opts); this.renderArray = _.filter([ this.layout, this.legend, this.axisTitle, this.chartTitle, this.alerts, this.xAxis, this.yAxis, ], Boolean); // memoize so that the same function is returned every time, // allowing us to remove/re-add the same function this.getProxyHandler = _.memoize(function (event) { var self = this; return function (e) { self.vis.emit(event, e); }; }); } /** * Validates whether data is actually present in the data object * used to render the Vis. Throws a no results error if data is not * present. * * @private */ Handler.prototype._validateData = function () { var dataType = this.data.type; if (!dataType) { throw new errors.NoResults(); } }; /** * Renders the constructors that create the visualization, * including the chart constructor * * @method render * @returns {HTMLElement} With the visualization child element */ Handler.prototype.render = function () { var self = this; var charts = this.charts = []; var selection = d3.select(this.el); selection.selectAll('*').remove(); this._validateData(); this.renderArray.forEach(function (property) { if (property instanceof Legend) { self.vis.activeEvents().forEach(function (event) { self.enable(event, property); }); } if (typeof property.render === 'function') { property.render(); } }); // render the chart(s) selection.selectAll('.chart') .each(function (chartData) { var chart = new self.ChartClass(self, this, chartData); self.vis.activeEvents().forEach(function (event) { self.enable(event, chart); }); charts.push(chart); chart.render(); }); }; /** * Enables events, i.e. binds specific events to the chart * object(s) `on` method. For example, `click` or `mousedown` events. * * @method enable * @param event {String} Event type * @param chart {Object} Chart * @returns {*} */ Handler.prototype.enable = chartEventProxyToggle('on'); /** * Disables events for all charts * * @method disable * @param event {String} Event type * @param chart {Object} Chart * @returns {*} */ Handler.prototype.disable = chartEventProxyToggle('off'); function chartEventProxyToggle(method) { return function (event, chart) { var proxyHandler = this.getProxyHandler(event); _.each(chart ? [chart] : this.charts, function (chart) { chart.events[method](event, proxyHandler); }); }; } /** * Removes all DOM elements from the HTML element provided * * @method removeAll * @param el {HTMLElement} Reference to the HTML Element that * contains the chart * @returns {D3.Selection|D3.Transition.Transition} With the chart * child element removed */ Handler.prototype.removeAll = function (el) { return d3.select(el).selectAll('*').remove(); }; /** * Displays an error message in the DOM * * @method error * @param message {String} Error message to display * @returns {HTMLElement} Displays the input message */ Handler.prototype.error = function (message) { this.removeAll(this.el); var div = d3.select(this.el) .append('div') // class name needs `chart` in it for the polling checkSize function // to continuously call render on resize .attr('class', 'visualize-error chart error'); if (message === 'No results found') { div.append('div') .attr('class', 'text-center visualize-error visualize-chart ng-scope') .append('div').attr('class', 'item top') .append('div').attr('class', 'item') .append('h2').html('<i class="fa fa-meh-o"></i>') .append('h4').text(message); div.append('div').attr('class', 'item bottom'); return div; } return div.append('h4').text(message); }; /** * Destroys all the charts in the visualization * * @method destroy */ Handler.prototype.destroy = function () { this.charts.forEach(function (chart) { if (_.isFunction(chart.destroy)) { chart.destroy(); } }); this.charts.length = 0; }; return Handler; }; });