kibana-123
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
203 lines (174 loc) • 5.47 kB
JavaScript
import _ from 'lodash';
import d3 from 'd3';
import Binder from 'ui/binder';
import errors from 'ui/errors';
import EventsProvider from 'ui/events';
import './styles/main.less';
import VislibLibResizeCheckerProvider from './lib/resize_checker';
import VisConifgProvider from './lib/vis_config';
import VisHandlerProvider from './lib/handler';
export default function VisFactory(Private) {
const ResizeChecker = Private(VislibLibResizeCheckerProvider);
const Events = Private(EventsProvider);
const VisConfig = Private(VisConifgProvider);
const Handler = Private(VisHandlerProvider);
/**
* Creates the visualizations.
*
* @class Vis
* @constructor
* @param $el {HTMLElement} jQuery selected HTML element
* @param config {Object} Parameters that define the chart type and chart options
*/
class Vis extends Events {
constructor($el, visConfigArgs) {
super(arguments);
this.el = $el.get ? $el.get(0) : $el;
this.binder = new Binder();
this.visConfigArgs = _.cloneDeep(visConfigArgs);
// bind the resize function so it can be used as an event handler
this.resize = _.bind(this.resize, this);
this.resizeChecker = new ResizeChecker(this.el);
this.binder.on(this.resizeChecker, 'resize', this.resize);
}
hasLegend() {
return this.visConfigArgs.addLegend;
}
/**
* Renders the visualization
*
* @method render
* @param data {Object} Elasticsearch query results
*/
render(data, uiState) {
if (!data) {
throw new Error('No valid data!');
}
if (this.handler) {
this.data = null;
this._runOnHandler('destroy');
}
this.data = data;
if (!this.uiState) {
this.uiState = uiState;
this._uiStateChangeHandler = () => {
if (document.body.contains(this.el)) {
this.render(this.data, this.uiState);
}
};
uiState.on('change', this._uiStateChangeHandler);
}
this.visConfig = new VisConfig(this.visConfigArgs, this.data, this.uiState, this.el);
this.handler = new Handler(this, this.visConfig);
this._runWithoutResizeChecker('render');
};
getLegendLabels() {
return this.visConfig ? this.visConfig.get('legend.labels', null) : null;
}
getLegendColors() {
return this.visConfig ? this.visConfig.get('legend.colors', null) : null;
}
/**
* Resizes the visualization
*
* @method resize
*/
resize() {
if (!this.data) {
return;
}
if (this.handler && _.isFunction(this.handler.resize)) {
this._runOnHandler('resize');
} else {
this.render(this.data, this.uiState);
}
};
_runWithoutResizeChecker(method) {
this.resizeChecker.stopSchedule();
this._runOnHandler(method);
this.resizeChecker.saveSize();
this.resizeChecker.saveDirty(false);
this.resizeChecker.continueSchedule();
};
_runOnHandler(method) {
try {
this.handler[method]();
} catch (error) {
if (error instanceof errors.KbnError) {
error.displayToScreen(this.handler);
} else {
throw error;
}
}
};
/**
* Destroys the visualization
* Removes chart and all elements associated with it.
* Removes chart and all elements associated with it.
* Remove event listeners and pass destroy call down to owned objects.
*
* @method destroy
*/
destroy() {
const selection = d3.select(this.el).select('.vis-wrapper');
this.binder.destroy();
this.resizeChecker.destroy();
if (this.uiState) this.uiState.off('change', this._uiStateChangeHandler);
if (this.handler) this._runOnHandler('destroy');
selection.remove();
};
/**
* Sets attributes on the visualization
*
* @method set
* @param name {String} An attribute name
* @param val {*} Value to which the attribute name is set
*/
set(name, val) {
this.visConfigArgs[name] = val;
this.render(this.data, this.uiState);
};
/**
* Gets attributes from the visualization
*
* @method get
* @param name {String} An attribute name
* @returns {*} The value of the attribute name
*/
get(name) {
return this.visConfig.get(name);
};
/**
* Turns on event listeners.
*
* @param event {String}
* @param listener{Function}
* @returns {*}
*/
on(event, listener) {
const first = this.listenerCount(event) === 0;
const ret = Events.prototype.on.call(this, event, listener);
const added = this.listenerCount(event) > 0;
// if this is the first listener added for the event
// enable the event in the handler
if (first && added && this.handler) this.handler.enable(event);
return ret;
};
/**
* Turns off event listeners.
*
* @param event {String}
* @param listener{Function}
* @returns {*}
*/
off(event, listener) {
const last = this.listenerCount(event) === 1;
const ret = Events.prototype.off.call(this, event, listener);
const removed = this.listenerCount(event) === 0;
// Once all listeners are removed, disable the events in the handler
if (last && removed && this.handler) this.handler.disable(event);
return ret;
};
}
return Vis;
};