Browse Source

Merged develop branch

v3_develop
jos 10 years ago
parent
commit
6d8df70efd
136 changed files with 93204 additions and 34163 deletions
  1. +0
    -1
      .npmignore
  2. +48
    -0
      HISTORY.md
  3. +0
    -208
      Jakefile.js
  4. +129
    -9
      README.md
  5. +2
    -3
      bower.json
  6. +26664
    -0
      dist/vis-light.js
  7. +1
    -1
      dist/vis.css
  8. +27005
    -25723
      dist/vis.js
  9. +1
    -0
      dist/vis.map
  10. +0
    -0
      dist/vis.min.css
  11. +15
    -14
      dist/vis.min.js
  12. +7
    -0
      docs/dataset.html
  13. +150
    -4
      docs/network.html
  14. +21
    -1
      docs/timeline.html
  15. +7
    -6
      examples/network/02_random_nodes.html
  16. +1
    -1
      examples/network/07_selections.html
  17. +1
    -0
      examples/network/23_hierarchical_layout.html
  18. +34
    -1
      examples/network/24_hierarchical_layout_userdefined.html
  19. +75
    -0
      examples/network/26_staticSmoothCurves.html
  20. +10109
    -0
      examples/network/27_world_cup_network.html
  21. +10053
    -0
      examples/network/28_world_cup_network_performance.html
  22. +10213
    -0
      examples/network/29_neighbourhood_highlight.html
  23. +166
    -0
      examples/network/30_importing_from_gephi.html
  24. +1
    -0
      examples/network/data/WorldCup2014.json
  25. +5
    -0
      examples/network/index.html
  26. +152
    -0
      gulpfile.js
  27. +69
    -0
      index.js
  28. +10
    -14
      lib/DOMutil.js
  29. +14
    -2
      lib/DataSet.js
  30. +5
    -0
      lib/DataView.js
  31. +135
    -0
      lib/graph3d/Camera.js
  32. +218
    -0
      lib/graph3d/Filter.js
  33. +32
    -1074
      lib/graph3d/Graph3d.js
  34. +11
    -0
      lib/graph3d/Point2d.js
  35. +85
    -0
      lib/graph3d/Point3d.js
  36. +346
    -0
      lib/graph3d/Slider.js
  37. +140
    -0
      lib/graph3d/StepNumber.js
  38. +28
    -0
      lib/hammerUtil.js
  39. +0
    -0
      lib/header.js
  40. +10
    -0
      lib/module/hammer.js
  41. +3
    -0
      lib/module/moment.js
  42. +320
    -84
      lib/network/Edge.js
  43. +14
    -11
      lib/network/Groups.js
  44. +2
    -0
      lib/network/Images.js
  45. +140
    -50
      lib/network/Network.js
  46. +40
    -28
      lib/network/Node.js
  47. +2
    -0
      lib/network/Popup.js
  48. +0
    -0
      lib/network/css/network-manipulation.css
  49. +0
    -0
      lib/network/css/network-navigation.css
  50. +826
    -0
      lib/network/dotparser.js
  51. +60
    -0
      lib/network/gephiParser.js
  52. +0
    -0
      lib/network/img/acceptDeleteIcon.png
  53. +0
    -0
      lib/network/img/addNodeIcon.png
  54. +0
    -0
      lib/network/img/backIcon.png
  55. +0
    -0
      lib/network/img/connectIcon.png
  56. +0
    -0
      lib/network/img/cross.png
  57. +0
    -0
      lib/network/img/cross2.png
  58. +0
    -0
      lib/network/img/deleteIcon.png
  59. +0
    -0
      lib/network/img/downArrow.png
  60. +0
    -0
      lib/network/img/editIcon.png
  61. +0
    -0
      lib/network/img/leftArrow.png
  62. +0
    -0
      lib/network/img/minus.png
  63. +0
    -0
      lib/network/img/plus.png
  64. +0
    -0
      lib/network/img/rightArrow.png
  65. +0
    -0
      lib/network/img/upArrow.png
  66. +0
    -0
      lib/network/img/zoomExtends.png
  67. +1137
    -0
      lib/network/mixins/ClusterMixin.js
  68. +322
    -0
      lib/network/mixins/HierarchicalLayoutMixin.js
  69. +576
    -0
      lib/network/mixins/ManipulationMixin.js
  70. +198
    -0
      lib/network/mixins/MixinLoader.js
  71. +181
    -0
      lib/network/mixins/NavigationMixin.js
  72. +548
    -0
      lib/network/mixins/SectorsMixin.js
  73. +705
    -0
      lib/network/mixins/SelectionMixin.js
  74. +393
    -0
      lib/network/mixins/physics/BarnesHutMixin.js
  75. +154
    -0
      lib/network/mixins/physics/HierarchialRepulsionMixin.js
  76. +708
    -0
      lib/network/mixins/physics/PhysicsMixin.js
  77. +58
    -0
      lib/network/mixins/physics/RepulsionMixin.js
  78. +0
    -0
      lib/network/shapes.js
  79. +8
    -2
      lib/timeline/DataStep.js
  80. +13
    -0
      lib/timeline/Graph2d.js
  81. +10
    -3
      lib/timeline/Range.js
  82. +18
    -22
      lib/timeline/Stack.js
  83. +4
    -0
      lib/timeline/TimeStep.js
  84. +22
    -0
      lib/timeline/Timeline.js
  85. +2
    -0
      lib/timeline/component/Component.js
  86. +5
    -1
      lib/timeline/component/CurrentTime.js
  87. +6
    -0
      lib/timeline/component/CustomTime.js
  88. +7
    -0
      lib/timeline/component/DataAxis.js
  89. +8
    -3
      lib/timeline/component/GraphGroup.js
  90. +10
    -3
      lib/timeline/component/Group.js
  91. +71
    -9
      lib/timeline/component/ItemSet.js
  92. +14
    -8
      lib/timeline/component/Legend.js
  93. +10
    -4
      lib/timeline/component/LineGraph.js
  94. +6
    -0
      lib/timeline/component/TimeAxis.js
  95. +0
    -0
      lib/timeline/component/css/animation.css
  96. +0
    -0
      lib/timeline/component/css/currenttime.css
  97. +0
    -0
      lib/timeline/component/css/customtime.css
  98. +0
    -0
      lib/timeline/component/css/dataaxis.css
  99. +0
    -0
      lib/timeline/component/css/item.css
  100. +0
    -0
      lib/timeline/component/css/itemset.css

+ 0
- 1
.npmignore View File

@ -1,6 +1,5 @@
misc
node_modules
src
test
tools
.idea

+ 48
- 0
HISTORY.md View File

