initial commit
This commit is contained in:
179
node_modules/vis/lib/graph3d/Camera.js
generated
vendored
Normal file
179
node_modules/vis/lib/graph3d/Camera.js
generated
vendored
Normal file
@@ -0,0 +1,179 @@
|
||||
var Point3d = require('./Point3d');
|
||||
|
||||
/**
|
||||
* The camera is mounted on a (virtual) camera arm. The camera arm can rotate
|
||||
* The camera is always looking in the direction of the origin of the arm.
|
||||
* This way, the camera always rotates around one fixed point, the location
|
||||
* of the camera arm.
|
||||
*
|
||||
* Documentation:
|
||||
* http://en.wikipedia.org/wiki/3D_projection
|
||||
* @class Camera
|
||||
*/
|
||||
function Camera() {
|
||||
this.armLocation = new Point3d();
|
||||
this.armRotation = {};
|
||||
this.armRotation.horizontal = 0;
|
||||
this.armRotation.vertical = 0;
|
||||
this.armLength = 1.7;
|
||||
this.cameraOffset = new Point3d();
|
||||
this.offsetMultiplier = 0.6;
|
||||
|
||||
this.cameraLocation = new Point3d();
|
||||
this.cameraRotation = new Point3d(0.5*Math.PI, 0, 0);
|
||||
|
||||
this.calculateCameraOrientation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set offset camera in camera coordinates
|
||||
* @param {number} x offset by camera horisontal
|
||||
* @param {number} y offset by camera vertical
|
||||
*/
|
||||
Camera.prototype.setOffset = function(x, y) {
|
||||
var abs = Math.abs,
|
||||
sign = Math.sign,
|
||||
mul = this.offsetMultiplier,
|
||||
border = this.armLength * mul;
|
||||
|
||||
if (abs(x) > border) {
|
||||
x = sign(x) * border;
|
||||
}
|
||||
if (abs(y) > border) {
|
||||
y = sign(y) * border;
|
||||
}
|
||||
this.cameraOffset.x = x;
|
||||
this.cameraOffset.y = y;
|
||||
this.calculateCameraOrientation();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get camera offset by horizontal and vertical
|
||||
* @returns {number}
|
||||
*/
|
||||
Camera.prototype.getOffset = function() {
|
||||
return this.cameraOffset;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the location (origin) of the arm
|
||||
* @param {number} x Normalized value of x
|
||||
* @param {number} y Normalized value of y
|
||||
* @param {number} z Normalized value of z
|
||||
*/
|
||||
Camera.prototype.setArmLocation = function(x, y, z) {
|
||||
this.armLocation.x = x;
|
||||
this.armLocation.y = y;
|
||||
this.armLocation.z = z;
|
||||
|
||||
this.calculateCameraOrientation();
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the rotation of the camera arm
|
||||
* @param {number} horizontal The horizontal rotation, between 0 and 2*PI.
|
||||
* Optional, can be left undefined.
|
||||
* @param {number} vertical The vertical rotation, between 0 and 0.5*PI
|
||||
* if vertical=0.5*PI, the graph is shown from the
|
||||
* top. Optional, can be left undefined.
|
||||
*/
|
||||
Camera.prototype.setArmRotation = function(horizontal, vertical) {
|
||||
if (horizontal !== undefined) {
|
||||
this.armRotation.horizontal = horizontal;
|
||||
}
|
||||
|
||||
if (vertical !== undefined) {
|
||||
this.armRotation.vertical = vertical;
|
||||
if (this.armRotation.vertical < 0) this.armRotation.vertical = 0;
|
||||
if (this.armRotation.vertical > 0.5*Math.PI) this.armRotation.vertical = 0.5*Math.PI;
|
||||
}
|
||||
|
||||
if (horizontal !== undefined || vertical !== undefined) {
|
||||
this.calculateCameraOrientation();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve the current arm rotation
|
||||
* @return {object} An object with parameters horizontal and vertical
|
||||
*/
|
||||
Camera.prototype.getArmRotation = function() {
|
||||
var rot = {};
|
||||
rot.horizontal = this.armRotation.horizontal;
|
||||
rot.vertical = this.armRotation.vertical;
|
||||
|
||||
return rot;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the (normalized) length of the camera arm.
|
||||
* @param {number} length A length between 0.71 and 5.0
|
||||
*/
|
||||
Camera.prototype.setArmLength = function(length) {
|
||||
if (length === undefined)
|
||||
return;
|
||||
|
||||
this.armLength = length;
|
||||
|
||||
// Radius must be larger than the corner of the graph,
|
||||
// which has a distance of sqrt(0.5^2+0.5^2) = 0.71 from the center of the
|
||||
// graph
|
||||
if (this.armLength < 0.71) this.armLength = 0.71;
|
||||
if (this.armLength > 5.0) this.armLength = 5.0;
|
||||
|
||||
this.setOffset(this.cameraOffset.x, this.cameraOffset.y);
|
||||
this.calculateCameraOrientation();
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve the arm length
|
||||
* @return {number} length
|
||||
*/
|
||||
Camera.prototype.getArmLength = function() {
|
||||
return this.armLength;
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve the camera location
|
||||
* @return {Point3d} cameraLocation
|
||||
*/
|
||||
Camera.prototype.getCameraLocation = function() {
|
||||
return this.cameraLocation;
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve the camera rotation
|
||||
* @return {Point3d} cameraRotation
|
||||
*/
|
||||
Camera.prototype.getCameraRotation = function() {
|
||||
return this.cameraRotation;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculate the location and rotation of the camera based on the
|
||||
* position and orientation of the camera arm
|
||||
*/
|
||||
Camera.prototype.calculateCameraOrientation = function() {
|
||||
// calculate location of the camera
|
||||
this.cameraLocation.x = this.armLocation.x - this.armLength * Math.sin(this.armRotation.horizontal) * Math.cos(this.armRotation.vertical);
|
||||
this.cameraLocation.y = this.armLocation.y - this.armLength * Math.cos(this.armRotation.horizontal) * Math.cos(this.armRotation.vertical);
|
||||
this.cameraLocation.z = this.armLocation.z + this.armLength * Math.sin(this.armRotation.vertical);
|
||||
|
||||
// calculate rotation of the camera
|
||||
this.cameraRotation.x = Math.PI/2 - this.armRotation.vertical;
|
||||
this.cameraRotation.y = 0;
|
||||
this.cameraRotation.z = -this.armRotation.horizontal;
|
||||
|
||||
var xa = this.cameraRotation.x;
|
||||
var za = this.cameraRotation.z;
|
||||
var dx = this.cameraOffset.x;
|
||||
var dy = this.cameraOffset.y;
|
||||
var sin = Math.sin, cos = Math.cos;
|
||||
|
||||
this.cameraLocation.x = this.cameraLocation.x + dx * cos(za) + dy * - sin(za) * cos(xa);
|
||||
this.cameraLocation.y = this.cameraLocation.y + dx * sin(za) + dy * cos(za) * cos(xa);
|
||||
this.cameraLocation.z = this.cameraLocation.z + dy * sin(xa);
|
||||
};
|
||||
|
||||
module.exports = Camera;
|
||||
504
node_modules/vis/lib/graph3d/DataGroup.js
generated
vendored
Normal file
504
node_modules/vis/lib/graph3d/DataGroup.js
generated
vendored
Normal file
@@ -0,0 +1,504 @@
|
||||
var DataSet = require('../DataSet');
|
||||
var DataView = require('../DataView');
|
||||
var Range = require('./Range');
|
||||
var Filter = require('./Filter');
|
||||
var Settings = require('./Settings');
|
||||
var Point3d = require('./Point3d');
|
||||
|
||||
|
||||
/**
|
||||
* Creates a container for all data of one specific 3D-graph.
|
||||
*
|
||||
* On construction, the container is totally empty; the data
|
||||
* needs to be initialized with method initializeData().
|
||||
* Failure to do so will result in the following exception begin thrown
|
||||
* on instantiation of Graph3D:
|
||||
*
|
||||
* Error: Array, DataSet, or DataView expected
|
||||
*
|
||||
* @constructor DataGroup
|
||||
*/
|
||||
function DataGroup() {
|
||||
this.dataTable = null; // The original data table
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initializes the instance from the passed data.
|
||||
*
|
||||
* Calculates minimum and maximum values and column index values.
|
||||
*
|
||||
* The graph3d instance is used internally to access the settings for
|
||||
* the given instance.
|
||||
* TODO: Pass settings only instead.
|
||||
*
|
||||
* @param {vis.Graph3d} graph3d Reference to the calling Graph3D instance.
|
||||
* @param {Array | DataSet | DataView} rawData The data containing the items for
|
||||
* the Graph.
|
||||
* @param {number} style Style Number
|
||||
* @returns {Array.<Object>}
|
||||
*/
|
||||
DataGroup.prototype.initializeData = function(graph3d, rawData, style) {
|
||||
if (rawData === undefined) return;
|
||||
|
||||
if (Array.isArray(rawData)) {
|
||||
rawData = new DataSet(rawData);
|
||||
}
|
||||
|
||||
var data;
|
||||
if (rawData instanceof DataSet || rawData instanceof DataView) {
|
||||
data = rawData.get();
|
||||
}
|
||||
else {
|
||||
throw new Error('Array, DataSet, or DataView expected');
|
||||
}
|
||||
|
||||
if (data.length == 0) return;
|
||||
|
||||
this.style = style;
|
||||
|
||||
// unsubscribe from the dataTable
|
||||
if (this.dataSet) {
|
||||
this.dataSet.off('*', this._onChange);
|
||||
}
|
||||
|
||||
this.dataSet = rawData;
|
||||
this.dataTable = data;
|
||||
|
||||
// subscribe to changes in the dataset
|
||||
var me = this;
|
||||
this._onChange = function () {
|
||||
graph3d.setData(me.dataSet);
|
||||
};
|
||||
this.dataSet.on('*', this._onChange);
|
||||
|
||||
// determine the location of x,y,z,value,filter columns
|
||||
this.colX = 'x';
|
||||
this.colY = 'y';
|
||||
this.colZ = 'z';
|
||||
|
||||
|
||||
var withBars = graph3d.hasBars(style);
|
||||
|
||||
// determine barWidth from data
|
||||
if (withBars) {
|
||||
if (graph3d.defaultXBarWidth !== undefined) {
|
||||
this.xBarWidth = graph3d.defaultXBarWidth;
|
||||
}
|
||||
else {
|
||||
this.xBarWidth = this.getSmallestDifference(data, this.colX) || 1;
|
||||
}
|
||||
|
||||
if (graph3d.defaultYBarWidth !== undefined) {
|
||||
this.yBarWidth = graph3d.defaultYBarWidth;
|
||||
}
|
||||
else {
|
||||
this.yBarWidth = this.getSmallestDifference(data, this.colY) || 1;
|
||||
}
|
||||
}
|
||||
|
||||
// calculate minima and maxima
|
||||
this._initializeRange(data, this.colX, graph3d, withBars);
|
||||
this._initializeRange(data, this.colY, graph3d, withBars);
|
||||
this._initializeRange(data, this.colZ, graph3d, false);
|
||||
|
||||
if (data[0].hasOwnProperty('style')) {
|
||||
this.colValue = 'style';
|
||||
var valueRange = this.getColumnRange(data, this.colValue);
|
||||
this._setRangeDefaults(valueRange, graph3d.defaultValueMin, graph3d.defaultValueMax);
|
||||
this.valueRange = valueRange;
|
||||
}
|
||||
|
||||
// Initialize data filter if a filter column is provided
|
||||
var table = this.getDataTable();
|
||||
if (table[0].hasOwnProperty('filter')) {
|
||||
if (this.dataFilter === undefined) {
|
||||
this.dataFilter = new Filter(this, 'filter', graph3d);
|
||||
this.dataFilter.setOnLoadCallback(function() { graph3d.redraw(); });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var dataPoints;
|
||||
if (this.dataFilter) {
|
||||
// apply filtering
|
||||
dataPoints = this.dataFilter._getDataPoints();
|
||||
}
|
||||
else {
|
||||
// no filtering. load all data
|
||||
dataPoints = this._getDataPoints(this.getDataTable());
|
||||
}
|
||||
return dataPoints;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Collect the range settings for the given data column.
|
||||
*
|
||||
* This internal method is intended to make the range
|
||||
* initalization more generic.
|
||||
*
|
||||
* TODO: if/when combined settings per axis defined, get rid of this.
|
||||
*
|
||||
* @private
|
||||
*
|
||||
* @param {'x'|'y'|'z'} column The data column to process
|
||||
* @param {vis.Graph3d} graph3d Reference to the calling Graph3D instance;
|
||||
* required for access to settings
|
||||
* @returns {Object}
|
||||
*/
|
||||
DataGroup.prototype._collectRangeSettings = function(column, graph3d) {
|
||||
var index = ['x', 'y', 'z'].indexOf(column);
|
||||
|
||||
if (index == -1) {
|
||||
throw new Error('Column \'' + column + '\' invalid');
|
||||
}
|
||||
|
||||
var upper = column.toUpperCase();
|
||||
|
||||
return {
|
||||
barWidth : this[column + 'BarWidth'],
|
||||
min : graph3d['default' + upper + 'Min'],
|
||||
max : graph3d['default' + upper + 'Max'],
|
||||
step : graph3d['default' + upper + 'Step'],
|
||||
range_label: column + 'Range', // Name of instance field to write to
|
||||
step_label : column + 'Step' // Name of instance field to write to
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Initializes the settings per given column.
|
||||
*
|
||||
* TODO: if/when combined settings per axis defined, rewrite this.
|
||||
*
|
||||
* @private
|
||||
*
|
||||
* @param {DataSet | DataView} data The data containing the items for the Graph
|
||||
* @param {'x'|'y'|'z'} column The data column to process
|
||||
* @param {vis.Graph3d} graph3d Reference to the calling Graph3D instance;
|
||||
* required for access to settings
|
||||
* @param {boolean} withBars True if initializing for bar graph
|
||||
*/
|
||||
DataGroup.prototype._initializeRange = function(data, column, graph3d, withBars) {
|
||||
var NUMSTEPS = 5;
|
||||
var settings = this._collectRangeSettings(column, graph3d);
|
||||
|
||||
var range = this.getColumnRange(data, column);
|
||||
if (withBars && column != 'z') { // Safeguard for 'z'; it doesn't have a bar width
|
||||
range.expand(settings.barWidth / 2);
|
||||
}
|
||||
|
||||
this._setRangeDefaults(range, settings.min, settings.max);
|
||||
this[settings.range_label] = range;
|
||||
this[settings.step_label ] = (settings.step !== undefined) ? settings.step : range.range()/NUMSTEPS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a list with all the different values in the data for the given column.
|
||||
*
|
||||
* If no data passed, use the internal data of this instance.
|
||||
*
|
||||
* @param {'x'|'y'|'z'} column The data column to process
|
||||
* @param {DataSet|DataView|undefined} data The data containing the items for the Graph
|
||||
*
|
||||
* @returns {Array} All distinct values in the given column data, sorted ascending.
|
||||
*/
|
||||
DataGroup.prototype.getDistinctValues = function(column, data) {
|
||||
if (data === undefined) {
|
||||
data = this.dataTable;
|
||||
}
|
||||
|
||||
var values = [];
|
||||
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
var value = data[i][column] || 0;
|
||||
if (values.indexOf(value) === -1) {
|
||||
values.push(value);
|
||||
}
|
||||
}
|
||||
|
||||
return values.sort(function(a,b) { return a - b; });
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Determine the smallest difference between the values for given
|
||||
* column in the passed data set.
|
||||
*
|
||||
* @param {DataSet|DataView|undefined} data The data containing the items for the Graph
|
||||
* @param {'x'|'y'|'z'} column The data column to process
|
||||
*
|
||||
* @returns {number|null} Smallest difference value or
|
||||
* null, if it can't be determined.
|
||||
*/
|
||||
DataGroup.prototype.getSmallestDifference = function(data, column) {
|
||||
var values = this.getDistinctValues(data, column);
|
||||
|
||||
// Get all the distinct diffs
|
||||
// Array values is assumed to be sorted here
|
||||
var smallest_diff = null;
|
||||
|
||||
for (var i = 1; i < values.length; i++) {
|
||||
var diff = values[i] - values[i - 1];
|
||||
|
||||
if (smallest_diff == null || smallest_diff > diff ) {
|
||||
smallest_diff = diff;
|
||||
}
|
||||
}
|
||||
|
||||
return smallest_diff;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the absolute min/max values for the passed data column.
|
||||
*
|
||||
* @param {DataSet|DataView|undefined} data The data containing the items for the Graph
|
||||
* @param {'x'|'y'|'z'} column The data column to process
|
||||
*
|
||||
* @returns {Range} A Range instance with min/max members properly set.
|
||||
*/
|
||||
DataGroup.prototype.getColumnRange = function(data, column) {
|
||||
var range = new Range();
|
||||
|
||||
// Adjust the range so that it covers all values in the passed data elements.
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
var item = data[i][column];
|
||||
range.adjust(item);
|
||||
}
|
||||
|
||||
return range;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Determines the number of rows in the current data.
|
||||
*
|
||||
* @returns {number}
|
||||
*/
|
||||
DataGroup.prototype.getNumberOfRows = function() {
|
||||
return this.dataTable.length;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set default values for range
|
||||
*
|
||||
* The default values override the range values, if defined.
|
||||
*
|
||||
* Because it's possible that only defaultMin or defaultMax is set, it's better
|
||||
* to pass in a range already set with the min/max set from the data. Otherwise,
|
||||
* it's quite hard to process the min/max properly.
|
||||
*
|
||||
* @param {vis.Range} range
|
||||
* @param {number} [defaultMin=range.min]
|
||||
* @param {number} [defaultMax=range.max]
|
||||
* @private
|
||||
*/
|
||||
DataGroup.prototype._setRangeDefaults = function (range, defaultMin, defaultMax) {
|
||||
if (defaultMin !== undefined) {
|
||||
range.min = defaultMin;
|
||||
}
|
||||
|
||||
if (defaultMax !== undefined) {
|
||||
range.max = defaultMax;
|
||||
}
|
||||
|
||||
// This is the original way that the default min/max values were adjusted.
|
||||
// TODO: Perhaps it's better if an error is thrown if the values do not agree.
|
||||
// But this will change the behaviour.
|
||||
if (range.max <= range.min) range.max = range.min + 1;
|
||||
};
|
||||
|
||||
|
||||
DataGroup.prototype.getDataTable = function() {
|
||||
return this.dataTable;
|
||||
};
|
||||
|
||||
|
||||
DataGroup.prototype.getDataSet = function() {
|
||||
return this.dataSet;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return all data values as a list of Point3d objects
|
||||
* @param {Array.<Object>} data
|
||||
* @returns {Array.<Object>}
|
||||
*/
|
||||
DataGroup.prototype.getDataPoints = function(data) {
|
||||
var dataPoints = [];
|
||||
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
var point = new Point3d();
|
||||
point.x = data[i][this.colX] || 0;
|
||||
point.y = data[i][this.colY] || 0;
|
||||
point.z = data[i][this.colZ] || 0;
|
||||
point.data = data[i];
|
||||
|
||||
if (this.colValue !== undefined) {
|
||||
point.value = data[i][this.colValue] || 0;
|
||||
}
|
||||
|
||||
var obj = {};
|
||||
obj.point = point;
|
||||
obj.bottom = new Point3d(point.x, point.y, this.zRange.min);
|
||||
obj.trans = undefined;
|
||||
obj.screen = undefined;
|
||||
|
||||
dataPoints.push(obj);
|
||||
}
|
||||
|
||||
return dataPoints;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Copy all values from the data table to a matrix.
|
||||
*
|
||||
* The provided values are supposed to form a grid of (x,y) positions.
|
||||
* @param {Array.<Object>} data
|
||||
* @returns {Array.<Object>}
|
||||
* @private
|
||||
*/
|
||||
DataGroup.prototype.initDataAsMatrix = function(data) {
|
||||
// TODO: store the created matrix dataPoints in the filters instead of
|
||||
// reloading each time.
|
||||
var x, y, i, obj;
|
||||
|
||||
// create two lists with all present x and y values
|
||||
var dataX = this.getDistinctValues(this.colX, data);
|
||||
var dataY = this.getDistinctValues(this.colY, data);
|
||||
|
||||
var dataPoints = this.getDataPoints(data);
|
||||
|
||||
// create a grid, a 2d matrix, with all values.
|
||||
var dataMatrix = []; // temporary data matrix
|
||||
for (i = 0; i < dataPoints.length; i++) {
|
||||
obj = dataPoints[i];
|
||||
|
||||
// TODO: implement Array().indexOf() for Internet Explorer
|
||||
var xIndex = dataX.indexOf(obj.point.x);
|
||||
var yIndex = dataY.indexOf(obj.point.y);
|
||||
|
||||
if (dataMatrix[xIndex] === undefined) {
|
||||
dataMatrix[xIndex] = [];
|
||||
}
|
||||
|
||||
dataMatrix[xIndex][yIndex] = obj;
|
||||
}
|
||||
|
||||
// fill in the pointers to the neighbors.
|
||||
for (x = 0; x < dataMatrix.length; x++) {
|
||||
for (y = 0; y < dataMatrix[x].length; y++) {
|
||||
if (dataMatrix[x][y]) {
|
||||
dataMatrix[x][y].pointRight = (x < dataMatrix.length-1) ? dataMatrix[x+1][y] : undefined;
|
||||
dataMatrix[x][y].pointTop = (y < dataMatrix[x].length-1) ? dataMatrix[x][y+1] : undefined;
|
||||
dataMatrix[x][y].pointCross =
|
||||
(x < dataMatrix.length-1 && y < dataMatrix[x].length-1) ?
|
||||
dataMatrix[x+1][y+1] :
|
||||
undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dataPoints;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return common information, if present
|
||||
*
|
||||
* @returns {string}
|
||||
*/
|
||||
DataGroup.prototype.getInfo = function() {
|
||||
var dataFilter = this.dataFilter;
|
||||
if (!dataFilter) return undefined;
|
||||
|
||||
return dataFilter.getLabel() + ': ' + dataFilter.getSelectedValue();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Reload the data
|
||||
*/
|
||||
DataGroup.prototype.reload = function() {
|
||||
if (this.dataTable) {
|
||||
this.setData(this.dataTable);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Filter the data based on the current filter
|
||||
*
|
||||
* @param {Array} data
|
||||
* @returns {Array} dataPoints Array with point objects which can be drawn on
|
||||
* screen
|
||||
*/
|
||||
DataGroup.prototype._getDataPoints = function (data) {
|
||||
var dataPoints = [];
|
||||
|
||||
if (this.style === Settings.STYLE.GRID || this.style === Settings.STYLE.SURFACE) {
|
||||
dataPoints = this.initDataAsMatrix(data);
|
||||
}
|
||||
else { // 'dot', 'dot-line', etc.
|
||||
this._checkValueField(data);
|
||||
dataPoints = this.getDataPoints(data);
|
||||
|
||||
if (this.style === Settings.STYLE.LINE) {
|
||||
// Add next member points for line drawing
|
||||
for (var i = 0; i < dataPoints.length; i++) {
|
||||
if (i > 0) {
|
||||
dataPoints[i - 1].pointNext = dataPoints[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dataPoints;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Check if the state is consistent for the use of the value field.
|
||||
*
|
||||
* Throws if a problem is detected.
|
||||
*
|
||||
* @param {Array.<Object>} data
|
||||
* @private
|
||||
*/
|
||||
DataGroup.prototype._checkValueField = function (data) {
|
||||
|
||||
var hasValueField = this.style === Settings.STYLE.BARCOLOR
|
||||
|| this.style === Settings.STYLE.BARSIZE
|
||||
|| this.style === Settings.STYLE.DOTCOLOR
|
||||
|| this.style === Settings.STYLE.DOTSIZE;
|
||||
|
||||
if (!hasValueField) {
|
||||
return; // No need to check further
|
||||
}
|
||||
|
||||
|
||||
// Following field must be present for the current graph style
|
||||
if (this.colValue === undefined) {
|
||||
throw new Error('Expected data to have '
|
||||
+ ' field \'style\' '
|
||||
+ ' for graph style \'' + this.style + '\''
|
||||
);
|
||||
}
|
||||
|
||||
// The data must also contain this field.
|
||||
// Note that only first data element is checked.
|
||||
if (data[0][this.colValue] === undefined) {
|
||||
throw new Error('Expected data to have '
|
||||
+ ' field \'' + this.colValue + '\' '
|
||||
+ ' for graph style \'' + this.style + '\''
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
module.exports = DataGroup;
|
||||
214
node_modules/vis/lib/graph3d/Filter.js
generated
vendored
Normal file
214
node_modules/vis/lib/graph3d/Filter.js
generated
vendored
Normal file
@@ -0,0 +1,214 @@
|
||||
var DataView = require('../DataView');
|
||||
|
||||
/**
|
||||
* @class Filter
|
||||
*
|
||||
* @param {DataGroup} dataGroup the data group
|
||||
* @param {number} column The index of the column to be filtered
|
||||
* @param {Graph3d} graph The graph
|
||||
*/
|
||||
function Filter (dataGroup, column, graph) {
|
||||
this.dataGroup = dataGroup;
|
||||
this.column = column;
|
||||
this.graph = graph; // the parent graph
|
||||
|
||||
this.index = undefined;
|
||||
this.value = undefined;
|
||||
|
||||
// read all distinct values and select the first one
|
||||
this.values = dataGroup.getDistinctValues(this.column);
|
||||
|
||||
if (this.values.length > 0) {
|
||||
this.selectValue(0);
|
||||
}
|
||||
|
||||
// create an array with the filtered datapoints. this will be loaded afterwards
|
||||
this.dataPoints = [];
|
||||
|
||||
this.loaded = false;
|
||||
this.onLoadCallback = undefined;
|
||||
|
||||
if (graph.animationPreload) {
|
||||
this.loaded = false;
|
||||
this.loadInBackground();
|
||||
}
|
||||
else {
|
||||
this.loaded = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the label
|
||||
* @return {string} label
|
||||
*/
|
||||
Filter.prototype.isLoaded = function() {
|
||||
return this.loaded;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return the loaded progress
|
||||
* @return {number} percentage between 0 and 100
|
||||
*/
|
||||
Filter.prototype.getLoadedProgress = function() {
|
||||
var len = this.values.length;
|
||||
|
||||
var i = 0;
|
||||
while (this.dataPoints[i]) {
|
||||
i++;
|
||||
}
|
||||
|
||||
return Math.round(i / len * 100);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return the label
|
||||
* @return {string} label
|
||||
*/
|
||||
Filter.prototype.getLabel = function() {
|
||||
return this.graph.filterLabel;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return the columnIndex of the filter
|
||||
* @return {number} columnIndex
|
||||
*/
|
||||
Filter.prototype.getColumn = function() {
|
||||
return this.column;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the currently selected value. Returns undefined if there is no selection
|
||||
* @return {*} value
|
||||
*/
|
||||
Filter.prototype.getSelectedValue = function() {
|
||||
if (this.index === undefined)
|
||||
return undefined;
|
||||
|
||||
return this.values[this.index];
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve all values of the filter
|
||||
* @return {Array} values
|
||||
*/
|
||||
Filter.prototype.getValues = function() {
|
||||
return this.values;
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve one value of the filter
|
||||
* @param {number} index
|
||||
* @return {*} value
|
||||
*/
|
||||
Filter.prototype.getValue = function(index) {
|
||||
if (index >= this.values.length)
|
||||
throw new Error('Index out of range');
|
||||
|
||||
return this.values[index];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve the (filtered) dataPoints for the currently selected filter index
|
||||
* @param {number} [index] (optional)
|
||||
* @return {Array} dataPoints
|
||||
*/
|
||||
Filter.prototype._getDataPoints = function(index) {
|
||||
if (index === undefined)
|
||||
index = this.index;
|
||||
|
||||
if (index === undefined)
|
||||
return [];
|
||||
|
||||
var dataPoints;
|
||||
if (this.dataPoints[index]) {
|
||||
dataPoints = this.dataPoints[index];
|
||||
}
|
||||
else {
|
||||
var f = {};
|
||||
f.column = this.column;
|
||||
f.value = this.values[index];
|
||||
|
||||
var dataView = new DataView(this.dataGroup.getDataSet(), {filter: function (item) {return (item[f.column] == f.value);}}).get();
|
||||
dataPoints = this.dataGroup._getDataPoints(dataView);
|
||||
|
||||
this.dataPoints[index] = dataPoints;
|
||||
}
|
||||
|
||||
return dataPoints;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set a callback function when the filter is fully loaded.
|
||||
*
|
||||
* @param {function} callback
|
||||
*/
|
||||
Filter.prototype.setOnLoadCallback = function(callback) {
|
||||
this.onLoadCallback = callback;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Add a value to the list with available values for this filter
|
||||
* No double entries will be created.
|
||||
* @param {number} index
|
||||
*/
|
||||
Filter.prototype.selectValue = function(index) {
|
||||
if (index >= this.values.length)
|
||||
throw new Error('Index out of range');
|
||||
|
||||
this.index = index;
|
||||
this.value = this.values[index];
|
||||
};
|
||||
|
||||
/**
|
||||
* Load all filtered rows in the background one by one
|
||||
* Start this method without providing an index!
|
||||
*
|
||||
* @param {number} [index=0]
|
||||
*/
|
||||
Filter.prototype.loadInBackground = function(index) {
|
||||
if (index === undefined)
|
||||
index = 0;
|
||||
|
||||
var frame = this.graph.frame;
|
||||
|
||||
if (index < this.values.length) {
|
||||
// create a progress box
|
||||
if (frame.progress === undefined) {
|
||||
frame.progress = document.createElement('DIV');
|
||||
frame.progress.style.position = 'absolute';
|
||||
frame.progress.style.color = 'gray';
|
||||
frame.appendChild(frame.progress);
|
||||
}
|
||||
var progress = this.getLoadedProgress();
|
||||
frame.progress.innerHTML = 'Loading animation... ' + progress + '%';
|
||||
// TODO: this is no nice solution...
|
||||
frame.progress.style.bottom = 60 + 'px'; // TODO: use height of slider
|
||||
frame.progress.style.left = 10 + 'px';
|
||||
|
||||
var me = this;
|
||||
setTimeout(function() {me.loadInBackground(index+1);}, 10);
|
||||
this.loaded = false;
|
||||
}
|
||||
else {
|
||||
this.loaded = true;
|
||||
|
||||
// remove the progress box
|
||||
if (frame.progress !== undefined) {
|
||||
frame.removeChild(frame.progress);
|
||||
frame.progress = undefined;
|
||||
}
|
||||
|
||||
if (this.onLoadCallback)
|
||||
this.onLoadCallback();
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = Filter;
|
||||
2399
node_modules/vis/lib/graph3d/Graph3d.js
generated
vendored
Normal file
2399
node_modules/vis/lib/graph3d/Graph3d.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
11
node_modules/vis/lib/graph3d/Point2d.js
generated
vendored
Normal file
11
node_modules/vis/lib/graph3d/Point2d.js
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* @prototype Point2d
|
||||
* @param {number} [x]
|
||||
* @param {number} [y]
|
||||
*/
|
||||
function Point2d (x, y) {
|
||||
this.x = x !== undefined ? x : 0;
|
||||
this.y = y !== undefined ? y : 0;
|
||||
}
|
||||
|
||||
module.exports = Point2d;
|
||||
85
node_modules/vis/lib/graph3d/Point3d.js
generated
vendored
Normal file
85
node_modules/vis/lib/graph3d/Point3d.js
generated
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
/**
|
||||
* @prototype Point3d
|
||||
* @param {number} [x]
|
||||
* @param {number} [y]
|
||||
* @param {number} [z]
|
||||
*/
|
||||
function Point3d(x, y, z) {
|
||||
this.x = x !== undefined ? x : 0;
|
||||
this.y = y !== undefined ? y : 0;
|
||||
this.z = z !== undefined ? z : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subtract the two provided points, returns a-b
|
||||
* @param {Point3d} a
|
||||
* @param {Point3d} b
|
||||
* @return {Point3d} a-b
|
||||
*/
|
||||
Point3d.subtract = function(a, b) {
|
||||
var sub = new Point3d();
|
||||
sub.x = a.x - b.x;
|
||||
sub.y = a.y - b.y;
|
||||
sub.z = a.z - b.z;
|
||||
return sub;
|
||||
};
|
||||
|
||||
/**
|
||||
* Add the two provided points, returns a+b
|
||||
* @param {Point3d} a
|
||||
* @param {Point3d} b
|
||||
* @return {Point3d} a+b
|
||||
*/
|
||||
Point3d.add = function(a, b) {
|
||||
var sum = new Point3d();
|
||||
sum.x = a.x + b.x;
|
||||
sum.y = a.y + b.y;
|
||||
sum.z = a.z + b.z;
|
||||
return sum;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculate the average of two 3d points
|
||||
* @param {Point3d} a
|
||||
* @param {Point3d} b
|
||||
* @return {Point3d} The average, (a+b)/2
|
||||
*/
|
||||
Point3d.avg = function(a, b) {
|
||||
return new Point3d(
|
||||
(a.x + b.x) / 2,
|
||||
(a.y + b.y) / 2,
|
||||
(a.z + b.z) / 2
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculate the cross product of the two provided points, returns axb
|
||||
* Documentation: http://en.wikipedia.org/wiki/Cross_product
|
||||
* @param {Point3d} a
|
||||
* @param {Point3d} b
|
||||
* @return {Point3d} cross product axb
|
||||
*/
|
||||
Point3d.crossProduct = function(a, b) {
|
||||
var crossproduct = new Point3d();
|
||||
|
||||
crossproduct.x = a.y * b.z - a.z * b.y;
|
||||
crossproduct.y = a.z * b.x - a.x * b.z;
|
||||
crossproduct.z = a.x * b.y - a.y * b.x;
|
||||
|
||||
return crossproduct;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Rtrieve the length of the vector (or the distance from this point to the origin
|
||||
* @return {number} length
|
||||
*/
|
||||
Point3d.prototype.length = function() {
|
||||
return Math.sqrt(
|
||||
this.x * this.x +
|
||||
this.y * this.y +
|
||||
this.z * this.z
|
||||
);
|
||||
};
|
||||
|
||||
module.exports = Point3d;
|
||||
97
node_modules/vis/lib/graph3d/Range.js
generated
vendored
Normal file
97
node_modules/vis/lib/graph3d/Range.js
generated
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
/**
|
||||
* @prototype Range
|
||||
*
|
||||
* Helper class to make working with related min and max values easier.
|
||||
*
|
||||
* The range is inclusive; a given value is considered part of the range if:
|
||||
*
|
||||
* this.min <= value <= this.max
|
||||
*/
|
||||
function Range() {
|
||||
this.min = undefined;
|
||||
this.max = undefined;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adjust the range so that the passed value fits in it.
|
||||
*
|
||||
* If the value is outside of the current extremes, adjust
|
||||
* the min or max so that the value is within the range.
|
||||
*
|
||||
* @param {number} value Numeric value to fit in range
|
||||
*/
|
||||
Range.prototype.adjust = function(value) {
|
||||
if (value === undefined) return;
|
||||
|
||||
if (this.min === undefined || this.min > value ) {
|
||||
this.min = value;
|
||||
}
|
||||
|
||||
if (this.max === undefined || this.max < value) {
|
||||
this.max = value;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Adjust the current range so that the passed range fits in it.
|
||||
*
|
||||
* @param {Range} range Range instance to fit in current instance
|
||||
*/
|
||||
Range.prototype.combine = function(range) {
|
||||
this.add(range.min);
|
||||
this.add(range.max);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Expand the range by the given value
|
||||
*
|
||||
* min will be lowered by given value;
|
||||
* max will be raised by given value
|
||||
*
|
||||
* Shrinking by passing a negative value is allowed.
|
||||
*
|
||||
* @param {number} val Amount by which to expand or shrink current range with
|
||||
*/
|
||||
Range.prototype.expand = function(val) {
|
||||
if (val === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
var newMin = this.min - val;
|
||||
var newMax = this.max + val;
|
||||
|
||||
// Note that following allows newMin === newMax.
|
||||
// This should be OK, since method expand() allows this also.
|
||||
if (newMin > newMax) {
|
||||
throw new Error('Passed expansion value makes range invalid');
|
||||
}
|
||||
|
||||
this.min = newMin;
|
||||
this.max = newMax;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Determine the full range width of current instance.
|
||||
*
|
||||
* @returns {num} The calculated width of this range
|
||||
*/
|
||||
Range.prototype.range = function() {
|
||||
return this.max - this.min;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Determine the central point of current instance.
|
||||
*
|
||||
* @returns {number} the value in the middle of min and max
|
||||
*/
|
||||
Range.prototype.center = function() {
|
||||
return (this.min + this.max) / 2;
|
||||
};
|
||||
|
||||
|
||||
module.exports = Range;
|
||||
487
node_modules/vis/lib/graph3d/Settings.js
generated
vendored
Normal file
487
node_modules/vis/lib/graph3d/Settings.js
generated
vendored
Normal file
@@ -0,0 +1,487 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// This modules handles the options for Graph3d.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
var util = require('../util');
|
||||
var Camera = require('./Camera');
|
||||
var Point3d = require('./Point3d');
|
||||
|
||||
|
||||
// enumerate the available styles
|
||||
var STYLE = {
|
||||
BAR : 0,
|
||||
BARCOLOR: 1,
|
||||
BARSIZE : 2,
|
||||
DOT : 3,
|
||||
DOTLINE : 4,
|
||||
DOTCOLOR: 5,
|
||||
DOTSIZE : 6,
|
||||
GRID : 7,
|
||||
LINE : 8,
|
||||
SURFACE : 9
|
||||
};
|
||||
|
||||
|
||||
// The string representations of the styles
|
||||
var STYLENAME = {
|
||||
'dot' : STYLE.DOT,
|
||||
'dot-line' : STYLE.DOTLINE,
|
||||
'dot-color': STYLE.DOTCOLOR,
|
||||
'dot-size' : STYLE.DOTSIZE,
|
||||
'line' : STYLE.LINE,
|
||||
'grid' : STYLE.GRID,
|
||||
'surface' : STYLE.SURFACE,
|
||||
'bar' : STYLE.BAR,
|
||||
'bar-color': STYLE.BARCOLOR,
|
||||
'bar-size' : STYLE.BARSIZE
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Field names in the options hash which are of relevance to the user.
|
||||
*
|
||||
* Specifically, these are the fields which require no special handling,
|
||||
* and can be directly copied over.
|
||||
*/
|
||||
var OPTIONKEYS = [
|
||||
'width',
|
||||
'height',
|
||||
'filterLabel',
|
||||
'legendLabel',
|
||||
'xLabel',
|
||||
'yLabel',
|
||||
'zLabel',
|
||||
'xValueLabel',
|
||||
'yValueLabel',
|
||||
'zValueLabel',
|
||||
'showXAxis',
|
||||
'showYAxis',
|
||||
'showZAxis',
|
||||
'showGrid',
|
||||
'showPerspective',
|
||||
'showShadow',
|
||||
'keepAspectRatio',
|
||||
'verticalRatio',
|
||||
'dotSizeRatio',
|
||||
'dotSizeMinFraction',
|
||||
'dotSizeMaxFraction',
|
||||
'showAnimationControls',
|
||||
'animationInterval',
|
||||
'animationPreload',
|
||||
'animationAutoStart',
|
||||
'axisColor',
|
||||
'gridColor',
|
||||
'xCenter',
|
||||
'yCenter',
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* Field names in the options hash which are of relevance to the user.
|
||||
*
|
||||
* Same as OPTIONKEYS, but internally these fields are stored with
|
||||
* prefix 'default' in the name.
|
||||
*/
|
||||
var PREFIXEDOPTIONKEYS = [
|
||||
'xBarWidth',
|
||||
'yBarWidth',
|
||||
'valueMin',
|
||||
'valueMax',
|
||||
'xMin',
|
||||
'xMax',
|
||||
'xStep',
|
||||
'yMin',
|
||||
'yMax',
|
||||
'yStep',
|
||||
'zMin',
|
||||
'zMax',
|
||||
'zStep'
|
||||
];
|
||||
|
||||
|
||||
// Placeholder for DEFAULTS reference
|
||||
var DEFAULTS = undefined;
|
||||
|
||||
|
||||
/**
|
||||
* Check if given hash is empty.
|
||||
*
|
||||
* Source: http://stackoverflow.com/a/679937
|
||||
*
|
||||
* @param {object} obj
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function isEmpty(obj) {
|
||||
for(var prop in obj) {
|
||||
if (obj.hasOwnProperty(prop))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Make first letter of parameter upper case.
|
||||
*
|
||||
* Source: http://stackoverflow.com/a/1026087
|
||||
*
|
||||
* @param {string} str
|
||||
* @returns {string}
|
||||
*/
|
||||
function capitalize(str) {
|
||||
if (str === undefined || str === "" || typeof str != "string") {
|
||||
return str;
|
||||
}
|
||||
|
||||
return str.charAt(0).toUpperCase() + str.slice(1);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add a prefix to a field name, taking style guide into account
|
||||
*
|
||||
* @param {string} prefix
|
||||
* @param {string} fieldName
|
||||
* @returns {string}
|
||||
*/
|
||||
function prefixFieldName(prefix, fieldName) {
|
||||
if (prefix === undefined || prefix === "") {
|
||||
return fieldName;
|
||||
}
|
||||
|
||||
return prefix + capitalize(fieldName);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Forcibly copy fields from src to dst in a controlled manner.
|
||||
*
|
||||
* A given field in dst will always be overwitten. If this field
|
||||
* is undefined or not present in src, the field in dst will
|
||||
* be explicitly set to undefined.
|
||||
*
|
||||
* The intention here is to be able to reset all option fields.
|
||||
*
|
||||
* Only the fields mentioned in array 'fields' will be handled.
|
||||
*
|
||||
* @param {object} src
|
||||
* @param {object} dst
|
||||
* @param {array<string>} fields array with names of fields to copy
|
||||
* @param {string} [prefix] prefix to use for the target fields.
|
||||
*/
|
||||
function forceCopy(src, dst, fields, prefix) {
|
||||
var srcKey;
|
||||
var dstKey;
|
||||
|
||||
for (var i = 0; i < fields.length; ++i) {
|
||||
srcKey = fields[i];
|
||||
dstKey = prefixFieldName(prefix, srcKey);
|
||||
|
||||
dst[dstKey] = src[srcKey];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Copy fields from src to dst in a safe and controlled manner.
|
||||
*
|
||||
* Only the fields mentioned in array 'fields' will be copied over,
|
||||
* and only if these are actually defined.
|
||||
*
|
||||
* @param {object} src
|
||||
* @param {object} dst
|
||||
* @param {array<string>} fields array with names of fields to copy
|
||||
* @param {string} [prefix] prefix to use for the target fields.
|
||||
*/
|
||||
function safeCopy(src, dst, fields, prefix) {
|
||||
var srcKey;
|
||||
var dstKey;
|
||||
|
||||
for (var i = 0; i < fields.length; ++i) {
|
||||
srcKey = fields[i];
|
||||
if (src[srcKey] === undefined) continue;
|
||||
|
||||
dstKey = prefixFieldName(prefix, srcKey);
|
||||
|
||||
dst[dstKey] = src[srcKey];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize dst with the values in src.
|
||||
*
|
||||
* src is the hash with the default values.
|
||||
* A reference DEFAULTS to this hash is stored locally for
|
||||
* further handling.
|
||||
*
|
||||
* For now, dst is assumed to be a Graph3d instance.
|
||||
* @param {object} src
|
||||
* @param {object} dst
|
||||
*/
|
||||
function setDefaults(src, dst) {
|
||||
if (src === undefined || isEmpty(src)) {
|
||||
throw new Error('No DEFAULTS passed');
|
||||
}
|
||||
if (dst === undefined) {
|
||||
throw new Error('No dst passed');
|
||||
}
|
||||
|
||||
// Remember defaults for future reference
|
||||
DEFAULTS = src;
|
||||
|
||||
// Handle the defaults which can be simply copied over
|
||||
forceCopy(src, dst, OPTIONKEYS);
|
||||
forceCopy(src, dst, PREFIXEDOPTIONKEYS, 'default');
|
||||
|
||||
// Handle the more complex ('special') fields
|
||||
setSpecialSettings(src, dst);
|
||||
|
||||
// Following are internal fields, not part of the user settings
|
||||
dst.margin = 10; // px
|
||||
dst.showGrayBottom = false; // TODO: this does not work correctly
|
||||
dst.showTooltip = false;
|
||||
dst.onclick_callback = null;
|
||||
dst.eye = new Point3d(0, 0, -1); // TODO: set eye.z about 3/4 of the width of the window?
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {object} options
|
||||
* @param {object} dst
|
||||
*/
|
||||
function setOptions(options, dst) {
|
||||
if (options === undefined) {
|
||||
return;
|
||||
}
|
||||
if (dst === undefined) {
|
||||
throw new Error('No dst passed');
|
||||
}
|
||||
|
||||
if (DEFAULTS === undefined || isEmpty(DEFAULTS)) {
|
||||
throw new Error('DEFAULTS not set for module Settings');
|
||||
}
|
||||
|
||||
// Handle the parameters which can be simply copied over
|
||||
safeCopy(options, dst, OPTIONKEYS);
|
||||
safeCopy(options, dst, PREFIXEDOPTIONKEYS, 'default');
|
||||
|
||||
// Handle the more complex ('special') fields
|
||||
setSpecialSettings(options, dst);
|
||||
}
|
||||
|
||||
/**
|
||||
* Special handling for certain parameters
|
||||
*
|
||||
* 'Special' here means: setting requires more than a simple copy
|
||||
*
|
||||
* @param {object} src
|
||||
* @param {object} dst
|
||||
*/
|
||||
function setSpecialSettings(src, dst) {
|
||||
if (src.backgroundColor !== undefined) {
|
||||
setBackgroundColor(src.backgroundColor, dst);
|
||||
}
|
||||
|
||||
setDataColor(src.dataColor, dst);
|
||||
setStyle(src.style, dst);
|
||||
setShowLegend(src.showLegend, dst);
|
||||
setCameraPosition(src.cameraPosition, dst);
|
||||
|
||||
// As special fields go, this is an easy one; just a translation of the name.
|
||||
// Can't use this.tooltip directly, because that field exists internally
|
||||
if (src.tooltip !== undefined) {
|
||||
dst.showTooltip = src.tooltip;
|
||||
}
|
||||
if (src.onclick != undefined) {
|
||||
dst.onclick_callback = src.onclick;
|
||||
}
|
||||
|
||||
if (src.tooltipStyle !== undefined) {
|
||||
util.selectiveDeepExtend(['tooltipStyle'], dst, src);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the value of setting 'showLegend'
|
||||
*
|
||||
* This depends on the value of the style fields, so it must be called
|
||||
* after the style field has been initialized.
|
||||
*
|
||||
* @param {boolean} showLegend
|
||||
* @param {object} dst
|
||||
*/
|
||||
function setShowLegend(showLegend, dst) {
|
||||
if (showLegend === undefined) {
|
||||
// If the default was auto, make a choice for this field
|
||||
var isAutoByDefault = (DEFAULTS.showLegend === undefined);
|
||||
|
||||
if (isAutoByDefault) {
|
||||
// these styles default to having legends
|
||||
var isLegendGraphStyle = dst.style === STYLE.DOTCOLOR
|
||||
|| dst.style === STYLE.DOTSIZE;
|
||||
|
||||
dst.showLegend = isLegendGraphStyle;
|
||||
} else {
|
||||
// Leave current value as is
|
||||
}
|
||||
} else {
|
||||
dst.showLegend = showLegend;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve the style index from given styleName
|
||||
* @param {string} styleName Style name such as 'dot', 'grid', 'dot-line'
|
||||
* @return {number} styleNumber Enumeration value representing the style, or -1
|
||||
* when not found
|
||||
*/
|
||||
function getStyleNumberByName(styleName) {
|
||||
var number = STYLENAME[styleName];
|
||||
|
||||
if (number === undefined) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return number;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if given number is a valid style number.
|
||||
*
|
||||
* @param {string | number} style
|
||||
* @return {boolean} true if valid, false otherwise
|
||||
*/
|
||||
function checkStyleNumber(style) {
|
||||
var valid = false;
|
||||
|
||||
for (var n in STYLE) {
|
||||
if (STYLE[n] === style) {
|
||||
valid = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string | number} style
|
||||
* @param {Object} dst
|
||||
*/
|
||||
function setStyle(style, dst) {
|
||||
if (style === undefined) {
|
||||
return; // Nothing to do
|
||||
}
|
||||
|
||||
var styleNumber;
|
||||
|
||||
if (typeof style === 'string') {
|
||||
styleNumber = getStyleNumberByName(style);
|
||||
|
||||
if (styleNumber === -1 ) {
|
||||
throw new Error('Style \'' + style + '\' is invalid');
|
||||
}
|
||||
} else {
|
||||
// Do a pedantic check on style number value
|
||||
if (!checkStyleNumber(style)) {
|
||||
throw new Error('Style \'' + style + '\' is invalid');
|
||||
}
|
||||
|
||||
styleNumber = style;
|
||||
}
|
||||
|
||||
dst.style = styleNumber;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the background styling for the graph
|
||||
* @param {string | {fill: string, stroke: string, strokeWidth: string}} backgroundColor
|
||||
* @param {Object} dst
|
||||
*/
|
||||
function setBackgroundColor(backgroundColor, dst) {
|
||||
var fill = 'white';
|
||||
var stroke = 'gray';
|
||||
var strokeWidth = 1;
|
||||
|
||||
if (typeof(backgroundColor) === 'string') {
|
||||
fill = backgroundColor;
|
||||
stroke = 'none';
|
||||
strokeWidth = 0;
|
||||
}
|
||||
else if (typeof(backgroundColor) === 'object') {
|
||||
if (backgroundColor.fill !== undefined) fill = backgroundColor.fill;
|
||||
if (backgroundColor.stroke !== undefined) stroke = backgroundColor.stroke;
|
||||
if (backgroundColor.strokeWidth !== undefined) strokeWidth = backgroundColor.strokeWidth;
|
||||
}
|
||||
else {
|
||||
throw new Error('Unsupported type of backgroundColor');
|
||||
}
|
||||
|
||||
dst.frame.style.backgroundColor = fill;
|
||||
dst.frame.style.borderColor = stroke;
|
||||
dst.frame.style.borderWidth = strokeWidth + 'px';
|
||||
dst.frame.style.borderStyle = 'solid';
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string | Object} dataColor
|
||||
* @param {Object} dst
|
||||
*/
|
||||
function setDataColor(dataColor, dst) {
|
||||
if (dataColor === undefined) {
|
||||
return; // Nothing to do
|
||||
}
|
||||
|
||||
if (dst.dataColor === undefined) {
|
||||
dst.dataColor = {};
|
||||
}
|
||||
|
||||
if (typeof dataColor === 'string') {
|
||||
dst.dataColor.fill = dataColor;
|
||||
dst.dataColor.stroke = dataColor;
|
||||
}
|
||||
else {
|
||||
if (dataColor.fill) {
|
||||
dst.dataColor.fill = dataColor.fill;
|
||||
}
|
||||
if (dataColor.stroke) {
|
||||
dst.dataColor.stroke = dataColor.stroke;
|
||||
}
|
||||
if (dataColor.strokeWidth !== undefined) {
|
||||
dst.dataColor.strokeWidth = dataColor.strokeWidth;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {Object} cameraPosition
|
||||
* @param {Object} dst
|
||||
*/
|
||||
function setCameraPosition(cameraPosition, dst) {
|
||||
var camPos = cameraPosition;
|
||||
if (camPos === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (dst.camera === undefined) {
|
||||
dst.camera = new Camera();
|
||||
}
|
||||
|
||||
dst.camera.setArmRotation(camPos.horizontal, camPos.vertical);
|
||||
dst.camera.setArmLength(camPos.distance);
|
||||
}
|
||||
|
||||
|
||||
module.exports.STYLE = STYLE;
|
||||
module.exports.setDefaults = setDefaults;
|
||||
module.exports.setOptions = setOptions;
|
||||
module.exports.setCameraPosition = setCameraPosition;
|
||||
349
node_modules/vis/lib/graph3d/Slider.js
generated
vendored
Normal file
349
node_modules/vis/lib/graph3d/Slider.js
generated
vendored
Normal file
@@ -0,0 +1,349 @@
|
||||
var util = require('../util');
|
||||
|
||||
/**
|
||||
* An html slider control with start/stop/prev/next buttons
|
||||
*
|
||||
* @constructor Slider
|
||||
* @param {Element} container The element where the slider will be created
|
||||
* @param {Object} options Available options:
|
||||
* {boolean} visible If true (default) the
|
||||
* slider is visible.
|
||||
*/
|
||||
function Slider(container, options) {
|
||||
if (container === undefined) {
|
||||
throw new Error('No container element defined');
|
||||
}
|
||||
this.container = container;
|
||||
this.visible = (options && options.visible != undefined) ? options.visible : true;
|
||||
|
||||
if (this.visible) {
|
||||
this.frame = document.createElement('DIV');
|
||||
//this.frame.style.backgroundColor = '#E5E5E5';
|
||||
this.frame.style.width = '100%';
|
||||
this.frame.style.position = 'relative';
|
||||
this.container.appendChild(this.frame);
|
||||
|
||||
this.frame.prev = document.createElement('INPUT');
|
||||
this.frame.prev.type = 'BUTTON';
|
||||
this.frame.prev.value = 'Prev';
|
||||
this.frame.appendChild(this.frame.prev);
|
||||
|
||||
this.frame.play = document.createElement('INPUT');
|
||||
this.frame.play.type = 'BUTTON';
|
||||
this.frame.play.value = 'Play';
|
||||
this.frame.appendChild(this.frame.play);
|
||||
|
||||
this.frame.next = document.createElement('INPUT');
|
||||
this.frame.next.type = 'BUTTON';
|
||||
this.frame.next.value = 'Next';
|
||||
this.frame.appendChild(this.frame.next);
|
||||
|
||||
this.frame.bar = document.createElement('INPUT');
|
||||
this.frame.bar.type = 'BUTTON';
|
||||
this.frame.bar.style.position = 'absolute';
|
||||
this.frame.bar.style.border = '1px solid red';
|
||||
this.frame.bar.style.width = '100px';
|
||||
this.frame.bar.style.height = '6px';
|
||||
this.frame.bar.style.borderRadius = '2px';
|
||||
this.frame.bar.style.MozBorderRadius = '2px';
|
||||
this.frame.bar.style.border = '1px solid #7F7F7F';
|
||||
this.frame.bar.style.backgroundColor = '#E5E5E5';
|
||||
this.frame.appendChild(this.frame.bar);
|
||||
|
||||
this.frame.slide = document.createElement('INPUT');
|
||||
this.frame.slide.type = 'BUTTON';
|
||||
this.frame.slide.style.margin = '0px';
|
||||
this.frame.slide.value = ' ';
|
||||
this.frame.slide.style.position = 'relative';
|
||||
this.frame.slide.style.left = '-100px';
|
||||
this.frame.appendChild(this.frame.slide);
|
||||
|
||||
// create events
|
||||
var me = this;
|
||||
this.frame.slide.onmousedown = function (event) {me._onMouseDown(event);};
|
||||
this.frame.prev.onclick = function (event) {me.prev(event);};
|
||||
this.frame.play.onclick = function (event) {me.togglePlay(event);};
|
||||
this.frame.next.onclick = function (event) {me.next(event);};
|
||||
}
|
||||
|
||||
this.onChangeCallback = undefined;
|
||||
|
||||
this.values = [];
|
||||
this.index = undefined;
|
||||
|
||||
this.playTimeout = undefined;
|
||||
this.playInterval = 1000; // milliseconds
|
||||
this.playLoop = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Select the previous index
|
||||
*/
|
||||
Slider.prototype.prev = function() {
|
||||
var index = this.getIndex();
|
||||
if (index > 0) {
|
||||
index--;
|
||||
this.setIndex(index);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Select the next index
|
||||
*/
|
||||
Slider.prototype.next = function() {
|
||||
var index = this.getIndex();
|
||||
if (index < this.values.length - 1) {
|
||||
index++;
|
||||
this.setIndex(index);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Select the next index
|
||||
*/
|
||||
Slider.prototype.playNext = function() {
|
||||
var start = new Date();
|
||||
|
||||
var index = this.getIndex();
|
||||
if (index < this.values.length - 1) {
|
||||
index++;
|
||||
this.setIndex(index);
|
||||
}
|
||||
else if (this.playLoop) {
|
||||
// jump to the start
|
||||
index = 0;
|
||||
this.setIndex(index);
|
||||
}
|
||||
|
||||
var end = new Date();
|
||||
var diff = (end - start);
|
||||
|
||||
// calculate how much time it to to set the index and to execute the callback
|
||||
// function.
|
||||
var interval = Math.max(this.playInterval - diff, 0);
|
||||
// document.title = diff // TODO: cleanup
|
||||
|
||||
var me = this;
|
||||
this.playTimeout = setTimeout(function() {me.playNext();}, interval);
|
||||
};
|
||||
|
||||
/**
|
||||
* Toggle start or stop playing
|
||||
*/
|
||||
Slider.prototype.togglePlay = function() {
|
||||
if (this.playTimeout === undefined) {
|
||||
this.play();
|
||||
} else {
|
||||
this.stop();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Start playing
|
||||
*/
|
||||
Slider.prototype.play = function() {
|
||||
// Test whether already playing
|
||||
if (this.playTimeout) return;
|
||||
|
||||
this.playNext();
|
||||
|
||||
if (this.frame) {
|
||||
this.frame.play.value = 'Stop';
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Stop playing
|
||||
*/
|
||||
Slider.prototype.stop = function() {
|
||||
clearInterval(this.playTimeout);
|
||||
this.playTimeout = undefined;
|
||||
|
||||
if (this.frame) {
|
||||
this.frame.play.value = 'Play';
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Set a callback function which will be triggered when the value of the
|
||||
* slider bar has changed.
|
||||
*
|
||||
* @param {function} callback
|
||||
*/
|
||||
Slider.prototype.setOnChangeCallback = function(callback) {
|
||||
this.onChangeCallback = callback;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the interval for playing the list
|
||||
* @param {number} interval The interval in milliseconds
|
||||
*/
|
||||
Slider.prototype.setPlayInterval = function(interval) {
|
||||
this.playInterval = interval;
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve the current play interval
|
||||
* @return {number} interval The interval in milliseconds
|
||||
*/
|
||||
Slider.prototype.getPlayInterval = function() {
|
||||
return this.playInterval;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set looping on or off
|
||||
* @param {boolean} doLoop If true, the slider will jump to the start when
|
||||
* the end is passed, and will jump to the end
|
||||
* when the start is passed.
|
||||
*
|
||||
*/
|
||||
Slider.prototype.setPlayLoop = function(doLoop) {
|
||||
this.playLoop = doLoop;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Execute the onchange callback function
|
||||
*/
|
||||
Slider.prototype.onChange = function() {
|
||||
if (this.onChangeCallback !== undefined) {
|
||||
this.onChangeCallback();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* redraw the slider on the correct place
|
||||
*/
|
||||
Slider.prototype.redraw = function() {
|
||||
if (this.frame) {
|
||||
// resize the bar
|
||||
this.frame.bar.style.top = (this.frame.clientHeight/2 -
|
||||
this.frame.bar.offsetHeight/2) + 'px';
|
||||
this.frame.bar.style.width = (this.frame.clientWidth -
|
||||
this.frame.prev.clientWidth -
|
||||
this.frame.play.clientWidth -
|
||||
this.frame.next.clientWidth - 30) + 'px';
|
||||
|
||||
// position the slider button
|
||||
var left = this.indexToLeft(this.index);
|
||||
this.frame.slide.style.left = (left) + 'px';
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set the list with values for the slider
|
||||
* @param {Array} values A javascript array with values (any type)
|
||||
*/
|
||||
Slider.prototype.setValues = function(values) {
|
||||
this.values = values;
|
||||
|
||||
if (this.values.length > 0)
|
||||
this.setIndex(0);
|
||||
else
|
||||
this.index = undefined;
|
||||
};
|
||||
|
||||
/**
|
||||
* Select a value by its index
|
||||
* @param {number} index
|
||||
*/
|
||||
Slider.prototype.setIndex = function(index) {
|
||||
if (index < this.values.length) {
|
||||
this.index = index;
|
||||
|
||||
this.redraw();
|
||||
this.onChange();
|
||||
}
|
||||
else {
|
||||
throw new Error('Index out of range');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* retrieve the index of the currently selected vaue
|
||||
* @return {number} index
|
||||
*/
|
||||
Slider.prototype.getIndex = function() {
|
||||
return this.index;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* retrieve the currently selected value
|
||||
* @return {*} value
|
||||
*/
|
||||
Slider.prototype.get = function() {
|
||||
return this.values[this.index];
|
||||
};
|
||||
|
||||
|
||||
Slider.prototype._onMouseDown = function(event) {
|
||||
// only react on left mouse button down
|
||||
var leftButtonDown = event.which ? (event.which === 1) : (event.button === 1);
|
||||
if (!leftButtonDown) return;
|
||||
|
||||
this.startClientX = event.clientX;
|
||||
this.startSlideX = parseFloat(this.frame.slide.style.left);
|
||||
|
||||
this.frame.style.cursor = 'move';
|
||||
|
||||
// add event listeners to handle moving the contents
|
||||
// we store the function onmousemove and onmouseup in the graph, so we can
|
||||
// remove the eventlisteners lateron in the function mouseUp()
|
||||
var me = this;
|
||||
this.onmousemove = function (event) {me._onMouseMove(event);};
|
||||
this.onmouseup = function (event) {me._onMouseUp(event);};
|
||||
util.addEventListener(document, 'mousemove', this.onmousemove);
|
||||
util.addEventListener(document, 'mouseup', this.onmouseup);
|
||||
util.preventDefault(event);
|
||||
};
|
||||
|
||||
|
||||
Slider.prototype.leftToIndex = function (left) {
|
||||
var width = parseFloat(this.frame.bar.style.width) -
|
||||
this.frame.slide.clientWidth - 10;
|
||||
var x = left - 3;
|
||||
|
||||
var index = Math.round(x / width * (this.values.length-1));
|
||||
if (index < 0) index = 0;
|
||||
if (index > this.values.length-1) index = this.values.length-1;
|
||||
|
||||
return index;
|
||||
};
|
||||
|
||||
Slider.prototype.indexToLeft = function (index) {
|
||||
var width = parseFloat(this.frame.bar.style.width) -
|
||||
this.frame.slide.clientWidth - 10;
|
||||
|
||||
var x = index / (this.values.length-1) * width;
|
||||
var left = x + 3;
|
||||
|
||||
return left;
|
||||
};
|
||||
|
||||
|
||||
|
||||
Slider.prototype._onMouseMove = function (event) {
|
||||
var diff = event.clientX - this.startClientX;
|
||||
var x = this.startSlideX + diff;
|
||||
|
||||
var index = this.leftToIndex(x);
|
||||
|
||||
this.setIndex(index);
|
||||
|
||||
util.preventDefault();
|
||||
};
|
||||
|
||||
|
||||
Slider.prototype._onMouseUp = function (event) { // eslint-disable-line no-unused-vars
|
||||
this.frame.style.cursor = 'auto';
|
||||
|
||||
// remove event listeners
|
||||
util.removeEventListener(document, 'mousemove', this.onmousemove);
|
||||
util.removeEventListener(document, 'mouseup', this.onmouseup);
|
||||
|
||||
util.preventDefault();
|
||||
};
|
||||
|
||||
module.exports = Slider;
|
||||
182
node_modules/vis/lib/graph3d/StepNumber.js
generated
vendored
Normal file
182
node_modules/vis/lib/graph3d/StepNumber.js
generated
vendored
Normal file
@@ -0,0 +1,182 @@
|
||||
/**
|
||||
* @prototype StepNumber
|
||||
* The class StepNumber is an iterator for Numbers. You provide a start and end
|
||||
* value, and a best step size. StepNumber itself rounds to fixed values and
|
||||
* a finds the step that best fits the provided step.
|
||||
*
|
||||
* If prettyStep is true, the step size is chosen as close as possible to the
|
||||
* provided step, but being a round value like 1, 2, 5, 10, 20, 50, ....
|
||||
*
|
||||
* Example usage:
|
||||
* var step = new StepNumber(0, 10, 2.5, true);
|
||||
* step.start();
|
||||
* while (!step.end()) {
|
||||
* alert(step.getCurrent());
|
||||
* step.next();
|
||||
* }
|
||||
*
|
||||
* Version: 1.0
|
||||
*
|
||||
* @param {number} start The start value
|
||||
* @param {number} end The end value
|
||||
* @param {number} step Optional. Step size. Must be a positive value.
|
||||
* @param {boolean} prettyStep Optional. If true, the step size is rounded
|
||||
* To a pretty step size (like 1, 2, 5, 10, 20, 50, ...)
|
||||
*/
|
||||
function StepNumber(start, end, step, prettyStep) {
|
||||
// set default values
|
||||
this._start = 0;
|
||||
this._end = 0;
|
||||
this._step = 1;
|
||||
this.prettyStep = true;
|
||||
this.precision = 5;
|
||||
|
||||
this._current = 0;
|
||||
this.setRange(start, end, step, prettyStep);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check for input values, to prevent disasters from happening
|
||||
*
|
||||
* Source: http://stackoverflow.com/a/1830844
|
||||
*
|
||||
* @param {string} n
|
||||
* @returns {boolean}
|
||||
*/
|
||||
StepNumber.prototype.isNumeric = function(n) {
|
||||
return !isNaN(parseFloat(n)) && isFinite(n);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set a new range: start, end and step.
|
||||
*
|
||||
* @param {number} start The start value
|
||||
* @param {number} end The end value
|
||||
* @param {number} step Optional. Step size. Must be a positive value.
|
||||
* @param {boolean} prettyStep Optional. If true, the step size is rounded
|
||||
* To a pretty step size (like 1, 2, 5, 10, 20, 50, ...)
|
||||
*/
|
||||
StepNumber.prototype.setRange = function(start, end, step, prettyStep) {
|
||||
if (!this.isNumeric(start)) {
|
||||
throw new Error('Parameter \'start\' is not numeric; value: ' + start);
|
||||
}
|
||||
if (!this.isNumeric(end)) {
|
||||
throw new Error('Parameter \'end\' is not numeric; value: ' + start);
|
||||
}
|
||||
if (!this.isNumeric(step)) {
|
||||
throw new Error('Parameter \'step\' is not numeric; value: ' + start);
|
||||
}
|
||||
|
||||
this._start = start ? start : 0;
|
||||
this._end = end ? end : 0;
|
||||
|
||||
this.setStep(step, prettyStep);
|
||||
};
|
||||
|
||||
/**
|
||||
* Set a new step size
|
||||
* @param {number} step New step size. Must be a positive value
|
||||
* @param {boolean} prettyStep Optional. If true, the provided step is rounded
|
||||
* to a pretty step size (like 1, 2, 5, 10, 20, 50, ...)
|
||||
*/
|
||||
StepNumber.prototype.setStep = function(step, prettyStep) {
|
||||
if (step === undefined || step <= 0)
|
||||
return;
|
||||
|
||||
if (prettyStep !== undefined)
|
||||
this.prettyStep = prettyStep;
|
||||
|
||||
if (this.prettyStep === true)
|
||||
this._step = StepNumber.calculatePrettyStep(step);
|
||||
else
|
||||
this._step = step;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculate a nice step size, closest to the desired step size.
|
||||
* Returns a value in one of the ranges 1*10^n, 2*10^n, or 5*10^n, where n is an
|
||||
* integer Number. For example 1, 2, 5, 10, 20, 50, etc...
|
||||
* @param {number} step Desired step size
|
||||
* @return {number} Nice step size
|
||||
*/
|
||||
StepNumber.calculatePrettyStep = function (step) {
|
||||
var log10 = function (x) {return Math.log(x) / Math.LN10;};
|
||||
|
||||
// try three steps (multiple of 1, 2, or 5
|
||||
var step1 = Math.pow(10, Math.round(log10(step))),
|
||||
step2 = 2 * Math.pow(10, Math.round(log10(step / 2))),
|
||||
step5 = 5 * Math.pow(10, Math.round(log10(step / 5)));
|
||||
|
||||
// choose the best step (closest to minimum step)
|
||||
var prettyStep = step1;
|
||||
if (Math.abs(step2 - step) <= Math.abs(prettyStep - step)) prettyStep = step2;
|
||||
if (Math.abs(step5 - step) <= Math.abs(prettyStep - step)) prettyStep = step5;
|
||||
|
||||
// for safety
|
||||
if (prettyStep <= 0) {
|
||||
prettyStep = 1;
|
||||
}
|
||||
|
||||
return prettyStep;
|
||||
};
|
||||
|
||||
/**
|
||||
* returns the current value of the step
|
||||
* @return {number} current value
|
||||
*/
|
||||
StepNumber.prototype.getCurrent = function () {
|
||||
return parseFloat(this._current.toPrecision(this.precision));
|
||||
};
|
||||
|
||||
/**
|
||||
* returns the current step size
|
||||
* @return {number} current step size
|
||||
*/
|
||||
StepNumber.prototype.getStep = function () {
|
||||
return this._step;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the current to its starting value.
|
||||
*
|
||||
* By default, this will be the largest value smaller than start, which
|
||||
* is a multiple of the step size.
|
||||
*
|
||||
* Parameters checkFirst is optional, default false.
|
||||
* If set to true, move the current value one step if smaller than start.
|
||||
*
|
||||
* @param {boolean} [checkFirst=false]
|
||||
*/
|
||||
StepNumber.prototype.start = function(checkFirst) {
|
||||
if (checkFirst === undefined) {
|
||||
checkFirst = false;
|
||||
}
|
||||
|
||||
this._current = this._start - this._start % this._step;
|
||||
|
||||
if (checkFirst) {
|
||||
if (this.getCurrent() < this._start) {
|
||||
this.next();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Do a step, add the step size to the current value
|
||||
*/
|
||||
StepNumber.prototype.next = function () {
|
||||
this._current += this._step;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns true whether the end is reached
|
||||
* @return {boolean} True if the current value has passed the end value.
|
||||
*/
|
||||
StepNumber.prototype.end = function () {
|
||||
return (this._current > this._end);
|
||||
};
|
||||
|
||||
module.exports = StepNumber;
|
||||
132
node_modules/vis/lib/graph3d/options.js
generated
vendored
Normal file
132
node_modules/vis/lib/graph3d/options.js
generated
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
/**
|
||||
* This object contains all possible options. It will check if the types are correct, if required if the option is one
|
||||
* of the allowed values.
|
||||
*
|
||||
* __any__ means that the name of the property does not matter.
|
||||
* __type__ is a required field for all objects and contains the allowed types of all objects
|
||||
*/
|
||||
let string = 'string';
|
||||
let bool = 'boolean';
|
||||
let number = 'number';
|
||||
let object = 'object'; // should only be in a __type__ property
|
||||
// Following not used here, but useful for reference
|
||||
//let array = 'array';
|
||||
//let dom = 'dom';
|
||||
//let any = 'any';
|
||||
|
||||
|
||||
let colorOptions = {
|
||||
fill : { string },
|
||||
stroke : { string },
|
||||
strokeWidth: { number },
|
||||
__type__ : { string, object, 'undefined': 'undefined' }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Order attempted to be alphabetical.
|
||||
* - x/y/z-prefixes ignored in sorting
|
||||
* - __type__ always at end
|
||||
* - globals at end
|
||||
*/
|
||||
let allOptions = {
|
||||
animationAutoStart: { boolean: bool, 'undefined': 'undefined' },
|
||||
animationInterval : { number },
|
||||
animationPreload : { boolean: bool },
|
||||
axisColor : { string },
|
||||
backgroundColor : colorOptions,
|
||||
xBarWidth : { number, 'undefined': 'undefined' },
|
||||
yBarWidth : { number, 'undefined': 'undefined' },
|
||||
cameraPosition : {
|
||||
distance : { number },
|
||||
horizontal: { number },
|
||||
vertical : { number },
|
||||
__type__ : { object }
|
||||
},
|
||||
xCenter : { string },
|
||||
yCenter : { string },
|
||||
dataColor : colorOptions,
|
||||
dotSizeMinFraction: { number },
|
||||
dotSizeMaxFraction: { number },
|
||||
dotSizeRatio : { number },
|
||||
filterLabel : { string },
|
||||
gridColor : { string },
|
||||
onclick : { 'function': 'function' },
|
||||
keepAspectRatio : { boolean: bool },
|
||||
xLabel : { string },
|
||||
yLabel : { string },
|
||||
zLabel : { string },
|
||||
legendLabel : { string },
|
||||
xMin : { number, 'undefined': 'undefined' },
|
||||
yMin : { number, 'undefined': 'undefined' },
|
||||
zMin : { number, 'undefined': 'undefined' },
|
||||
xMax : { number, 'undefined': 'undefined' },
|
||||
yMax : { number, 'undefined': 'undefined' },
|
||||
zMax : { number, 'undefined': 'undefined' },
|
||||
showAnimationControls: { boolean: bool, 'undefined': 'undefined' },
|
||||
showGrid : { boolean: bool },
|
||||
showLegend : { boolean: bool, 'undefined': 'undefined' },
|
||||
showPerspective : { boolean: bool },
|
||||
showShadow : { boolean: bool },
|
||||
showXAxis : { boolean: bool },
|
||||
showYAxis : { boolean: bool },
|
||||
showZAxis : { boolean: bool },
|
||||
xStep : { number, 'undefined': 'undefined' },
|
||||
yStep : { number, 'undefined': 'undefined' },
|
||||
zStep : { number, 'undefined': 'undefined' },
|
||||
style: {
|
||||
number, // TODO: either Graph3d.DEFAULT has string, or number allowed in documentation
|
||||
string: [
|
||||
'bar',
|
||||
'bar-color',
|
||||
'bar-size',
|
||||
'dot',
|
||||
'dot-line',
|
||||
'dot-color',
|
||||
'dot-size',
|
||||
'line',
|
||||
'grid',
|
||||
'surface'
|
||||
]
|
||||
},
|
||||
tooltip : { boolean: bool, 'function': 'function' },
|
||||
tooltipStyle : {
|
||||
content: {
|
||||
color : { string },
|
||||
background : { string },
|
||||
border : { string },
|
||||
borderRadius: { string },
|
||||
boxShadow : { string },
|
||||
padding : { string },
|
||||
__type__ : { object }
|
||||
},
|
||||
line: {
|
||||
borderLeft: { string },
|
||||
height : { string },
|
||||
width : { string },
|
||||
__type__ : { object }
|
||||
},
|
||||
dot: {
|
||||
border : { string },
|
||||
borderRadius: { string },
|
||||
height : { string },
|
||||
width : { string },
|
||||
__type__ : { object},
|
||||
},
|
||||
__type__: { object}
|
||||
},
|
||||
xValueLabel : { 'function': 'function' },
|
||||
yValueLabel : { 'function': 'function' },
|
||||
zValueLabel : { 'function': 'function' },
|
||||
valueMax : { number, 'undefined': 'undefined' },
|
||||
valueMin : { number, 'undefined': 'undefined' },
|
||||
verticalRatio : { number },
|
||||
|
||||
//globals :
|
||||
height: { string },
|
||||
width: { string },
|
||||
__type__: { object }
|
||||
};
|
||||
|
||||
|
||||
export {allOptions};
|
||||
Reference in New Issue
Block a user