Browse Source

Add option definitions and validation to Graph3d (#3099)

* Proof of concept with copied options + handling from network

* Added unit test for Graph3d, for checking default syntax; completed def's of all options, autoByDefault not handled yet.

* Fixes for options in playground example

* Added onclick options to graph3d documentation

* Fixes in graph3d examples

* Final fixes for option definitions in Graph3d

* Fixed handling of 'undefined' in options, enhanced graph3d unit test

* Disabled console output in graph3d unit test

* Upgrade webpack module
revert-3409-performance
wimrijnders 7 years ago
committed by Yotam Berkowitz
parent
commit
536d250180
8 changed files with 204 additions and 16 deletions
  1. +2
    -2
      .eslintrc
  2. +18
    -0
      docs/graph3d/index.html
  3. +1
    -2
      examples/graph3d/04_animation.html
  4. +1
    -1
      examples/graph3d/10_styling.html
  5. +7
    -5
      examples/graph3d/playground/playground.js
  6. +19
    -4
      lib/graph3d/Graph3d.js
  7. +132
    -0
      lib/graph3d/options.js
  8. +24
    -2
      test/Graph3d.test.js

+ 2
- 2
.eslintrc View File

@ -16,10 +16,10 @@
"complexity": [2, 55], "complexity": [2, 55],
"max-statements": [2, 115], "max-statements": [2, 115],
"no-unreachable": 1, "no-unreachable": 1,
"no-useless-escape": 0,
"no-console": 0,
"no-useless-escape": 0
/* /*
// some disabled options which might be useful // some disabled options which might be useful
"no-console": 0,
"no-empty": 0, "no-empty": 0,
"no-extra-semi": 0, "no-extra-semi": 0,
"no-fallthrough": 0, "no-fallthrough": 0,

+ 18
- 0
docs/graph3d/index.html View File

@ -441,6 +441,24 @@ var options = {
both have the same, maximum with.</td> both have the same, maximum with.</td>
</tr> </tr>
<tr>
<td>onclick</td>
<td>function</td>
<td>none</td>
<td>Event handler for a click event with signature <code>function onclick(point)</code>.<br>
Parameter <code>point</code> contains data for the nearest graph element relative to the click in
the line of sight. It is an object with the fields:
<ul>
<li><code>id </code> - id of nearest node to the click</li>
<li><code>x </code> - x-coordinate in graph units</li>
<li><code>y </code> - y-coordinate in graph units</li>
<li><code>z </code> - z-coordinate in graph units</li>
<li><code>style</code> - if present, the data value for this point</li>
</ul>
</td>
</tr>
<tr> <tr>
<td>showAnimationControls</td> <td>showAnimationControls</td>
<td>boolean</td> <td>boolean</td>

+ 1
- 2
examples/graph3d/04_animation.html View File

@ -51,8 +51,7 @@
keepAspectRatio: true, keepAspectRatio: true,
verticalRatio: 0.5, verticalRatio: 0.5,
animationInterval: 100, // milliseconds animationInterval: 100, // milliseconds
animationPreload: true,
filterValue: 'time'
animationPreload: true
}; };
// create our graph // create our graph

+ 1
- 1
examples/graph3d/10_styling.html View File

@ -58,7 +58,7 @@
keepAspectRatio: true, keepAspectRatio: true,
verticalRatio: 0.5 verticalRatio: 0.5
}; };
var camera = graph ? graph.getCameraPosition() : null; var camera = graph ? graph.getCameraPosition() : null;
// create our graph // create our graph

+ 7
- 5
examples/graph3d/playground/playground.js View File

@ -400,7 +400,7 @@ function getDataDatasource() {
* Retrieve a JSON object with all options * Retrieve a JSON object with all options
*/ */
function getOptions() { function getOptions() {
return {
var options = {
width: document.getElementById("width").value, width: document.getElementById("width").value,
height: document.getElementById("height").value, height: document.getElementById("height").value,
style: document.getElementById("style").value, style: document.getElementById("style").value,
@ -413,8 +413,8 @@ function getOptions() {
showLegend: (document.getElementById("showLegend").checked != false), showLegend: (document.getElementById("showLegend").checked != false),
showShadow: (document.getElementById("showShadow").checked != false), showShadow: (document.getElementById("showShadow").checked != false),
keepAspectRatio: (document.getElementById("keepAspectRatio").checked != false), keepAspectRatio: (document.getElementById("keepAspectRatio").checked != false),
verticalRatio: document.getElementById("verticalRatio").value,
animationInterval: document.getElementById("animationInterval").value,
verticalRatio: Number(document.getElementById("verticalRatio").value) || undefined,
animationInterval: Number(document.getElementById("animationInterval").value) || undefined,
xLabel: document.getElementById("xLabel").value, xLabel: document.getElementById("xLabel").value,
yLabel: document.getElementById("yLabel").value, yLabel: document.getElementById("yLabel").value,
zLabel: document.getElementById("zLabel").value, zLabel: document.getElementById("zLabel").value,
@ -423,8 +423,8 @@ function getOptions() {
animationPreload: (document.getElementById("animationPreload").checked != false), animationPreload: (document.getElementById("animationPreload").checked != false),
animationAutoStart:(document.getElementById("animationAutoStart").checked != false), animationAutoStart:(document.getElementById("animationAutoStart").checked != false),
xCenter: Number(document.getElementById("xCenter").value) || undefined,
yCenter: Number(document.getElementById("yCenter").value) || undefined,
xCenter: document.getElementById("xCenter").value,
yCenter: document.getElementById("yCenter").value,
xMin: Number(document.getElementById("xMin").value) || undefined, xMin: Number(document.getElementById("xMin").value) || undefined,
xMax: Number(document.getElementById("xMax").value) || undefined, xMax: Number(document.getElementById("xMax").value) || undefined,
@ -442,6 +442,8 @@ function getOptions() {
xBarWidth: Number(document.getElementById("xBarWidth").value) || undefined, xBarWidth: Number(document.getElementById("xBarWidth").value) || undefined,
yBarWidth: Number(document.getElementById("yBarWidth").value) || undefined yBarWidth: Number(document.getElementById("yBarWidth").value) || undefined
}; };
return options;
} }
/** /**

+ 19
- 4
lib/graph3d/Graph3d.js View File

@ -5,6 +5,9 @@ var Point2d = require('./Point2d');
var Slider = require('./Slider'); var Slider = require('./Slider');
var StepNumber = require('./StepNumber'); var StepNumber = require('./StepNumber');
var Settings = require('./Settings'); var Settings = require('./Settings');
var Validator = require("./../shared/Validator").default;
var {printStyle} = require('./../shared/Validator');
var {allOptions} = require('./options.js');
var DataGroup = require('./DataGroup'); var DataGroup = require('./DataGroup');
@ -31,7 +34,7 @@ var autoByDefault = undefined;
* If a field is not in this list, a default value of 'autoByDefault' is assumed, * If a field is not in this list, a default value of 'autoByDefault' is assumed,
* which is just an alias for 'undefined'. * which is just an alias for 'undefined'.
*/ */
var DEFAULTS = {
Graph3d.DEFAULTS = {
width : '400px', width : '400px',
height : '400px', height : '400px',
filterLabel : 'time', filterLabel : 'time',
@ -90,8 +93,6 @@ var DEFAULTS = {
} }
}, },
showLegend : autoByDefault, // determined by graph style
backgroundColor : autoByDefault,
dataColor : { dataColor : {
fill : '#7DC1FF', fill : '#7DC1FF',
@ -105,6 +106,13 @@ var DEFAULTS = {
distance : 1.7 distance : 1.7
}, },
/*
The following fields are 'auto by default', see above.
*/
showLegend : autoByDefault, // determined by graph style
backgroundColor : autoByDefault,
xBarWidth : autoByDefault, xBarWidth : autoByDefault,
yBarWidth : autoByDefault, yBarWidth : autoByDefault,
valueMin : autoByDefault, valueMin : autoByDefault,
@ -151,7 +159,7 @@ function Graph3d(container, data, options) {
// create a frame and canvas // create a frame and canvas
this.create(); this.create();
Settings.setDefaults(DEFAULTS, this);
Settings.setDefaults(Graph3d.DEFAULTS, this);
// the column indexes // the column indexes
this.colX = undefined; this.colX = undefined;
@ -628,6 +636,13 @@ Graph3d.prototype.setData = function (data) {
* @param {Object} options * @param {Object} options
*/ */
Graph3d.prototype.setOptions = function (options) { Graph3d.prototype.setOptions = function (options) {
if (options === undefined) return;
let errorFound = Validator.validate(options, allOptions);
if (errorFound === true) {
console.log('%cErrors have been found in the supplied options object.', printStyle);
}
this.animationStop(); this.animationStop();
Settings.setOptions(options, this); Settings.setOptions(options, this);

+ 132
- 0
lib/graph3d/options.js View 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};

+ 24
- 2
test/Graph3d.test.js View File

@ -1,11 +1,15 @@
var assert = require('assert'); var assert = require('assert');
var jsdom_global = require('jsdom-global');
var vis = require('../dist/vis'); var vis = require('../dist/vis');
var Graph3d = vis.Graph3d; var Graph3d = vis.Graph3d;
var jsdom_global = require('jsdom-global');
var stdout = require('test-console').stdout;
var Validator = require("./../lib/shared/Validator").default;
//var {printStyle} = require('./../lib/shared/Validator');
var {allOptions, configureOptions} = require('./../lib/graph3d/options.js');
var now = new Date();
describe('Graph3d', function () { describe('Graph3d', function () {
before(function() { before(function() {
//console.log('before!'); //console.log('before!');
this.jsdom_global = jsdom_global( this.jsdom_global = jsdom_global(
@ -15,6 +19,24 @@ describe('Graph3d', function () {
this.container = document.getElementById('mynetwork'); this.container = document.getElementById('mynetwork');
}); });
it('should pass validation for the default options', function () {
assert(Graph3d.DEFAULTS !== undefined);
let errorFound;
let output;
output = stdout.inspectSync(function() {
errorFound = Validator.validate(Graph3d.DEFAULTS, allOptions);
});
// Useful during debugging:
//if (errorFound === true) {
// console.log(JSON.stringify(output, null, 2));
//}
assert(!errorFound, 'DEFAULTS options object does not pass validation');
});
it('accepts new option values on defined instance', function () { it('accepts new option values on defined instance', function () {
assert(this.container !== null, 'Container div not found'); assert(this.container !== null, 'Container div not found');

Loading…
Cancel
Save