@ -2,6 +2,54 @@
http://visjs.org
## 2014-07-22, version 3.1.0
### General
- Refactored the code to commonjs modules, which are browserifyable. This allows
to create custom builds.
### Timeline
- Implemented function `getVisibleItems()`, which returns the items visible
in the current window.
- Added options `margin.item.horizontal` and `margin.item.vertical`, which
allows to specify different margins horizontally/vertically.
- Removed check for number of arguments in callbacks `onAdd`, `onUpdate`,
`onRemove`, and `onMove`.
- Fixed items in groups sometimes being displayed but not positioned correctly.
- Fixed range where the `end` of the first is equal to the `start` of the second
sometimes being stacked instead of put besides each other when `item.margin=0`
due to round-off errors.
### Network (formerly named Graph)
- Expanded smoothCurves options for improved support for large clusters.
- Added multiple types of smoothCurve drawing for greatly improved performance.
- Option for inherited edge colors from connected nodes.
- Option to disable the drawing of nodes or edges on drag.
- Fixed support nodes not being cleaned up if edges are removed.
- Improved edge selection detection for long smooth curves.
- Fixed dot radius bug.
- Updated max velocity of nodes to three times it's original value.
- Made "stabilized" event fire every time the network stabilizes.
- Fixed drift in dragging nodes while zooming.
- Fixed recursively constructing of hierarchical layouts.
- Added borderWidth option for nodes.
- Implemented new Hierarchical view solver.
- Fixed an issue with selecting nodes when the web page is scrolled down.
- Added Gephi JSON parser
- Added Neighbour Highlight example
- Added Import From Gephi example
- Enabled color parsing for nodes when supplied with rgb(xxx,xxx,xxx) value.
### DataSet
- Added .get() returnType option to return as JSON object, Array or Google
DataTable.
## 2014-07-07, version 3.0.0
### Timeline

+ 0
- 208
Jakefile.js View File

@ -1,208 +0,0 @@
/**
* Jake build script
*/
var jake = require('jake'),
browserify = require('browserify'),
wrench = require('wrench'),
CleanCSS = require('clean-css'),
fs = require('fs');
require('jake-utils');
// constants
var DIST = './dist';
var VIS = DIST + '/vis.js';
var VIS_CSS = DIST + '/vis.css';
var VIS_TMP = DIST + '/vis.js.tmp';
var VIS_MIN = DIST + '/vis.min.js';
var VIS_MIN_CSS = DIST + '/vis.min.css';
/**
* default task
*/
desc('Default task: build all libraries');
task('default', ['build', 'minify'], function () {
console.log('done');
});
/**
* build the visualization library vis.js
*/
desc('Build the visualization library vis.js');
task('build', {async: true}, function () {
jake.mkdirP(DIST);
jake.mkdirP(DIST + '/img');
// concatenate and stringify the css files
concat({
src: [
'./src/timeline/component/css/timeline.css',
'./src/timeline/component/css/panel.css',
'./src/timeline/component/css/labelset.css',
'./src/timeline/component/css/itemset.css',
'./src/timeline/component/css/item.css',
'./src/timeline/component/css/timeaxis.css',
'./src/timeline/component/css/currenttime.css',
'./src/timeline/component/css/customtime.css',
'./src/timeline/component/css/animation.css',
'./src/timeline/component/css/dataaxis.css',
'./src/timeline/component/css/pathStyles.css',
'./src/network/css/network-manipulation.css',
'./src/network/css/network-navigation.css'
],
dest: VIS_CSS,
separator: '\n'
});
console.log('created ' + VIS_CSS);
// concatenate the script files
concat({
dest: VIS_TMP,
src: [
'./src/module/imports.js',
'./src/shim.js',
'./src/util.js',
'./src/DOMutil.js',
'./src/DataSet.js',
'./src/DataView.js',
'./src/timeline/component/GraphGroup.js',
'./src/timeline/component/Legend.js',
'./src/timeline/component/DataAxis.js',
'./src/timeline/component/LineGraph.js',
'./src/timeline/DataStep.js',
'./src/timeline/Stack.js',
'./src/timeline/TimeStep.js',
'./src/timeline/Range.js',
'./src/timeline/component/Component.js',
'./src/timeline/component/TimeAxis.js',
'./src/timeline/component/CurrentTime.js',
'./src/timeline/component/CustomTime.js',
'./src/timeline/component/ItemSet.js',
'./src/timeline/component/item/*.js',
'./src/timeline/component/Group.js',
'./src/timeline/Timeline.js',
'./src/timeline/Graph2d.js',
'./src/network/dotparser.js',
'./src/network/shapes.js',
'./src/network/Node.js',
'./src/network/Edge.js',
'./src/network/Popup.js',
'./src/network/Groups.js',
'./src/network/Images.js',
'./src/network/networkMixins/physics/PhysicsMixin.js',
'./src/network/networkMixins/physics/HierarchialRepulsion.js',
'./src/network/networkMixins/physics/BarnesHut.js',
'./src/network/networkMixins/physics/Repulsion.js',
'./src/network/networkMixins/HierarchicalLayoutMixin.js',
'./src/network/networkMixins/ManipulationMixin.js',
'./src/network/networkMixins/SectorsMixin.js',
'./src/network/networkMixins/ClusterMixin.js',
'./src/network/networkMixins/SelectionMixin.js',
'./src/network/networkMixins/NavigationMixin.js',
'./src/network/networkMixins/MixinLoader.js',
'./src/network/Network.js',
'./src/graph3d/Graph3d.js',
'./src/module/exports.js'
],
separator: '\n'
});
// copy images
wrench.copyDirSyncRecursive('./src/network/img', DIST + '/img/network', {
forceDelete: true
});
wrench.copyDirSyncRecursive('./src/timeline/img', DIST + '/img/timeline', {
forceDelete: true
});
var timeStart = Date.now();
// bundle the concatenated script and dependencies into one file
var b = browserify();
b.add(VIS_TMP);
b.bundle({
standalone: 'vis'
}, function (err, code) {
if(err) {
throw err;
}
console.log("browserify",Date.now() - timeStart); timeStart = Date.now();
// add header and footer
var lib = read('./src/module/header.js') + code;
// write bundled file
write(VIS, lib);
console.log('created js' + VIS);
// remove temporary file
fs.unlinkSync(VIS_TMP);
// update version number and stuff in the javascript files
replacePlaceholders(VIS);
complete();
});
});
/**
* minify the visualization library vis.js
*/
desc('Minify the visualization library vis.js');
task('minify', {async: true}, function () {
// minify javascript
minify({
src: VIS,
dest: VIS_MIN,
header: read('./src/module/header.js')
});
// update version number and stuff in the javascript files
replacePlaceholders(VIS_MIN);
console.log('created minified ' + VIS_MIN);
var minified = new CleanCSS().minify(read(VIS_CSS));
write(VIS_MIN_CSS, minified);
console.log('created minified ' + VIS_MIN_CSS);
});
/**
* test task
*/
desc('Test the library');
task('test', function () {
// TODO: use a testing suite for testing: nodeunit, mocha, tap, ...
var filelist = new jake.FileList();
filelist.include([
'./test/**/*.js'
]);
var files = filelist.toArray();
files.forEach(function (file) {
require('./' + file);
});
console.log('Executed ' + files.length + ' test files successfully');
});
/**
* replace version, date, and name placeholders in the provided file
* @param {String} filename
*/
var replacePlaceholders = function (filename) {
replace({
replacements: [
{pattern: '@@date', replacement: today()},
{pattern: '@@version', replacement: version()}
],
src: filename
});
};

+ 129
- 9
README.md View File

@ -57,7 +57,7 @@ or load vis.js using require.js. Note that vis.css must be loaded too.
```js
require.config({
paths: {
vis: 'path/to/vis',
vis: 'path/to/vis/dist',
}
});
require(['vis'], function (math) {
@ -124,15 +124,9 @@ To build the library from source, clone the project from github
git clone git://github.com/almende/vis.git
The project uses [jake](https://github.com/mde/jake) as build tool.
The build script uses [Browserify](http://browserify.org/) to
bundle the source code into a library,
and uses [UglifyJS](http://lisperator.net/uglifyjs/) to minify the code.
The source code uses the module style of node (require and module.exports) to
organize dependencies.
To install all dependencies and build the library, run `npm install` in the
root of the project.
organize dependencies. To install all dependencies and build the library,
run `npm install` in the root of the project.
cd vis
npm install
@ -141,6 +135,132 @@ Then, the project can be build running:
npm run build
To automatically rebuild on changes in the source files, once can use
npm run watch
This will both build and minify the library on changes. Minifying is relatively
slow, so when only the non-minified library is needed, one can use the
`watch-dev` script instead:
npm run watch-dev
## Custom builds
The folder `dist` contains bundled versions of vis.js for direct use in the browser. These bundles contain the all visualizations and includes external dependencies such as hammer.js and moment.js.
The source code of vis.js consists of commonjs modules, which makes it possible to create custom bundles using tools like [Browserify](http://browserify.org/) or [Webpack](http://webpack.github.io/). This can be bundling just one visualization like the Timeline, or bundling vis.js as part of your own browserified web application. Note that hammer.js v1.0.6 or newer is required.
#### Example 1: Bundle a single visualization
For example, to create a bundle with just the Timeline and DataSet, create an index file named **custom.js** in the root of the project, containing:
```js
exports.DataSet = require('./lib/DataSet');
exports.Timeline = require('./lib/timeline/Timeline');
```
Install browserify globally via `[sudo] npm install -g browserify`, then create a custom bundle like:
browserify custom.js -o vis-custom.js -s vis
This will generate a custom bundle *vis-custom.js*, which exposes the namespace `vis` containing only `DataSet` and `Timeline`. The generated bundle can be minified with uglifyjs (installed globally with `[sudo] npm install -g uglify-js`):
uglifyjs vis-custom.js -o vis-custom.min.js
The custom bundle can now be loaded like:
```html
<!DOCTYPE HTML>
<html>
<head>
<script src="vis-custom.min.js"></script>
<link href="dist/vis.min.css" rel="stylesheet" type="text/css" />
</head>
<body>
...
</body>
</html>
```
#### Example 2: Exclude external libraries
The default bundle `vis.js` is standalone and includes external dependencies such as hammer.js and moment.js. When these libraries are already loaded by the application, vis.js does not need to include these dependencies itself too. To build a custom bundle of vis.js excluding moment.js and hammer.js, run browserify in the root of the project:
browserify index.js -o vis-custom.js -s vis -x moment -x hammerjs
This will generate a custom bundle *vis-custom.js*, which exposes the namespace `vis`, and has moment and hammerjs excluded. The generated bundle can be minified with uglifyjs:
uglifyjs vis-custom.js -o vis-custom.min.js
The custom bundle can now be loaded as:
```html
<!DOCTYPE HTML>
<html>
<head>
<!-- load external dependencies -->
<script src="http://cdnjs.cloudflare.com/ajax/libs/moment.js/2.7.0/moment.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/hammer.js/1.1.3/hammer.min.js"></script>
<!-- load vis.js -->
<script src="vis-custom.min.js"></script>
<link href="dist/vis.min.css" rel="stylesheet" type="text/css" />
</head>
<body>
...
</body>
</html>
```
#### Example 3: Bundle vis.js as part of your (commonjs) application
When writing a web application with commonjs modules, vis.js can be packaged automatically into the application. Create a file **app.js** containing:
```js
var moment = require('moment');
var DataSet = require('vis/lib/DataSet');
var Timeline = require('vis/lib/timeline/Timeline');
var container = document.getElementById('visualization');
var data = new DataSet([
{id: 1, content: 'item 1', start: moment('2013-04-20')},
{id: 2, content: 'item 2', start: moment('2013-04-14')},
{id: 3, content: 'item 3', start: moment('2013-04-18')},
{id: 4, content: 'item 4', start: moment('2013-04-16'), end: moment('2013-04-19')},
{id: 5, content: 'item 5', start: moment('2013-04-25')},
{id: 6, content: 'item 6', start: moment('2013-04-27')}
]);
var options = {};
var timeline = new Timeline(container, data, options);
```
Install the application dependencies via npm:
npm install vis moment
The application can be bundled and minified:
browserify app.js -o app-bundle.js
uglifyjs app-bundle.js -o app-bundle.min.js
And loaded into a webpage:
```html
<!DOCTYPE HTML>
<html>
<head>
<link href="node_modules/vis/dist/vis.min.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="visualization"></div>
<script src="app-bundle.min.js"></script>
</body>
</html>
```
## Test

+ 2
- 3
bower.json View File

@ -1,6 +1,6 @@
{
"name": "vis",
"version": "3.0.0",
"version": "3.1.0",
"description": "A dynamic, browser-based visualization library.",
"homepage": "http://visjs.org/",
"repository": {
@ -10,11 +10,10 @@
"ignore": [
"misc",
"node_modules",
"src",
"test",
"tools",
".idea",
"Jakefile.js",
"gulpfile.js",
"package.json",
".npmignore",
".gitignore"

+ 26664
- 0
dist/vis-light.js
File diff suppressed because it is too large
View File


+ 1
- 1
dist/vis.css View File

@ -703,4 +703,4 @@ div.network-navigation.zoomExtends {
background-image: url("img/network/zoomExtends.png");
bottom:50px;
right:15px;
}
}

+ 27005
- 25723
dist/vis.js
File diff suppressed because it is too large
View File


+ 1
- 0
dist/vis.map
File diff suppressed because it is too large
View File


+ 0
- 0
dist/vis.min.css View File


+ 15
- 14
dist/vis.min.js
File diff suppressed because it is too large
View File


+ 7
- 0
docs/dataset.html View File

@ -691,6 +691,13 @@ DataSet.map(callback [, options]);
<td>Order the items by a field name or custom sort function.</td>
</tr>
<tr>
<td>returnType</td>
<td>String</td>
<td>Determine the type of output of the get function. Allowed values are <code>Array | Object | DataTable</code>.
The <code>DataTable</code> refers to a Google DataTable. The default returnType is an array. The object type will return a JSON object with the ID's as keys.</td>
</tr>
</table>
<p>

+ 150
- 4
docs/network.html View File

@ -54,6 +54,7 @@
<li><a href="#Nodes">Nodes</a></li>
<li><a href="#Edges">Edges</a></li>
<li><a href="#DOT_language">DOT language</a></li>
<li><a href="#Gephi_import">Gephi import</a></li>
</ul>
</li>
<li>
@ -262,6 +263,21 @@ When using a DataSet, the network is automatically updating to changes in the Da
<th>Description</th>
</tr>
<tr>
<td>borderWidth</td>
<td>Number</td>
<td>1</td>
<td>The width of the border of the node when it is not selected, automatically limited by the width of the node.</td>
</tr>
<tr>
<td>borderWidthSelected</td>
<td>Number</td>
<td>undefined</td>
<td>The width of the border of the node when it is selected. If left at undefined, double the borderWidth will be used.</td>
</tr>
<tr>
<td>color</td>
<td>String | Object</td>
@ -672,6 +688,14 @@ When using a DataSet, the network is automatically updating to changes in the Da
<td>physics.[method].springLength</td>
<td>The resting length of the edge when modeled as a spring. By default the springLength determined by the physics is used. By using this setting you can make certain edges have different resting lengths.</td>
</tr>
<tr>
<td>inheritColor</td>
<td>String | Boolean</td>
<td>false</td>
<td>Possible values: <code>"to","from", true, false</code>. If this value is set to false, the edge color information is used. If the value is set to true or "from",
the color data from the borders of the "from" node is used. If this value is "to", the color data from the borders of the "to" node is used.</td>
</tr>
<tr>
<td>title</td>
<td>string | function</td>
@ -736,7 +760,85 @@ var data = {
var network = new vis.Network(container, data);
</pre>
<h3 id="Gephi_import">Gephi import (JSON)</h3>
<p>
network can import data straight from an exported json file from gephi. You can get the JSON exporter here:
<a href="https://marketplace.gephi.org/plugin/json-exporter/" target="_blank">https://marketplace.gephi.org/plugin/json-exporter/</a>.
An example exists showing how to get a JSON file into Vis: <a href="../examples/Network/30_importing_from_gephi.html">30_importing_from_gephi</a>.
</p>
<p>
Example usage:
</p>
<pre class="prettyprint lang-js">
// load the JSON file containing the Gephi network.
var gephiJSON = loadJSON("./data/WorldCup2014.json"); // code in example 30
// create a data object with the gephi key:
var data = {
gephi: gephiJSON
};
// create a network
var network = new vis.Network(container, data);
</pre>
Alternatively you can use the parser manually:
<pre class="prettyprint lang-js">
// load the JSON file containing the Gephi network.
var gephiJSON = loadJSON("./data/WorldCup2014.json"); // code in example 30
// parse the gephi file to receive an object
// containing nodes and edges in vis format.
var parsed = vis.network.gephiParser.parseGephi(gephiJSON);
// provide data in the normal fashion
var data = {
nodes: parsed.nodes,
edged: parsed.edges
};
// create a network
var network = new vis.Network(container, data);
</pre>
<h4>Gephi parser options</h4>
There are a few options you can use to tell Vis what to do with the data from Gephi.
<pre class="prettyprint lang-js">
var parserOptions = {
allowedToMove: false,
parseColor: false
}
var parsed = vis.network.gephiParser.parseGephi(gephiJSON, parserOptions);
</pre>
<table>
<tr>
<th>Name</th>
<th>Type</th>
<th>Default</th>
<th>Description</th>
</tr>
<tr>
<td>allowedToMove</td>
<td>Boolean</td>
<td>false</td>
<td>
If true, the nodes will move according to the physics model after import. If false, the nodes do not move at all.
</td>
</tr>
<tr>
<td>parseColor</td>
<td>Boolean</td>
<td>false</td>
<td>
If true, the color will be parsed by the vis parser, generating extra colors for the borders, highlighs and hover. If false, the node will be the supplied color.
</td>
</tr>
</table>
<h2 id="Configuration_options">Configuration options</h2>
@ -874,7 +976,22 @@ var options = {
Toggle if the nodes can be dragged. This will not affect the dragging of the network.
</td>
</tr>
<tr>
<td>hideNodesOnDrag</td>
<td>Boolean</td>
<td>false</td>
<td>
Toggle if the nodes are drawn during a drag. This can greatly improve performance if you have many nodes.
</td>
</tr>
<tr>
<td>hideEdgesOnDrag</td>
<td>Boolean</td>
<td>false</td>
<td>
Toggle if the edges are drawn during a drag. This can greatly improve performance if you have many edges.
</td>
</tr>
<tr>
<td><a href="#Navigation_controls">navigation</a></td>
<td>Object</td>
@ -895,11 +1012,31 @@ var options = {
<tr>
<td>smoothCurves</td>
<td>Boolean || object</td>
<td>object</td>
<td>If true, edges are drawn as smooth curves. This is more computationally intensive since the edge now is a quadratic Bezier curve. This can be further configured by the options below.</td>
</tr>
<tr>
<td>smoothCurves.dynamic</td>
<td>Boolean</td>
<td>true</td>
<td>If true, edges are drawn as smooth curves. This is more computationally intensive since the edge now is a quadratic Bezier curve with control points on both nodes and an invisible node in the center of the edge. This support node is also handed by the physics simulation.</td>
<td>By default, the edges are dynamic. This means there are support nodes placed in the middle of the edge. This support node is also handed by the physics simulation. If false, the smoothness will be based on the
relative positions of the to and from nodes. This is computationally cheaper but there is no self organisation.</td>
</tr>
<tr>
<td>smoothCurves.type</td>
<td>String</td>
<td>"continuous"</td>
<td>This option only affects NONdynamic smooth curves. The supported types are: <code>continuous, discrete, diagonalCross, straightCross, horizontal, vertical</code>. The effects of these types
are shown in examples <a href="../examples/Network/26_staticSmoothCurves.html">26</a> and <a href="../examples/Network/27_world_cup_network.html">27</a></td>
</tr>
<tr>
<td>smoothCurves.roundness</td>
<td>Number</td>
<td>0.5</td>
<td>This only affects NONdynamic smooth curves. The roundness can be tweaked with the parameter. The value range is from 0 to 1 with a maximum roundness at 0.5.</td>
</tr>
<tr>
<td>selectable</td>
<td>Boolean</td>
@ -1223,6 +1360,14 @@ var options = {
<td>The resting length of the edge when modeled as a spring. By default the springLength determined by the physics is used. By using this setting you can make certain edges have different resting lengths.</td>
</tr>
<tr>
<td>inheritColor</td>
<td>String | Boolean</td>
<td>false</td>
<td>Possible values: <code>"to","from", true, false</code>. If this value is set to false, the edge color information is used. If the value is set to true or "from",
the color data from the borders of the "from" node is used. If this value is "to", the color data from the borders of the "to" node is used.</td>
</tr>
<tr>
<td>style</td>
<td>String</td>
@ -2366,7 +2511,8 @@ network.off('select', onSelect);
</tr>
<tr>
<td>stabilized</td>
<td>Fired when the network has been stabilized after initialization. This event can be used to trigger the .storePosition() function after stabilization.</td>
<td>Fired when the network has been stabilized. This event can be used to trigger the .storePosition() function after stabilization. When the network in initialized, the parameter
iterations will be the amount of iterations it took to stabilize. After initialization, this parameter is null.</td>
<td>
<ul>
<li><code>iterations</code>: number of iterations used to stabilize</li>

+ 21
- 1
docs/timeline.html View File

@ -449,7 +449,21 @@ var options = {
<td>margin.item</td>
<td>Number</td>
<td>10</td>
<td>The minimal margin in pixels between items.</td>
<td>The minimal margin in pixels between items in both horizontal and vertical direction.</td>
</tr>
<tr>
<td>margin.item.horizontal</td>
<td>Number</td>
<td>10</td>
<td>The minimal horizontal margin in pixels between items.</td>
</tr>
<tr>
<td>margin.item.vertical</td>
<td>Number</td>
<td>10</td>
<td>The minimal vertical margin in pixels between items.</td>
</tr>
<tr>
@ -726,6 +740,12 @@ timeline.clear({options: true}); // clear options only
<td>Get an array with the ids of the currently selected items.</td>
</tr>
<tr>
<td>getVisibleItems()</td>
<td>Number[]</td>
<td>Get an array with the ids of the currently visible items.</td>
</tr>
<tr>
<td>getWindow()</td>
<td>Object</td>

+ 7
- 6
examples/network/02_random_nodes.html View File

@ -31,7 +31,8 @@
for (var i = 0; i < nodeCount; i++) {
nodes.push({
id: i,
label: String(i)
label: String(i),
radius:300
});
connectionCount[i] = 0;
@ -81,12 +82,12 @@
},
stabilize: false
};
network = new vis.Network(container, data, options);
network = new vis.Network(container, data, options);
// add event listeners
network.on('select', function(params) {
document.getElementById('selection').innerHTML = 'Selection: ' + params.nodes;
});
// add event listeners
network.on('select', function(params) {
document.getElementById('selection').innerHTML = 'Selection: ' + params.nodes;
});
}
</script>
</head>

+ 1
- 1
examples/network/07_selections.html View File

@ -56,7 +56,7 @@
});
// set initial selection (id's of some nodes)
network.setSelection([3, 4, 5]);
network.selectNodes([3, 4, 5]);
</script>
</body>

+ 1
- 0
examples/network/23_hierarchical_layout.html View File

@ -82,6 +82,7 @@
edges: {
},
stabilize: false,
smoothCurves: false,
hierarchicalLayout: {
direction: directionInput.value
}

+ 34
- 1
examples/network/24_hierarchical_layout_userdefined.html View File

@ -20,6 +20,7 @@
var nodes = null;
var edges = null;
var network = null;
var directionInput = document.getElementById("direction");
function draw() {
nodes = [];
@ -113,7 +114,9 @@
};
var options = {
hierarchicalLayout:true
hierarchicalLayout: {
direction: directionInput.value
}
};
network = new vis.Network(container, data, options);
@ -122,6 +125,7 @@
document.getElementById('selection').innerHTML = 'Selection: ' + params.nodes;
});
}
</script>
</head>
@ -129,11 +133,40 @@
<h2>Hierarchical Layout - User-defined</h2>
<div style="width:700px; font-size:14px;">
This example shows a user-defined hierarchical layout. If the user defines levels for nodes but does not do so for all nodes, an alert will show up and hierarchical layout will be disabled. Either all or none can be defined.
If the smooth curves appear to be inverted, the direction of the edge is not in the same direction as the network.
</div>
<input type="button" id="btn-UD" value="Up-Down">
<input type="button" id="btn-DU" value="Down-Up">
<input type="button" id="btn-LR" value="Left-Right">
<input type="button" id="btn-RL" value="Right-Left">
<input type="hidden" id='direction' value="UD">
<br />
<div id="mynetwork"></div>
<p id="selection"></p>
<script language="JavaScript">
var directionInput = document.getElementById("direction");
var btnUD = document.getElementById("btn-UD");
btnUD.onclick = function() {
directionInput.value = "UD";
draw();
}
var btnDU = document.getElementById("btn-DU");
btnDU.onclick = function() {
directionInput.value = "DU";
draw();
};
var btnLR = document.getElementById("btn-LR");
btnLR.onclick = function() {
directionInput.value = "LR";
draw();
};
var btnRL = document.getElementById("btn-RL");
btnRL.onclick = function() {
directionInput.value = "RL";
draw();
};
</script>
</body>
</html>

+ 75
- 0
examples/network/26_staticSmoothCurves.html View File

@ -0,0 +1,75 @@
<!doctype html>
<html>
<head>
<title>Network | Static smooth curves</title>
<script type="text/javascript" src="../../dist/vis.js"></script>
<style type="text/css">
#mynetwork {
width: 400px;
height: 400px;
border: 1px solid lightgray;
}
</style>
</head>
<body>
<h2>Static smooth curves</h2>
<div style="width:700px; font-size:14px;">
All the smooth curves in the examples so far have been using dynamic smooth curves. This means that each curve has a
support node which takes part in the physics simulation. For large networks or dense clusters, this may not be the ideal
solution. To solve this, static smooth curves have been added. The static smooth curves are based only on the positions of the connected
nodes. There are multiple ways to determine the way this curve is drawn. This example shows the effect of the different
types. <br /> <br />
Drag the nodes around each other to see how the smooth curves are drawn for each setting. For animated system, we
recommend only the continuous mode. In the next example you can see the effect of these methods on a large network. Keep in mind
that the direction (the from and to) of the curve matters.
<br /> <br />
</div>
Smooth curve type:
<select id="dropdownID">
<option value="continuous">continuous</option>
<option value="discrete">discrete</option>
<option value="diagonalCross">diagonalCross</option>
<option value="straightCross">straightCross</option>
<option value="horizontal">horizontal</option>
<option value="vertical">vertical</option>
</select>
<div id="mynetwork"></div>
<script type="text/javascript">
var dropdown = document.getElementById("dropdownID");
dropdown.onchange = update;
// create an array with nodes
var nodes = [
{id: 1, label: 'Node 1'},
{id: 2, label: 'Node 2', x:150, y:130, allowedToMoveX: true, allowedToMoveY: true}
];
// create an array with edges
var edges = [
{from: 1, to: 2}
];
// create a network
var container = document.getElementById('mynetwork');
var data = {
nodes: nodes,
edges: edges
};
var options = {physics:{barnesHut:{gravitationalConstant:0, springConstant:0, centralGravity: 0}},
smoothCurves:{dynamic:false, type: '1'}};
var network = new vis.Network(container, data, options);
function update() {
var type = dropdown.value;
network.setOptions({smoothCurves:{type:type}});
}
</script>
</body>
</html>

+ 10109
- 0
examples/network/27_world_cup_network.html
File diff suppressed because it is too large
View File


+ 10053
- 0
examples/network/28_world_cup_network_performance.html
File diff suppressed because it is too large
View File


+ 10213
- 0
examples/network/29_neighbourhood_highlight.html
File diff suppressed because it is too large
View File


+ 166
- 0
examples/network/30_importing_from_gephi.html View File

@ -0,0 +1,166 @@
<!DOCTYPE html>
<!-- saved from url=(0044)http://kenedict.com/networks/worldcup14/vis/ , thanks Andre!-->
<html><head><meta http-equiv="content-type" content="text/html; charset=UTF8">
<title>Dynamic Data - Importing from Gephi (JSON)</title>
<script type="text/javascript" src="../../dist/vis.js"></script>
<link type="text/css" rel="stylesheet" href="../../dist/vis.css">
<style type="text/css">
#mynetwork {
width: 800px;
height: 800px;
border: 1px solid lightgray;
}
div.nodeContent {
position: relative;
border: 1px solid lightgray;
width:480px;
height:780px;
margin-top: -802px;
margin-left: 810px;
padding:10px;
}
pre {padding: 5px; margin: 5px; }
.string { color: green; }
.number { color: darkorange; }
.boolean { color: blue; }
.null { color: magenta; }
.key { color: red; }
</style>
</head>
<body>
<h2>Dynamic Data - Importing from Gephi (JSON)</h2>
<div style="width:700px; font-size:14px;">
This example shows how to import a JSON file exported by Gephi. The two options available for the import are
available through the checkboxes. You can download the Gephi JSON exporter here:
<a href="https://marketplace.gephi.org/plugin/json-exporter/" target="_blank">https://marketplace.gephi.org/plugin/json-exporter/</a>.
All of Gephi's attributes are also contained within the node elements. This means you can access all of this data through the DataSet.
<br />
</div>
<input type="checkbox" id="allowedToMove">: Allow to move after import. <br/>
<input type="checkbox" id="parseColor">: Parse the color instead of copy (adds borders, highlights etc.)
<div id="mynetwork"></div>
<div class="nodeContent"><h4>Node Content:</h4> <pre id="nodeContent"></pre></div>
<script type="text/javascript">
var network;
var nodes = new vis.DataSet();
var edges = new vis.DataSet();
var gephiImported;
var allowedToMoveCheckbox = document.getElementById("allowedToMove");
allowedToMoveCheckbox.onchange = redrawAll;
var parseColorCheckbox = document.getElementById("parseColor");
parseColorCheckbox.onchange = redrawAll;
var nodeContent = document.getElementById("nodeContent");
loadJSON("./data/WorldCup2014.json",redrawAll);
var container = document.getElementById('mynetwork');
var data = {
nodes: nodes,
edges: edges
};
var options = {
nodes: {
shape: 'dot',
fontFace: "Tahoma"
},
edges: {
width: 0.15,
inheritColor: "from"
},
tooltip: {
delay: 200,
fontSize: 12,
color: {
background: "#fff"
}
},
smoothCurves: {dynamic:false, type: "continuous"},
stabilize: false,
physics: {barnesHut: {gravitationalConstant: -10000, springConstant: 0.002, springLength: 150}},
hideEdgesOnDrag: true
};
network = new vis.Network(container, data, options);
/**
* This function fills the DataSets. These DataSets will update the network.
*/
function redrawAll(gephiJSON) {
if (gephiJSON.nodes === undefined) {
gephiJSON = gephiImported;
}
else {
gephiImported = gephiJSON;
}
nodes.clear();
edges.clear();
var allowedToMove = allowedToMoveCheckbox.checked;
var parseColor = parseColorCheckbox.checked;
var parsed = vis.network.gephiParser.parseGephi(gephiJSON, {allowedToMove:allowedToMove, parseColor:parseColor});
// add the parsed data to the DataSets.
nodes.add(parsed.nodes);
edges.add(parsed.edges);
var data = nodes.get(2); // get the data from node 2
nodeContent.innerHTML = syntaxHighlight(data); // show the data in the div
network.zoomExtent(); // zoom to fit
}
// from http://stackoverflow.com/questions/4810841/how-can-i-pretty-print-json-using-javascript
function syntaxHighlight(json) {
if (typeof json != 'string') {
json = JSON.stringify(json, undefined, 2);
}
json = json.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match) {
var cls = 'number';
if (/^"/.test(match)) {
if (/:$/.test(match)) {
cls = 'key';
} else {
cls = 'string';
}
} else if (/true|false/.test(match)) {
cls = 'boolean';
} else if (/null/.test(match)) {
cls = 'null';
}
return '<span class="' + cls + '">' + match + '</span>';
});
}
function loadJSON(path, success, error) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
success(JSON.parse(xhr.responseText));
}
else {
error(xhr);
}
}
};
xhr.open("GET", path, true);
xhr.send();
}
</script>
</body></html>

+ 1
- 0
examples/network/data/WorldCup2014.json
File diff suppressed because it is too large
View File


+ 5
- 0
examples/network/index.html View File

@ -37,6 +37,11 @@
<p><a href="23_hierarchical_layout.html">23_hierarchical_layout.html</a></p>
<p><a href="24_hierarchical_layout_userdefined.html">24_hierarchical_layout_userdefined.html</a></p>
<p><a href="25_physics_configuration.html">25_physics_configuration.html</a></p>
<p><a href="26_staticSmoothCurves.html">26_staticSmoothCurves.html</a></p>
<p><a href="27_world_cup_network.html">27_world_cup_network.html</a></p>
<p><a href="28_world_cup_network_performance.html">28_world_cup_network_performance.html</a></p>
<p><a href="29_neighbourhood_highlight.html">29_neighbourhood_highlight.html</a></p>
<p><a href="30_importing_from_gephi.html">30_importing_from_gephi.html</a></p>
<p><a href="graphviz/graphviz_gallery.html">graphviz_gallery.html</a></p>
</div>

+ 152
- 0
gulpfile.js View File

@ -0,0 +1,152 @@
var fs = require('fs');
var gulp = require('gulp');
var gutil = require('gulp-util');
var concat = require('gulp-concat');
var minifyCSS = require('gulp-minify-css');
var rename = require("gulp-rename");
var webpack = require('webpack');
var uglify = require('uglify-js');
var rimraf = require('rimraf');
var merge = require('merge-stream');
var argv = require('yargs').argv;
var ENTRY = './index.js';
var HEADER = './lib/header.js';
var DIST = './dist';
var VIS_JS = 'vis.js';
var VIS_MAP = 'vis.map';
var VIS_MIN_JS = 'vis.min.js';
var VIS_CSS = 'vis.css';
var VIS_MIN_CSS = 'vis.min.css';
// generate banner with today's date and correct version
function createBanner() {
var today = gutil.date(new Date(), 'yyyy-mm-dd'); // today, formatted as yyyy-mm-dd
var version = require('./package.json').version;
return String(fs.readFileSync(HEADER))
.replace('@@date', today)
.replace('@@version', version);
}
var bannerPlugin = new webpack.BannerPlugin(createBanner(), {
entryOnly: true,
raw: true
});
// TODO: the moment.js language files should be excluded by default (they are quite big)
var webpackConfig = {
entry: ENTRY,
output: {
library: 'vis',
libraryTarget: 'umd',
path: DIST,
filename: VIS_JS,
sourcePrefix: ' '
},
// exclude requires of moment.js language files
module: {
wrappedContextRegExp: /$^/
},
plugins: [ bannerPlugin ],
cache: true
};
var uglifyConfig = {
outSourceMap: VIS_MAP,
output: {
comments: /@license/
}
};
// create a single instance of the compiler to allow caching
var compiler = webpack(webpackConfig);
// clean the dist/img directory
gulp.task('clean', function (cb) {
rimraf(DIST + '/img', cb);
});
gulp.task('bundle-js', ['clean'], function (cb) {
// update the banner contents (has a date in it which should stay up to date)
bannerPlugin.banner = createBanner();
compiler.run(function (err, stats) {
if (err) gutil.log(err);
cb();
});
});
// bundle and minify css
gulp.task('bundle-css', ['clean'], function () {
var files = [
'./lib/timeline/component/css/timeline.css',
'./lib/timeline/component/css/panel.css',
'./lib/timeline/component/css/labelset.css',
'./lib/timeline/component/css/itemset.css',
'./lib/timeline/component/css/item.css',
'./lib/timeline/component/css/timeaxis.css',
'./lib/timeline/component/css/currenttime.css',
'./lib/timeline/component/css/customtime.css',
'./lib/timeline/component/css/animation.css',
'./lib/timeline/component/css/dataaxis.css',
'./lib/timeline/component/css/pathStyles.css',
'./lib/network/css/network-manipulation.css',
'./lib/network/css/network-navigation.css'
];
return gulp.src(files)
.pipe(concat(VIS_CSS))
.pipe(gulp.dest(DIST))
// TODO: nicer to put minifying css in a separate task?
.pipe(minifyCSS())
.pipe(rename(VIS_MIN_CSS))
.pipe(gulp.dest(DIST));
});
gulp.task('copy', ['clean'], function () {
var network = gulp.src('./lib/network/img/**/*')
.pipe(gulp.dest(DIST + '/img/network'));
var timeline = gulp.src('./lib/timeline/img/**/*')
.pipe(gulp.dest(DIST + '/img/timeline'));
return merge(network, timeline);
});
gulp.task('minify', ['bundle-js'], function (cb) {
var result = uglify.minify([DIST + '/' + VIS_JS], uglifyConfig);
fs.writeFileSync(DIST + '/' + VIS_MIN_JS, result.code);
fs.writeFileSync(DIST + '/' + VIS_MAP, result.map);
cb();
});
gulp.task('bundle', ['bundle-js', 'bundle-css', 'copy']);
// read command line arguments --bundle and --minify
var bundle = 'bundle' in argv;
var minify = 'minify' in argv;
var watchTasks = [];
if (bundle || minify) {
// do bundling and/or minifying only when specified on the command line
watchTasks = [];
if (bundle) watchTasks.push('bundle');
if (minify) watchTasks.push('minify');
}
else {
// by default, do both bundling and minifying
watchTasks = ['bundle', 'minify'];
}
// The watch task (to automatically rebuild when the source code changes)
gulp.task('watch', watchTasks, function () {
gulp.watch(['index.js', 'lib/**/*'], watchTasks);
});
// The default task (called when you run `gulp`)
gulp.task('default', ['clean', 'bundle', 'minify']);

+ 69
- 0
index.js View File

@ -0,0 +1,69 @@
// utils
exports.util = require('./lib/util');
exports.DOMutil = require('./lib/DOMutil');
// data
exports.DataSet = require('./lib/DataSet');
exports.DataView = require('./lib/DataView');
// Graph3d
exports.Graph3d = require('./lib/graph3d/Graph3d');
exports.graph3d = {
Camera: require('./lib/graph3d/Camera'),
Filter: require('./lib/graph3d/Filter'),
Point2d: require('./lib/graph3d/Point2d'),
Point3d: require('./lib/graph3d/Point3d'),
Slider: require('./lib/graph3d/Slider'),
StepNumber: require('./lib/graph3d/StepNumber')
};
// Timeline
exports.Timeline = require('./lib/timeline/Timeline');
exports.Graph2d = require('./lib/timeline/Graph2d');
exports.timeline = {
DataStep: require('./lib/timeline/DataStep'),
Range: require('./lib/timeline/Range'),
stack: require('./lib/timeline/Stack'),
TimeStep: require('./lib/timeline/TimeStep'),
components: {
items: {
Item: require('./lib/timeline/component/item/Item'),
ItemBox: require('./lib/timeline/component/item/ItemBox'),
ItemPoint: require('./lib/timeline/component/item/ItemPoint'),
ItemRange: require('./lib/timeline/component/item/ItemRange')
},
Component: require('./lib/timeline/component/Component'),
CurrentTime: require('./lib/timeline/component/CurrentTime'),
CustomTime: require('./lib/timeline/component/CustomTime'),
DataAxis: require('./lib/timeline/component/DataAxis'),
GraphGroup: require('./lib/timeline/component/GraphGroup'),
Group: require('./lib/timeline/component/Group'),
ItemSet: require('./lib/timeline/component/ItemSet'),
Legend: require('./lib/timeline/component/Legend'),
LineGraph: require('./lib/timeline/component/LineGraph'),
TimeAxis: require('./lib/timeline/component/TimeAxis')
}
};
// Network
exports.Network = require('./lib/network/Network');
exports.network = {
Edge: require('./lib/network/Edge'),
Groups: require('./lib/network/Groups'),
Images: require('./lib/network/Images'),
Node: require('./lib/network/Node'),
Popup: require('./lib/network/Popup'),
dotparser: require('./lib/network/dotparser'),
gephiParser: require('./lib/network/gephiParser')
};
// Deprecated since v3.0.0
exports.Graph = function () {
throw new Error('Graph is renamed to Network. Please create a graph as new vis.Network(...)');
};
// bundled external libraries
exports.moment = require('./lib/module/moment');
exports.hammer = require('./lib/module/hammer');

src/DOMutil.js → lib/DOMutil.js View File

@ -1,15 +1,11 @@
/**
* Created by Alex on 6/20/14.
*/
var DOMutil = {};
// DOM utility methods
/**
* this prepares the JSON container for allocating SVG elements
* @param JSONcontainer
* @private
*/
DOMutil.prepareElements = function(JSONcontainer) {
exports.prepareElements = function(JSONcontainer) {
// cleanup the redundant svgElements;
for (var elementType in JSONcontainer) {
if (JSONcontainer.hasOwnProperty(elementType)) {
@ -26,7 +22,7 @@ DOMutil.prepareElements = function(JSONcontainer) {
* @param JSONcontainer
* @private
*/
DOMutil.cleanupElements = function(JSONcontainer) {
exports.cleanupElements = function(JSONcontainer) {
// cleanup the redundant svgElements;
for (var elementType in JSONcontainer) {
if (JSONcontainer.hasOwnProperty(elementType)) {
@ -50,7 +46,7 @@ DOMutil.cleanupElements = function(JSONcontainer) {
* @returns {*}
* @private
*/
DOMutil.getSVGElement = function (elementType, JSONcontainer, svgContainer) {
exports.getSVGElement = function (elementType, JSONcontainer, svgContainer) {
var element;
// allocate SVG element, if it doesnt yet exist, create one.
if (JSONcontainer.hasOwnProperty(elementType)) { // this element has been created before
@ -86,7 +82,7 @@ DOMutil.getSVGElement = function (elementType, JSONcontainer, svgContainer) {
* @returns {*}
* @private
*/
DOMutil.getDOMElement = function (elementType, JSONcontainer, DOMContainer) {
exports.getDOMElement = function (elementType, JSONcontainer, DOMContainer) {
var element;
// allocate SVG element, if it doesnt yet exist, create one.
if (JSONcontainer.hasOwnProperty(elementType)) { // this element has been created before
@ -126,17 +122,17 @@ DOMutil.getDOMElement = function (elementType, JSONcontainer, DOMContainer) {
* @param svgContainer
* @returns {*}
*/
DOMutil.drawPoint = function(x, y, group, JSONcontainer, svgContainer) {
exports.drawPoint = function(x, y, group, JSONcontainer, svgContainer) {
var point;
if (group.options.drawPoints.style == 'circle') {
point = DOMutil.getSVGElement('circle',JSONcontainer,svgContainer);
point = exports.getSVGElement('circle',JSONcontainer,svgContainer);
point.setAttributeNS(null, "cx", x);
point.setAttributeNS(null, "cy", y);
point.setAttributeNS(null, "r", 0.5 * group.options.drawPoints.size);
point.setAttributeNS(null, "class", group.className + " point");
}
else {
point = DOMutil.getSVGElement('rect',JSONcontainer,svgContainer);
point = exports.getSVGElement('rect',JSONcontainer,svgContainer);
point.setAttributeNS(null, "x", x - 0.5*group.options.drawPoints.size);
point.setAttributeNS(null, "y", y - 0.5*group.options.drawPoints.size);
point.setAttributeNS(null, "width", group.options.drawPoints.size);
@ -153,8 +149,8 @@ DOMutil.drawPoint = function(x, y, group, JSONcontainer, svgContainer) {
* @param y
* @param className
*/
DOMutil.drawBar = function (x, y, width, height, className, JSONcontainer, svgContainer) {
var rect = DOMutil.getSVGElement('rect',JSONcontainer, svgContainer);
exports.drawBar = function (x, y, width, height, className, JSONcontainer, svgContainer) {
var rect = exports.getSVGElement('rect',JSONcontainer, svgContainer);
rect.setAttributeNS(null, "x", x - 0.5 * width);
rect.setAttributeNS(null, "y", y);
rect.setAttributeNS(null, "width", width);

src/DataSet.js → lib/DataSet.js View File

@ -1,3 +1,5 @@
var util = require('./util');
/**
* DataSet
*
@ -320,7 +322,8 @@ DataSet.prototype.get = function (args) {
// determine the return type
var returnType;
if (options && options.returnType) {
returnType = (options.returnType == 'DataTable') ? 'DataTable' : 'Array';
var allowedValues = ["DataTable", "Array", "Object"];
returnType = allowedValues.indexOf(options.returnType) == -1 ? "Array" : options.returnType;
if (data && (returnType != util.getType(data))) {
throw new Error('Type of parameter "data" (' + util.getType(data) + ') ' +
@ -399,12 +402,19 @@ DataSet.prototype.get = function (args) {
}
else {
// copy the items to the provided data table
for (i = 0, len = items.length; i < len; i++) {
for (i = 0; i < items.length; i++) {
me._appendRow(data, columns, items[i]);
}
}
return data;
}
else if (returnType == "Object") {
var result = {};
for (i = 0; i < items.length; i++) {
result[items[i].id] = items[i];
}
return result;
}
else {
// return an array
if (id != undefined) {
@ -932,3 +942,5 @@ DataSet.prototype._appendRow = function (dataTable, columns, item) {
dataTable.setValue(row, col, item[field]);
}
};
module.exports = DataSet;

src/DataView.js → lib/DataView.js View File

@ -1,3 +1,6 @@
var util = require('./util');
var DataSet = require('./DataSet');
/**
* DataView
*
@ -294,3 +297,5 @@ DataView.prototype._trigger = DataSet.prototype._trigger;
// TODO: make these functions deprecated (replaced with `on` and `off` since version 0.5)
DataView.prototype.subscribe = DataView.prototype.on;
DataView.prototype.unsubscribe = DataView.prototype.off;
module.exports = DataView;

+ 135
- 0
lib/graph3d/Camera.js View File

@ -0,0 +1,135 @@
var Point3d = require('./Point3d');
/**
* @class Camera
* 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
*/
Camera = function () {
this.armLocation = new Point3d();
this.armRotation = {};
this.armRotation.horizontal = 0;
this.armRotation.vertical = 0;
this.armLength = 1.7;
this.cameraLocation = new Point3d();
this.cameraRotation = new Point3d(0.5*Math.PI, 0, 0);
this.calculateCameraOrientation();
};
/**
* 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) {<