Browse Source

Merge branch 'develop' into mbroad/unittest/lib/shared

mbroad/unittest/lib/shared
MacLeod Broad 6 years ago
parent
commit
3aae9fcd08
No known key found for this signature in database GPG Key ID: F1B295D13C3CC9CF
55 changed files with 1154 additions and 434 deletions
  1. +1
    -0
      .gitignore
  2. +231
    -0
      docs/README.md
  3. +6
    -81
      docs/data/dataset.html
  4. +19
    -1
      docs/network/index.html
  5. +118
    -0
      docs/publish.js
  6. +7
    -0
      docs/timeline/index.html
  7. +40
    -0
      docs/tmpl/html-head.tmpl
  8. +49
    -0
      docs/tmpl/navbar.tmpl
  9. +3
    -1
      examples/network/nodeStyles/shapes.html
  10. +1
    -0
      examples/network/nodeStyles/shapesWithDashedBorders.html
  11. +58
    -0
      examples/timeline/other/loadingScreen.html
  12. +2
    -11
      examples/timeline/other/stressPerformance.html
  13. +26
    -3
      examples/timeline/styling/weekStyling.html
  14. +36
    -1
      gulpfile.js
  15. +3
    -0
      jsdoc.json
  16. +20
    -0
      lib/network/Network.js
  17. +3
    -2
      lib/network/modules/LayoutEngine.js
  18. +12
    -6
      lib/network/modules/components/DirectionStrategy.js
  19. +2
    -2
      lib/network/modules/components/Edge.js
  20. +1
    -1
      lib/network/modules/components/edges/BezierEdgeDynamic.js
  21. +1
    -1
      lib/network/modules/components/edges/BezierEdgeStatic.js
  22. +1
    -1
      lib/network/modules/components/edges/CubicBezierEdge.js
  23. +2
    -2
      lib/network/modules/components/edges/StraightEdge.js
  24. +4
    -4
      lib/network/modules/components/edges/util/EdgeBase.js
  25. +0
    -22
      lib/network/modules/components/edges/util/EndPoints.js
  26. +1
    -1
      lib/network/modules/components/nodes/shapes/Box.js
  27. +1
    -1
      lib/network/modules/components/nodes/shapes/Circle.js
  28. +1
    -1
      lib/network/modules/components/nodes/shapes/CircularImage.js
  29. +1
    -1
      lib/network/modules/components/nodes/shapes/Database.js
  30. +1
    -1
      lib/network/modules/components/nodes/shapes/Diamond.js
  31. +1
    -1
      lib/network/modules/components/nodes/shapes/Dot.js
  32. +1
    -1
      lib/network/modules/components/nodes/shapes/Ellipse.js
  33. +2
    -2
      lib/network/modules/components/nodes/shapes/Hexagon.js
  34. +2
    -2
      lib/network/modules/components/nodes/shapes/Icon.js
  35. +1
    -1
      lib/network/modules/components/nodes/shapes/Image.js
  36. +1
    -1
      lib/network/modules/components/nodes/shapes/Square.js
  37. +1
    -1
      lib/network/modules/components/nodes/shapes/Star.js
  38. +1
    -1
      lib/network/modules/components/nodes/shapes/Text.js
  39. +1
    -1
      lib/network/modules/components/nodes/shapes/Triangle.js
  40. +1
    -1
      lib/network/modules/components/nodes/shapes/TriangleDown.js
  41. +2
    -2
      lib/network/modules/components/nodes/util/CircleImageBase.js
  42. +7
    -7
      lib/network/modules/components/nodes/util/NodeBase.js
  43. +1
    -1
      lib/network/modules/components/nodes/util/ShapeBase.js
  44. +0
    -20
      lib/network/modules/components/shared/ComponentUtil.js
  45. +1
    -26
      lib/network/modules/components/shared/Label.js
  46. +322
    -214
      lib/network/modules/components/shared/LabelSplitter.js
  47. +97
    -0
      lib/network/typedefs.js
  48. +5
    -2
      lib/timeline/Core.js
  49. +2
    -2
      lib/timeline/TimeStep.js
  50. +22
    -1
      lib/timeline/Timeline.js
  51. +8
    -2
      lib/timeline/component/css/timeline.css
  52. +19
    -0
      lib/timeline/component/css/timeline.js
  53. +1
    -0
      lib/timeline/optionsTimeline.js
  54. +3
    -1
      package.json
  55. +1
    -0
      test/Label.test.js

+ 1
- 0
.gitignore View File

@ -16,3 +16,4 @@ npm-debug.log
# temporary files
.*.sw[op]
.commits.tmp
gen/

+ 231
- 0
docs/README.md View File

@ -0,0 +1,231 @@
# Command line usage example
```
jsdoc -c jsdoc.json -r -t docs -d gen/docs lib
```
- `-c`: use this config file for `jsdoc`
- `-r`: Recurse into subdirectories of the specified source directories
- `-t`: Use template in path `docs`
- `-d`: Generated html files put in `gen/docs`
- Source files to parse are taken from directory `lib`
## Notes
The template generation is set up so that:
- Files ending in `.tmpl` are skipped
- All non-html files are plain copied
- html-files *can* contain `<?js ?>` tags, but this is not required
## Intention
The `docs` directory is treated as a `jsdoc` template, in which the html-files are the template files. This allows for a gradual adaptation of the html-files to templates; unchanged html-files will pass through `jsdoc` unchanged.
The added value of using `jsdoc` for documentation generation, is that the complete documentation information, as collected by `jsdoc` from the source, is available for usage. This way, it's possible to insert technical notes from the source code into the documentation.
----
# Usage of and Notes on Source Code
This section contains notes on the usage of `jsdoc` functionality, to aid with the handling of its generated data.
## Parameters of `publish()`
### Parameter `taffyData`
A table containing *all* data collected from the source code, related to jsdoc generation. See below for more info and example outputs.
### Parameter `opt`
Example of `opt` variable:
```js
{
"_":["../github/vis/lib/network/"],
"configure":"jsdoc.json",
"recurse":true,
"template":"/home/wim/projects/jsdoc/default",
"destination":"./out/",
"encoding":"utf8"
}
```
### Parameter `tutorial`
This does not appear to be of use for the generation of `vis.js` documentation.
Example of `tutorial` variable:
```js
{
"longname":"",
"name":"",
"title":"",
"content":"",
"parent":null,
"children":[],
"_tutorials":{}
}
```
## Global variable `env`
This contains addition info for the current execution of `jsdoc`. Example of `env` variable:
```js
{
"run":{"start":"2017-09-16T05:06:45.621Z","finish":null},
"args":["-c","jsdoc.json","-r","-t","default","../github/vis/lib/network/"],
"conf":{
"plugins":["/usr/lib/node_modules/jsdoc/plugins/markdown.js"],
"recurseDepth":10,
"source":{"includePattern":".+\\.js(doc|x)?$","excludePattern":""},
"sourceType":"module",
"tags":{"allowUnknownTags":true,"dictionaries":["jsdoc","closure"]},
"templates":{"monospaceLinks":false,"cleverLinks":false}
},
"dirname":"/usr/lib/node_modules/jsdoc",
"pwd":"/home/wim/projects/jsdoc",
"opts":{ <<same as parameter 'opt' above>> },
"sourceFiles":[ <<list of full path names of all js-source files used as input>> ],
"version":{"number":"3.5.4","revision":"Fri, 04 Aug 2017 22:05:27 GMT"}
}
```
## taffyData
This is a parameter to `publish()`. It's a table containing *all* data collected from the source code, related to jsdoc generation.
I can't find any way to return a list of fields for the data items in the taffyDB docs, therefore below there are examples of items, for better understanding of usage.
Example usage:
```js
var data = taffyData;
var tmp = data().filter({name:'Label'}).get();
```
Returns an array with all items with `name === 'Label'`. Example output of one of these items, for a class:
*In these examples, block comment endings are redacted to ' * /'*
```js
{
"comment":"/**\n * A Label to be used for Nodes or Edges.\n * /",
"meta":{
"range":[3770,41303],
"filename":"Label.js",
"lineno":167,
"columnno":0,
"path":"/home/wim/projects/github/vis/lib/network/modules/components/shared",
"code":{
"id":"astnode100065034",
"name":"Label",
"type":"ClassDeclaration",
"paramnames":["body","options","edgelabel"]
}
},
"classdesc":"
A Label to be used for Nodes or Edges.
",
"name":"Label",
"longname":"Label",
"kind":"class",
"scope":"global",
"params":[
{"type":{"names":["Object"]},"name":"body"},
{"type":{"names":["Object"]},"name":"options"},
{"type":{"names":["boolean"]},"optional":true,"defaultvalue":false,"name":"edgelabel"}
],
"___id":"T000002R005289",
"___s":true
}
```
Example of item for an instance method:
```js
var tmp = data().filter({name:'_drawText'}).get();
```
Full output returned:
```js
[{
"comment":"/**\n *\n * @param {CanvasRenderingContext2D} ctx\n * @param {boolean} selected\n * @param {boolean} hover\n * @param {number} x\n * @param {number} y\n * @param {string} [baseline='middle']\n * @private\n * /",
"meta":{
"range":[20060,22269],
"filename":"Label.js",
"lineno":652,
"columnno":2,
"path":"/home/wim/projects/github/vis/lib/network/modules/components/shared",
"code":{
"id":"astnode100066427",
"name":"Label#_drawText",
"type":"MethodDefinition",
"paramnames":["ctx","selected","hover","x","y","baseline"]
},
"vars":{"":null}
},
"params":[
{"type":{"names":["CanvasRenderingContext2D"]},"name":"ctx"},
{"type":{"names":["boolean"]},"name":"selected"},
{"type":{"names":["boolean"]},"name":"hover"},
{"type":{"names":["number"]},"name":"x"},
{"type":{"names":["number"]},"name":"y"},
{"type":{"names":["string"]},"optional":true,"defaultvalue":"'middle'","name":"baseline"}
],
"access":"private",
"name":"_drawText",
"longname":"Label#_drawText",
"kind":"function",
"memberof":"Label",
"scope":"instance",
"___id":"T000002R005388",
"___s":true
}]
```
## `jsdoc` template rendering
See `function createRenderer(fromDir, data)` in code for usage.
There are two calls for rendering templates:
- `var html = renderer.render(inFile, docData);`
- `var html = renderer.partial(inFile, docData);`
The difference is that `render()` will use a default layout template, if present, which will encapsulate all html. This can be set by:
```js
renderer.layout = 'path/to/default/layout.tmpl';
```
Parameter `docData` is a hash which is used to pass parameters into a template. The standard way of using this appear to be:
```
<?js
var data = obj; // Whatever docData is
var self = this;
?>
```
But it also appear to be possible to use the elements of docData directly:
```js
var docData = {
myTitle: 'Hello, pussycat!'
};
```
Within the template:
```
<?js= myTitle ?>
```

+ 6
- 81
docs/data/dataset.html View File

@ -1,86 +1,11 @@
<!DOCTYPE html>
<html lang="en"><head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<link rel="icon" HREF="favicon.ico">
<title>DataSet - vis.js - A dynamic, browser based visualization library.</title>
<!-- Bootstrap core CSS -->
<link href="../css/bootstrap.css" rel="stylesheet">
<!-- Tipue vendor css -->
<link href="../css/tipuesearch.css" rel="stylesheet">
<link href="../css/style.css" rel="stylesheet">
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
<link href="../css/prettify.css" type="text/css" rel="stylesheet"/>
<script type="text/javascript" src="../js/googleAnalytics.js"></script>
<script type="text/javascript" src="../js/prettify/prettify.js"></script>
<script src="../js/smooth-scroll.min.js"></script>
<script language="JavaScript">
smoothScroll.init();
</script>
<script type="text/javascript" src="../js/toggleTable.js"></script>
<?js
var self = this;
var title = 'DataSet - vis.js - A dynamic, browser based visualization library.';
?>
<?js= self.partial('tmpl/html-head.tmpl', title) ?>
</head>
<body onload="prettyPrint();">
<div class="navbar-wrapper">
<div class="container">
<nav class="navbar navbar-inverse navbar-static-top" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar"
aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand hidden-sm" href="./index.html">vis.js</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a href="http://www.visjs.org/index.html#modules">Modules</a></li>
<li><a href="http://www.visjs.org/blog.html">Blog</a></li>
<li><a href="http://www.visjs.org/index.html#download_install">Download</a></li>
<li><a href="http://www.visjs.org/showcase/index.html">Showcase</a></li>
<li><a href="http://www.visjs.org/index.html#contribute">Contribute</a></li>
<li><a href="http://www.visjs.org/featureRequests.html">Feature requests</a></li>
<li><a href="http://www.visjs.org/index.html#licenses">License</a></li>
</ul>
<form class="navbar-form navbar-right" role="search">
<input name="q" id="tipue_search_input" autocomplete="off" type="text" class="form-control" placeholder="Enter keywords">
<button type="submit" class="btn btn-default">Go!</button>
</form>
<div id="search-results-wrapper" class="panel panel-default">
<div class="panel-body">
<div id="tipue_search_content"></div>
</div>
</div>
<div id="keyword-info" class="panel panel-success">
<div class="panel-body">
Found <span id="keyword-count"></span> results. Click <a id="keyword-jumper-button" href="">here</a> to jump to the first keyword occurence!
</div>
</div>
</div>
</div>
</nav>
</div>
</div>
<a href="https://github.com/almende/vis" class="hidden-xs hidden-sm hidden-md"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://camo.githubusercontent.com/38ef81f8aca64bb9a64448d0d70f1308ef5341ab/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f6461726b626c75655f3132313632312e706e67" alt="Fork me on GitHub" data-canonical-src="https://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png"></a>
<?js= self.partial('tmpl/navbar.tmpl', title) ?>
<div class="container full">
<h1>DataSet</h1>

+ 19
- 1
docs/network/index.html View File

@ -1,3 +1,6 @@
<?js
var self = this;
?>
<!DOCTYPE html>
<html lang="en">
<head>
@ -609,6 +612,21 @@ var locales = {
The options object is explained in full <a data-scroll="" data-options="{ &quot;easing&quot;: &quot;easeInCubic&quot; }" href="#optionsObject">below</a>.
</td>
</tr>
<?js
var comment = self.getComment("Network#findNode");
?>
<tr class="collapsible toggle" onclick="toggleTable('methodTable','findNodeNew', this);">
<td colspan="2"><span parent="findNode" class="right-caret" id="method_findNodeNew"></span>
<?js= comment.prototype ?> <b>This comes from the source!</b>
</tr>
<tr class="hidden" parent="findNodeNew">
<td class="midMethods">Returns: <?js= comment.returns ?></td>
<td>
<?js= comment.description ?>
</td>
</tr>
<tr class="collapsible toggle" onclick="toggleTable('methodTable','findNode', this);">
<td colspan="2"><span parent="findNode" class="right-caret" id="method_findNode"></span> findNode(
<code>String/Number nodeId</code>)
@ -1487,7 +1505,7 @@ Thus, to get the topmost item, get the value at index 0.
</td>
<tr><td id="event_stabilized">stabilized</td>
<td>Object</td>
<td>Fired when the network has stabilized or when the <code>stopSimulation()</code> has been called. The amount of iterations it took could be used to tweak the maximum amount of iterations needed to stabilize the network. Passes an object with properties structured as:
<td>Fired when the network has stabilized, when the amount of iterations defined in the options has been reached, or when the <code>stopSimulation()</code> has been called. The amount of iterations it took could be used to tweak the maximum amount of iterations needed to stabilize the network. Passes an object with properties structured as:
<pre class="prettyprint lang-js">{
iterations: Number // iterations it took
}</pre>

+ 118
- 0
docs/publish.js View File

@ -0,0 +1,118 @@
/*==============================================================================
Demo template, showing how documentation can be generated for `vis.js`.
------------------------------------------------------------------------------
## Notes on `jsdoc` code
// claim some special filenames in advance, so the All-Powerful Overseer of Filename Uniqueness
// doesn't try to hand them out later
indexUrl = helper.getUniqueFilename('index');
// don't call registerLink() on this one! 'index' is also a valid longname
globalUrl = helper.getUniqueFilename('global');
helper.registerLink('global', globalUrl);
============================================================================== */
'use strict';
//var taffy = require('taffydb').taffy; // not really required here, left for reference
// Internal modules of `jsdoc` are available here.
// This is not the complete list, there may be more useful stuff in jsdoc
// For all modules scan in: '/usr/lib/node_modules/jsdoc/lib/jsdoc/' (or similar on your system)
var fs = require('jsdoc/fs');
var path = require('jsdoc/path');
var template = require('jsdoc/template');
/**
* Set up the template rendering engine.
*/
function createRenderer(fromDir, data) {
var renderer = new template.Template(fromDir); // Param is the template source directory.
// All template files are relative to this directory!
/**
* Example helper method
*
* This can be called from within a template as follows:
*
* ```
* <?js
* var self = this;
* ?>
* ...
* <?js= self.helper('hello!') ?>
* ```
*
* /
renderer.helper = function(val) {
return 'this is a helper! ' + val;
};
*/
/**
* Retrieves jsdoc info for the passed instance method.
*/
renderer.getComment = function(methodName) {
var tmp = data().filter({longname: methodName}).get()[0];
//console.log(JSON.stringify(tmp));
// Some restructuring, to adapt it to the docs layout
// This needs some work to make it handle 0 and > 1 parameters
var param = tmp.params[0];
var prototype = tmp.name + '(<code>' + param.type.names.join('|') + ' ' + param.name + '</code>)';
var returns = tmp.returns[0].type.names;
return {
prototype: prototype,
returns: returns,
description: tmp.description
}
};
return renderer;
}
/**
Entry point for the template.
This is called from `jsdoc` during execution
@param {TAFFY} taffyData See <http://taffydb.com/>.
@param {object} opts
@param {Tutorial} tutorials
*/
exports.publish = function(taffyData, opts, tutorials) {
//console.log(JSON.stringify(opts, null, 2));
var fromDir = path.resolve(opts.template);
var toDir = path.join(opts.destination);
var renderer = createRenderer(fromDir, taffyData);
var docFiles = fs.ls(fromDir, 3);
docFiles.forEach(function(fileName) {
// Template filenames need to be relative to template source dir
var relName = path.relative(fromDir, fileName);
var outFile = path.join(toDir, relName);
if (/publish.js$/.test(fileName)) return; // Skip self
if (/README.md$/.test(fileName)) return; // Skip own README
if (/\.tmpl$/.test(fileName)) return; // Skip .tmpl files; these are used as partials only
if (!/\.html$/.test(fileName)) {
// Just plain copy over non-html files
var tmpDir = fs.toDir(outFile);
fs.mkPath(tmpDir);
fs.copyFileSync(fileName, tmpDir);
return;
}
// Render html files as templates
//console.log(relName);
var html = renderer.partial(relName, {});
fs.mkPath(fs.toDir(outFile));
fs.writeFileSync(outFile, html, 'utf8');
});
//console.log(JSON.stringify(env, null, 2));
};

+ 7
- 0
docs/timeline/index.html View File

@ -773,6 +773,13 @@ function (option, path) {
<td>If true, range of all items in the Timeline is draggable without being selected. If false, range is only draggable for the selected item(s). Only applicable when option <code>itemsAlwaysDraggable.item</code> is set <code>true</code>. </td>
</tr>
<tr>
<td>loadingScreenTemplate</td>
<td>function</td>
<td>none</td>
<td>A template function used to generate the timeline initial loading screen. See section <a href="#Templates">Templates</a> for a detailed explanation.</td>
</tr>
<tr>
<td>locale</td>
<td>String</td>

+ 40
- 0
docs/tmpl/html-head.tmpl View File

@ -0,0 +1,40 @@
<?js
var title = obj;
var self = this;
?>
<!DOCTYPE html>
<html lang="en"><head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<link rel="icon" HREF="favicon.ico">
<title><?js= title ?></title>
<!-- Bootstrap core CSS -->
<link href="../css/bootstrap.css" rel="stylesheet">
<!-- Tipue vendor css -->
<link href="../css/tipuesearch.css" rel="stylesheet">
<link href="../css/style.css" rel="stylesheet">
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
<link href="../css/prettify.css" type="text/css" rel="stylesheet"/>
<script type="text/javascript" src="../js/googleAnalytics.js"></script>
<script type="text/javascript" src="../js/prettify/prettify.js"></script>
<script src="../js/smooth-scroll.min.js"></script>
<script language="JavaScript">
smoothScroll.init();
</script>
<script type="text/javascript" src="../js/toggleTable.js"></script>
<?js /* end tag '</head>' purposely missing here, so that more stuff can be added to header */ ?>

+ 49
- 0
docs/tmpl/navbar.tmpl View File

@ -0,0 +1,49 @@
<?js
var title = obj;
var self = this;
?>
<div class="navbar-wrapper">
<div class="container">
<nav class="navbar navbar-inverse navbar-static-top" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar"
aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand hidden-sm" href="./index.html">vis.js</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a href="http://www.visjs.org/index.html#modules">Modules</a></li>
<li><a href="http://www.visjs.org/blog.html">Blog</a></li>
<li><a href="http://www.visjs.org/index.html#download_install">Download</a></li>
<li><a href="http://www.visjs.org/showcase/index.html">Showcase</a></li>
<li><a href="http://www.visjs.org/index.html#contribute">Contribute</a></li>
<li><a href="http://www.visjs.org/featureRequests.html">Feature requests</a></li>
<li><a href="http://www.visjs.org/index.html#licenses">License</a></li>
</ul>
<form class="navbar-form navbar-right" role="search">
<input name="q" id="tipue_search_input" autocomplete="off" type="text" class="form-control" placeholder="Enter keywords">
<button type="submit" class="btn btn-default">Go!</button>
</form>
<div id="search-results-wrapper" class="panel panel-default">
<div class="panel-body">
<div id="tipue_search_content"></div>
</div>
</div>
<div id="keyword-info" class="panel panel-success">
<div class="panel-body">
Found <span id="keyword-count"></span> results. Click <a id="keyword-jumper-button" href="">here</a> to jump to the first keyword occurence!
</div>
</div>
</div>
</div>
</nav>
</div>
</div>
<a href="https://github.com/almende/vis" class="hidden-xs hidden-sm hidden-md"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://camo.githubusercontent.com/38ef81f8aca64bb9a64448d0d70f1308ef5341ab/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f6461726b626c75655f3132313632312e706e67" alt="Fork me on GitHub" data-canonical-src="https://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png"></a>

+ 3
- 1
examples/network/nodeStyles/shapes.html View File

@ -32,6 +32,7 @@
{id: 9, label: 'triangleDown', shape: 'triangleDown'},
{id: 10, label: 'text', shape: 'text'},
{id: 11, label: 'star', shape: 'star'},
{id: 12, label: 'hexagon', shape: 'hexagon'},
{id: 21, font:{size:30}, label: 'big circle', shape: 'circle' },
{id: 22, font:{size:30}, label: 'big ellipse', shape: 'ellipse'},
{id: 23, font:{size:30}, label: 'ellipse with a long label text', shape: 'ellipse'},
@ -43,7 +44,8 @@
{id: 29, font:{size:30}, size:40, label: 'big triangle',shape: 'triangle'},
{id: 30, font:{size:30}, size:40, label: 'big triangleDown', shape: 'triangleDown'},
{id: 31, font:{size:30}, label: 'big text', shape: 'text'},
{id: 32, font:{size:30}, size:40, label: 'big star', shape: 'star'}
{id: 32, font:{size:30}, size:40, label: 'big star', shape: 'star'},
{id: 33, font:{size:30}, size:40, label: 'big hexagon', shape: 'hexagon'},
];
edges = [

+ 1
- 0
examples/network/nodeStyles/shapesWithDashedBorders.html View File

@ -32,6 +32,7 @@
{id: 9, font:{size:30}, size:40, label: 'triangleDown', shape: 'triangleDown', shapeProperties:{borderDashes:[5,5]}},
{id: 10, font:{size:30}, size:40, label: 'star', shape: 'star', shapeProperties:{borderDashes:true}},
{id: 11, font:{size:30}, size:40, label: 'circularImage', shape: 'circularImage', image: '../img/indonesia/4.png', shapeProperties: {borderDashes:[15,5]}},
{id: 12, font:{size:30}, size:40, label: 'hexagon', shape: 'hexagon', shapeProperties:{borderDashes:[5,5]}},
];
edges = [

+ 58
- 0
examples/timeline/other/loadingScreen.html View File

@ -0,0 +1,58 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Timeline | Loading screen example</title>
<script src="http://cdnjs.cloudflare.com/ajax/libs/moment.js/2.8.4/moment.min.js"></script>
<script src="../../../dist/vis.js"></script>
<link href="../../../dist/vis-timeline-graph2d.min.css" rel="stylesheet" type="text/css" />
</head>
<body>
<h1>Timeline with loading screen</h1>
<div id="visualization"></div>
</body>
<script>
var now = moment();
var groupCount = 20;
var itemCount = 400;
// create a data set with groups
var groups = new vis.DataSet();
for (var g = 0; g < groupCount; g++) {
groups.add({
id: g,
content: "group " + g
});
}
var types = ['point', 'range', 'box', 'background']
// create a dataset with items
var items = new vis.DataSet();
for (var i = 0; i < itemCount; i++) {
var start = now.clone().add(Math.random() * 180, 'days');
var end = start.clone().add(Math.random() * 30, 'days');
var group = Math.floor(Math.random() * groupCount);
items.add({
id: i,
type: types[Math.floor(Math.random() * types.length)],
group: group,
content: '' + i,
start: start,
end: end
});
}
// create visualization
var container = document.getElementById('visualization');
var options = {
loadingScreenTemplate: function() {
return '<h1>Loading...</h1>'
}
};
var timeline = new vis.Timeline(container, items, groups, options);
</script>
</html>

+ 2
- 11
examples/timeline/other/stressPerformance.html View File

@ -49,18 +49,9 @@
// create visualization
var container = document.getElementById('visualization');
var options = {
width: '100%',
showCurrentTime: false,
stack: true,
selectable: true,
editable: true,
};
var options = {};
var timeline = new vis.Timeline(container);
timeline.setOptions(options);
timeline.setGroups(groups);
timeline.setItems(items);
var timeline = new vis.Timeline(container, items, groups, options);
</script>
</html>

+ 26
- 3
examples/timeline/styling/weekStyling.html View File

@ -26,7 +26,21 @@
of moment.js including locales.</p>
<p>To set a locale for the timeline, specify the option
<code>{locale: STRING}</code>.</p>
<p>To set the scale to use week numbers, use for example <code>{scale: 'week', step: 1}</code>.</p>
<p>
To set the scale to use week numbers, use the following options:
<code>
{
timeAxis: {
scale: 'week',
step: 1
},
format: {
minorLabels: {week: 'w'}
}
}
</code>
</p>
<p>The following timeline is initialized with the 'de' locale and items are added with locally localized moment.js
objects. The timeline locale can be switched to another locale at runtime. If you choose the 'en' locale, the week
numbers will be calculated according to the US week calendar numbering scheme.</p>
@ -93,7 +107,16 @@
}
// Configuration for the Timeline
var options = {timeAxis: {scale: 'week', step: 1}, locale: 'de'};
var options = {
locale: 'de',
timeAxis: {
scale: 'week',
step: 1
},
format: {
minorLabels: {week: 'w'}
}
};
// Create a Timeline
var timeline = new vis.Timeline(container, items, groups, options);
@ -108,4 +131,4 @@
select.onchange();
</script>
</body>
</html>
</html>

+ 36
- 1
gulpfile.js View File

@ -10,6 +10,7 @@ var webpack = require('webpack');
var uglify = require('uglify-js');
var rimraf = require('rimraf');
var argv = require('yargs').argv;
var child_exec = require('child_process').exec;
var ENTRY = './index.js';
var HEADER = './lib/header.js';
@ -29,7 +30,12 @@ var INDIVIDUAL_CSS_BUNDLES = [
{entry: ['./lib/shared/**/*.css', './lib/network/**/*.css'], filename: 'vis-network.min.css'}
];
// generate banner with today's date and correct version
/**
* Generate banner with today's date and correct version
*
* @returns {string} banner text
*/
function createBanner() {
var today = gutil.date(new Date(), 'yyyy-mm-dd'); // today, formatted as yyyy-mm-dd
var version = require('./package.json').version;
@ -39,6 +45,7 @@ function createBanner() {
.replace('@@version', version);
}
var bannerPlugin = new webpack.BannerPlugin({
banner: createBanner(),
entryOnly: true,
@ -92,6 +99,12 @@ var uglifyConfig = {
// create a single instance of the compiler to allow caching
var compiler = webpack(webpackConfig);
/**
* Callback for handling errors for a compiler run
*
* @param {object} err
* @param {objects} stats
*/
function handleCompilerCallback (err, stats) {
if (err) {
gutil.log(err.toString());
@ -232,5 +245,27 @@ gulp.task('lint', function () {
});
// Generate the documentation files
gulp.task('docs', function(cb) {
var targetDir = 'gen/docs';
// Not sure if this is the best way to handle 'cb'; at least it works.
var hasError = false;
var onError = function(error) {
if (error !== undefined && error !== null) {
console.error('Error while running task: ' + error);
hasError = true;
cb();
}
}
rimraf(__dirname + '/' + targetDir, onError); // Clean up previous generation
if (!hasError) {
var params = '-c ./jsdoc.json -r -t docs -d ' + targetDir;
child_exec('node ./node_modules/jsdoc/jsdoc.js ' + params + ' lib', undefined, cb);
}
});
// The default task (called when you run `gulp`)
gulp.task('default', ['clean', 'bundle', 'minify']);

+ 3
- 0
jsdoc.json View File

@ -0,0 +1,3 @@
{
"plugins": ["plugins/markdown"]
}

+ 20
- 0
lib/network/Network.js View File

@ -470,7 +470,27 @@ Network.prototype.isActive = function () {
Network.prototype.setSize = function() {return this.canvas.setSize.apply(this.canvas,arguments);};
Network.prototype.canvasToDOM = function() {return this.canvas.canvasToDOM.apply(this.canvas,arguments);};
Network.prototype.DOMtoCanvas = function() {return this.canvas.DOMtoCanvas.apply(this.canvas,arguments);};
/**
* Nodes can be in clusters. Clusters can also be in clusters. This function returns and array of
* nodeIds showing where the node is.
*
* If any nodeId in the chain, especially the first passed in as a parameter, is not present in
* the current nodes list, an empty array is returned.
*
* Example:
* cluster 'A' contains cluster 'B',
* cluster 'B' contains cluster 'C',
* cluster 'C' contains node 'fred'.
* `jsnetwork.clustering.findNode('fred')` will return `['A','B','C','fred']`.
*
* @param {string|number} nodeId
* @returns {Array}
*/
Network.prototype.findNode = function() {return this.clustering.findNode.apply(this.clustering,arguments);};
Network.prototype.isCluster = function() {return this.clustering.isCluster.apply(this.clustering,arguments);};
Network.prototype.openCluster = function() {return this.clustering.openCluster.apply(this.clustering,arguments);};
Network.prototype.cluster = function() {return this.clustering.cluster.apply(this.clustering,arguments);};

+ 3
- 2
lib/network/modules/LayoutEngine.js View File

@ -1,4 +1,3 @@
'use strict';
/**
* There's a mix-up with terms in the code. Following are the formal definitions:
*
@ -30,6 +29,8 @@
* The layout is a way to arrange the nodes in the view; this can be done
* on non-hierarchical networks as well. The converse is also possible.
*/
'use strict';
var TimSort = require('timsort');
let util = require('../../util');
var NetworkUtil = require('../NetworkUtil').default;
var {HorizontalStrategy, VerticalStrategy} = require('./components/DirectionStrategy.js');
@ -1422,7 +1423,7 @@ class LayoutEngine {
result.push(Number(size));
});
result.sort(function(a, b) {
TimSort.sort(result, function(a, b) {
return b - a;
});

+ 12
- 6
lib/network/modules/components/DirectionStrategy.js View File

@ -3,6 +3,7 @@
*
* Strategy pattern for usage of direction methods for hierarchical layouts.
*/
var TimSort = require('timsort');
/**
@ -87,6 +88,15 @@ class DirectionInterface {
/**
* Sort array of nodes on the unfixed coordinates.
*
* **Note:** chrome has non-stable sorting implementation, which
* has a tendency to change the order of the array items,
* even if the custom sort function returns 0.
*
* For this reason, an external sort implementation is used,
* which has the added benefit of being faster than the standard
* platforms implementation. This has been verified on `node.js`,
* `firefox` and `chrome` (all linux).
*
* @param {Array.<Node>} nodeArray array of nodes to sort
*/
sort(nodeArray) { this.fake_use(nodeArray); this.abstract(); }
@ -156,9 +166,7 @@ class VerticalStrategy extends DirectionInterface {
/** @inheritdoc */
sort(nodeArray) {
nodeArray.sort(function(a, b) {
// Test on 'undefined' takes care of divergent behaviour in chrome
if (a.x === undefined || b.x === undefined) return 0; // THIS HAPPENS
TimSort.sort(nodeArray, function(a, b) {
return a.x - b.x;
});
}
@ -221,9 +229,7 @@ class HorizontalStrategy extends DirectionInterface {
/** @inheritdoc */
sort(nodeArray) {
nodeArray.sort(function(a, b) {
// Test on 'undefined' takes care of divergent behaviour in chrome
if (a.y === undefined || b.y === undefined) return 0; // THIS HAPPENS
TimSort.sort(nodeArray, function(a, b) {
return a.y - b.y;
});
}

+ 2
- 2
lib/network/modules/components/Edge.js View File

@ -241,7 +241,7 @@ class Edge {
/**
*
* @returns {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}}
* @returns {ArrowOptions}
*/
getFormattingValues() {
let toArrow = (this.options.arrows.to === true) || (this.options.arrows.to.enabled === true)
@ -545,7 +545,7 @@ class Edge {
*
* @param {CanvasRenderingContext2D} ctx
* @param {Object} arrowData
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
* @param {ArrowOptions} values
*/
drawArrows(ctx, arrowData, values) {
if (values.fromArrow) {

+ 1
- 1
lib/network/modules/components/edges/BezierEdgeDynamic.js View File

@ -122,7 +122,7 @@ class BezierEdgeDynamic extends BezierEdgeBase {
/**
* Draw a line between two nodes
* @param {CanvasRenderingContext2D} ctx
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
* @param {ArrowOptions} values
* @param {Node} viaNode
* @private
*/

+ 1
- 1
lib/network/modules/components/edges/BezierEdgeStatic.js View File

@ -19,7 +19,7 @@ class BezierEdgeStatic extends BezierEdgeBase {
/**
* Draw a line between two nodes
* @param {CanvasRenderingContext2D} ctx
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
* @param {ArrowOptions} values
* @param {Node} viaNode
* @private
*/

+ 1
- 1
lib/network/modules/components/edges/CubicBezierEdge.js View File

@ -19,7 +19,7 @@ class CubicBezierEdge extends CubicBezierEdgeBase {
/**
* Draw a line between two nodes
* @param {CanvasRenderingContext2D} ctx
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
* @param {ArrowOptions} values
* @param {Array.<Node>} viaNodes
* @private
*/

+ 2
- 2
lib/network/modules/components/edges/StraightEdge.js View File

@ -18,7 +18,7 @@ class StraightEdge extends EdgeBase {
/**
* Draw a line between two nodes
* @param {CanvasRenderingContext2D} ctx
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
* @param {ArrowOptions} values
* @private
*/
_line(ctx, values) {
@ -100,4 +100,4 @@ class StraightEdge extends EdgeBase {
}
export default StraightEdge;
export default StraightEdge;

+ 4
- 4
lib/network/modules/components/edges/util/EdgeBase.js View File

@ -322,7 +322,7 @@ class EdgeBase {
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
* @param {ArrowOptions} values
* @param {boolean} selected - Unused
* @param {boolean} hover - Unused
* @returns {string}
@ -544,7 +544,7 @@ class EdgeBase {
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
* @param {ArrowOptions} values
* @param {boolean} selected
* @param {boolean} hover
* @param {Object} arrowData
@ -568,7 +568,7 @@ class EdgeBase {
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
* @param {ArrowOptions} values
*/
enableShadow(ctx, values) {
if (values.shadow === true) {
@ -582,7 +582,7 @@ class EdgeBase {
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
* @param {ArrowOptions} values
*/
disableShadow(ctx, values) {
if (values.shadow === true) {

+ 0
- 22
lib/network/modules/components/edges/util/EndPoints.js View File

@ -25,28 +25,6 @@
* `edgeStyles/arrowTypes`.
* ============================================================================= */
// NOTE: When a typedef is isolated in a separate comment block, an actual description is generated for it,
// using the rest of the commenting in the code block. Usage of typedef in other comments then
// link to there. TIL.
//
// Also noteworthy, all typedef's set up in this manner are collected in a single, global page 'global.html'.
// In other words, it doesn't matter *where* the typedef's are defined in the code.
//
//
// TODO: add descriptive commenting to given typedef's
/**
* @typedef {{type:string, point:Point, angle:number, length:number}} ArrowData
*
* Object containing instantiation data for a given endpoint.
*/
/**
* @typedef {{x:number, y:number}} Point
*
* A point in view-coordinates.
*/
/**
* Common methods for endpoints
*

+ 1
- 1
lib/network/modules/components/nodes/shapes/Box.js View File

@ -41,7 +41,7 @@ class Box extends NodeBase {
* @param {number} y height
* @param {boolean} selected
* @param {boolean} hover
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
* @param {ArrowOptions} values
*/
draw(ctx, x, y, selected, hover, values) {
this.resize(ctx, selected, hover);

+ 1
- 1
lib/network/modules/components/nodes/shapes/Circle.js View File

@ -45,7 +45,7 @@ class Circle extends CircleImageBase {
* @param {number} y height
* @param {boolean} selected
* @param {boolean} hover
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
* @param {ArrowOptions} values
*/
draw(ctx, x, y, selected, hover, values) {
this.resize(ctx, selected, hover);

+ 1
- 1
lib/network/modules/components/nodes/shapes/CircularImage.js View File

@ -53,7 +53,7 @@ class CircularImage extends CircleImageBase {
* @param {number} y height
* @param {boolean} selected
* @param {boolean} hover
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
* @param {ArrowOptions} values
*/
draw(ctx, x, y, selected, hover, values) {
this.switchImages(selected);

+ 1
- 1
lib/network/modules/components/nodes/shapes/Database.js View File

@ -42,7 +42,7 @@ class Database extends NodeBase {
* @param {number} y height
* @param {boolean} selected
* @param {boolean} hover
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
* @param {ArrowOptions} values
*/
draw(ctx, x, y, selected, hover, values) {
this.resize(ctx, selected, hover);

+ 1
- 1
lib/network/modules/components/nodes/shapes/Diamond.js View File

@ -24,7 +24,7 @@ class Diamond extends ShapeBase {
* @param {number} y height
* @param {boolean} selected
* @param {boolean} hover
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
* @param {ArrowOptions} values
*/
draw(ctx, x, y, selected, hover, values) {
this._drawShape(ctx, 'diamond', 4, x, y, selected, hover, values);

+ 1
- 1
lib/network/modules/components/nodes/shapes/Dot.js View File

@ -24,7 +24,7 @@ class Dot extends ShapeBase {
* @param {number} y height
* @param {boolean} selected
* @param {boolean} hover
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
* @param {ArrowOptions} values
*/
draw(ctx, x, y, selected, hover, values) {
this._drawShape(ctx, 'circle', 2, x, y, selected, hover, values);

+ 1
- 1
lib/network/modules/components/nodes/shapes/Ellipse.js View File

@ -40,7 +40,7 @@ class Ellipse extends NodeBase {
* @param {number} y height
* @param {boolean} selected
* @param {boolean} hover
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
* @param {ArrowOptions} values
*/
draw(ctx, x, y, selected, hover, values) {
this.resize(ctx, selected, hover);

+ 2
- 2
lib/network/modules/components/nodes/shapes/Hexagon.js View File

@ -24,7 +24,7 @@ class Hexagon extends ShapeBase {
* @param {number} y height
* @param {boolean} selected
* @param {boolean} hover
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
* @param {ArrowOptions} values
*/
draw(ctx, x, y, selected, hover, values) {
this._drawShape(ctx, 'hexagon', 4, x, y, selected, hover, values);
@ -41,4 +41,4 @@ class Hexagon extends ShapeBase {
}
}
export default Hexagon;
export default Hexagon;

+ 2
- 2
lib/network/modules/components/nodes/shapes/Icon.js View File

@ -43,7 +43,7 @@ class Icon extends NodeBase {
* @param {number} y height
* @param {boolean} selected
* @param {boolean} hover
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
* @param {ArrowOptions} values
*/
draw(ctx, x, y, selected, hover, values) {
this.resize(ctx, selected, hover);
@ -88,7 +88,7 @@ class Icon extends NodeBase {
* @param {number} y height
* @param {boolean} selected
* @param {boolean} hover - Unused
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
* @param {ArrowOptions} values
*/
_icon(ctx, x, y, selected, hover, values) {
let iconSize = Number(this.options.icon.size);

+ 1
- 1
lib/network/modules/components/nodes/shapes/Image.js View File

@ -52,7 +52,7 @@ class Image extends CircleImageBase {
* @param {number} y height
* @param {boolean} selected
* @param {boolean} hover
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
* @param {ArrowOptions} values
*/
draw(ctx, x, y, selected, hover, values) {
this.switchImages(selected);

+ 1
- 1
lib/network/modules/components/nodes/shapes/Square.js View File

@ -24,7 +24,7 @@ class Square extends ShapeBase {
* @param {number} y height
* @param {boolean} selected
* @param {boolean} hover
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
* @param {ArrowOptions} values
*/
draw(ctx, x, y, selected, hover, values) {
this._drawShape(ctx, 'square', 2, x, y, selected, hover, values);

+ 1
- 1
lib/network/modules/components/nodes/shapes/Star.js View File

@ -24,7 +24,7 @@ class Star extends ShapeBase {
* @param {number} y height
* @param {boolean} selected
* @param {boolean} hover
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
* @param {ArrowOptions} values
*/
draw(ctx, x, y, selected, hover, values) {
this._drawShape(ctx, 'star', 4, x, y, selected, hover, values);

+ 1
- 1
lib/network/modules/components/nodes/shapes/Text.js View File

@ -40,7 +40,7 @@ class Text extends NodeBase {
* @param {number} y height
* @param {boolean} selected
* @param {boolean} hover
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
* @param {ArrowOptions} values
*/
draw(ctx, x, y, selected, hover, values) {
this.resize(ctx, selected, hover);

+ 1
- 1
lib/network/modules/components/nodes/shapes/Triangle.js View File

@ -24,7 +24,7 @@ class Triangle extends ShapeBase {
* @param {number} y
* @param {boolean} selected
* @param {boolean} hover
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
* @param {ArrowOptions} values
*/
draw(ctx, x, y, selected, hover, values) {
this._drawShape(ctx, 'triangle', 3, x, y, selected, hover, values);

+ 1
- 1
lib/network/modules/components/nodes/shapes/TriangleDown.js View File

@ -24,7 +24,7 @@ class TriangleDown extends ShapeBase {
* @param {number} y
* @param {boolean} selected
* @param {boolean} hover
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
* @param {ArrowOptions} values
*/
draw(ctx, x, y, selected, hover, values) {
this._drawShape(ctx, 'triangleDown', 3, x, y, selected, hover, values);

+ 2
- 2
lib/network/modules/components/nodes/util/CircleImageBase.js View File

@ -124,7 +124,7 @@ class CircleImageBase extends NodeBase {
* @param {CanvasRenderingContext2D} ctx
* @param {number} x width
* @param {number} y height
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
* @param {ArrowOptions} values
* @private
*/
_drawRawCircle(ctx, x, y, values) {
@ -136,7 +136,7 @@ class CircleImageBase extends NodeBase {
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
* @param {ArrowOptions} values
* @private
*/
_drawImageAtPosition(ctx, values) {

+ 7
- 7
lib/network/modules/components/nodes/util/NodeBase.js View File

@ -70,7 +70,7 @@ class NodeBase {
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
* @param {ArrowOptions} values
*/
enableShadow(ctx, values) {
if (values.shadow) {
@ -84,7 +84,7 @@ class NodeBase {
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
* @param {ArrowOptions} values
*/
disableShadow(ctx, values) {
if (values.shadow) {
@ -98,7 +98,7 @@ class NodeBase {
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
* @param {ArrowOptions} values
*/
enableBorderDashes(ctx, values) {
if (values.borderDashes !== false) {
@ -120,7 +120,7 @@ class NodeBase {
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
* @param {ArrowOptions} values
*/
disableBorderDashes(ctx, values) {
if (values.borderDashes !== false) {
@ -157,7 +157,7 @@ class NodeBase {
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
* @param {ArrowOptions} values
*/
initContextForDraw(ctx, values) {
var borderWidth = values.borderWidth / this.body.view.scale;
@ -170,7 +170,7 @@ class NodeBase {
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
* @param {ArrowOptions} values
*/
performStroke(ctx, values) {
var borderWidth = values.borderWidth / this.body.view.scale;
@ -191,7 +191,7 @@ class NodeBase {
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
* @param {ArrowOptions} values
*/
performFill(ctx, values) {
// draw shadow if enabled

+ 1
- 1
lib/network/modules/components/nodes/util/ShapeBase.js View File

@ -41,7 +41,7 @@ class ShapeBase extends NodeBase {
* @param {number} y
* @param {boolean} selected
* @param {boolean} hover
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
* @param {ArrowOptions} values
* @private
*/
_drawShape(ctx, shape, sizeMultiplier, x, y, selected, hover, values) {

+ 0
- 20
lib/network/modules/components/shared/ComponentUtil.js View File

@ -1,23 +1,3 @@
/**
* Definitions for param's in jsdoc.
* These are more or less global within Network. Putting them here until I can figure out
* where to really put them
*
* @typedef {string|number} Id
* @typedef {Id} NodeId
* @typedef {Id} EdgeId
* @typedef {Id} LabelId
*
* @typedef {{x: number, y: number}} point
* @typedef {{left: number, top: number, width: number, height: number}} rect
* @typedef {{x: number, y:number, angle: number}} rotationPoint
* - point to rotate around and the angle in radians to rotate. angle == 0 means no rotation
* @typedef {{nodeId:NodeId}} nodeClickItem
* @typedef {{nodeId:NodeId, labelId:LabelId}} nodeLabelClickItem
* @typedef {{edgeId:EdgeId}} edgeClickItem
* @typedef {{edgeId:EdgeId, labelId:LabelId}} edgeLabelClickItem
*/
let util = require("../../../../util");
/**

+ 1
- 26
lib/network/modules/components/shared/Label.js View File

@ -2,32 +2,6 @@ let util = require('../../../../util');
let ComponentUtil = require('./ComponentUtil').default;
let LabelSplitter = require('./LabelSplitter').default;
/**
* @typedef {'bold'|'ital'|'boldital'|'mono'|'normal'} MultiFontStyle
*
* The allowed specifiers of multi-fonts.
*/
/**
* @typedef {{color:string, size:number, face:string, mod:string, vadjust:number}} MultiFontOptions
*
* The full set of options of a given multi-font.
*/
/**
* @typedef {Array.<object>} Pile
*
* Sequence of option objects, the order is significant.
* The sequence is used to determine the value of a given option.
*
* Usage principles:
*
* - All search is done in the sequence of the pile.
* - As soon as a value is found, the searching stops.
* - prototypes are totally ignored. The idea is to add option objects used as prototypes
* to the pile, in the correct order.
*/
/**
* List of special styles for multi-fonts
@ -35,6 +9,7 @@ let LabelSplitter = require('./LabelSplitter').default;
*/
const multiFontStyle = ['bold', 'ital', 'boldital', 'mono'];
/**
* A Label to be used for Nodes or Edges.
*/

+ 322
- 214
lib/network/modules/components/shared/LabelSplitter.js View File

@ -1,6 +1,274 @@
let LabelAccumulator = require('./LabelAccumulator').default;
let ComponentUtil = require('./ComponentUtil').default;
// Hash of prepared regexp's for tags
var tagPattern = {
// HTML
'<b>': /<b>/,
'<i>': /<i>/,
'<code>': /<code>/,
'</b>': /<\/b>/,
'</i>': /<\/i>/,
'</code>': /<\/code>/,
// Markdown
'*': /\*/, // bold
'_': /\_/, // ital
'`': /`/, // mono
'afterBold': /[^\*]/,
'afterItal': /[^_]/,
'afterMono': /[^`]/,
};
/**
* Internal helper class for parsing the markup tags for HTML and Markdown.
*
* NOTE: Sequences of tabs and spaces are reduced to single space.
* Scan usage of `this.spacing` within method
*/
class MarkupAccumulator {
/**
* Create an instance
*
* @param {string} text text to parse for markup
*/
constructor(text) {
this.text = text;
this.bold = false;
this.ital = false;
this.mono = false;
this.spacing = false;
this.position = 0;
this.buffer = "";
this.modStack = [];
this.blocks = [];
}
/**
* Return the mod label currently on the top of the stack
*
* @returns {string} label of topmost mod
* @private
*/
mod() {
return (this.modStack.length === 0) ? 'normal' : this.modStack[0];
}
/**
* Return the mod label currently active
*
* @returns {string} label of active mod
* @private
*/
modName() {
if (this.modStack.length === 0)
return 'normal';
else if (this.modStack[0] === 'mono')
return 'mono';
else {
if (this.bold && this.ital) {
return 'boldital';
} else if (this.bold) {
return 'bold';
} else if (this.ital) {
return 'ital';
}
}
}
/**
* @private
*/
emitBlock() {
if (this.spacing) {
this.add(" ");
this.spacing = false;
}
if (this.buffer.length > 0) {
this.blocks.push({ text: this.buffer, mod: this.modName() });
this.buffer = "";
}
}
/**
* Output text to buffer
*
* @param {string} text text to add
* @private
*/
add(text) {
if (text === " ") {
this.spacing = true;
}
if (this.spacing) {
this.buffer += " ";
this.spacing = false;
}
if (text != " ") {
this.buffer += text;
}
}
/**
* Handle parsing of whitespace
*
* @param {string} ch the character to check
* @returns {boolean} true if the character was processed as whitespace, false otherwise
*/
parseWS(ch) {
if (/[ \t]/.test(ch)) {
if (!this.mono) {
this.spacing = true;
} else {
this.add(ch);
}
return true;
}
return false;
}
/**
* @param {string} tagName label for block type to set
* @private
*/
setTag(tagName) {
this.emitBlock();
this[tagName] = true;
this.modStack.unshift(tagName);
}
/**
* @param {string} tagName label for block type to unset
* @private
*/
unsetTag(tagName) {
this.emitBlock();
this[tagName] = false;
this.modStack.shift();
}
/**
* @param {string} tagName label for block type we are currently processing
* @param {string|RegExp} tag string to match in text
* @returns {boolean} true if the tag was processed, false otherwise
*/
parseStartTag(tagName, tag) {
// Note: if 'mono' passed as tagName, there is a double check here. This is OK
if (!this.mono && !this[tagName] && this.match(tag)) {
this.setTag(tagName);
return true;
}
return false;
}
/**
* @param {string|RegExp} tag
* @param {number} [advance=true] if set, advance current position in text
* @returns {boolean} true if match at given position, false otherwise
* @private
*/
match(tag, advance = true) {
let [regExp, length] = this.prepareRegExp(tag);
let matched = regExp.test(this.text.substr(this.position, length));
if (matched && advance) {
this.position += length - 1;
}
return matched;
}
/**
* @param {string} tagName label for block type we are currently processing
* @param {string|RegExp} tag string to match in text
* @param {RegExp} [nextTag] regular expression to match for characters *following* the current tag
* @returns {boolean} true if the tag was processed, false otherwise
*/
parseEndTag(tagName, tag, nextTag) {
let checkTag = (this.mod() === tagName);
if (tagName === 'mono') { // special handling for 'mono'
checkTag = checkTag && this.mono;
} else {
checkTag = checkTag && !this.mono;
}
if (checkTag && this.match(tag)) {
if (nextTag !== undefined) {
// Purpose of the following match is to prevent a direct unset/set of a given tag
// E.g. '*bold **still bold*' => '*bold still bold*'
if ((this.position === this.text.length-1) || this.match(nextTag, false)) {
this.unsetTag(tagName);
}
} else {
this.unsetTag(tagName);
}
return true;
}
return false;
}
/**
* @param {string|RegExp} tag string to match in text
* @param {value} value string to replace tag with, if found at current position
* @returns {boolean} true if the tag was processed, false otherwise
*/
replace(tag, value) {
if (this.match(tag)) {
this.add(value);
this.position += length - 1;
return true;
}
return false;
}
/**
* Create a regular expression for the tag if it isn't already one.
*
* @param {string|RegExp} tag string to match in text
* @returns {[RegExp, number]} regular expression to use and length of input string to match
* @private
*/
prepareRegExp(tag) {
let length;
let regExp;
if (tag instanceof RegExp) {
regExp = tag;
length = 1; // ASSUMPTION: regexp only tests one character
} else {
// use prepared regexp if present
var prepared = tagPattern[tag];
if (prepared !== undefined) {
regExp = prepared;
} else {
regExp = new RegExp(tag);
}
length = tag.length;
}
return [regExp, length];
}
}
/**
* Helper class for Label which explodes the label text into lines and blocks within lines
@ -159,123 +427,43 @@ class LabelSplitter {
* @returns {Array}
*/
splitHtmlBlocks(text) {
let blocks = [];
// TODO: consolidate following + methods/closures with splitMarkdownBlocks()
// NOTE: sequences of tabs and spaces are reduced to single space; scan usage of `this.spacing` within method
let s = {
bold: false,
ital: false,
mono: false,
spacing: false,
position: 0,
buffer: "",
modStack: []
};
let s = new MarkupAccumulator(text);
s.mod = function() {
return (this.modStack.length === 0) ? 'normal' : this.modStack[0];
};
let parseEntities = (ch) => {
if (/&/.test(ch)) {
let parsed = s.replace(s.text, '&lt;', '<')
|| s.replace(s.text, '&amp;', '&');
s.modName = function() {
if (this.modStack.length === 0)
return 'normal';
else if (this.modStack[0] === 'mono')
return 'mono';
else {
if (s.bold && s.ital) {
return 'boldital';
} else if (s.bold) {
return 'bold';
} else if (s.ital) {
return 'ital';
if (!parsed) {
s.add("&");
}
}
};
s.emitBlock = function(override=false) { // eslint-disable-line no-unused-vars
if (this.spacing) {
this.add(" ");
this.spacing = false;
}
if (this.buffer.length > 0) {
blocks.push({ text: this.buffer, mod: this.modName() });
this.buffer = "";
return true;
}
};
s.add = function(text) {
if (text === " ") {
s.spacing = true;
}
if (s.spacing) {
this.buffer += " ";
this.spacing = false;
}
if (text != " ") {
this.buffer += text;
}
return false;
};
while (s.position < text.length) {
let ch = text.charAt(s.position);
if (/[ \t]/.test(ch)) {
if (!s.mono) {
s.spacing = true;
} else {
s.add(ch);
}
} else if (/</.test(ch)) {
if (!s.mono && !s.bold && /<b>/.test(text.substr(s.position,3))) {
s.emitBlock();
s.bold = true;
s.modStack.unshift("bold");
s.position += 2;
} else if (!s.mono && !s.ital && /<i>/.test(text.substr(s.position,3))) {
s.emitBlock();
s.ital = true;
s.modStack.unshift("ital");
s.position += 2;
} else if (!s.mono && /<code>/.test(text.substr(s.position,6))) {
s.emitBlock();
s.mono = true;
s.modStack.unshift("mono");
s.position += 5;
} else if (!s.mono && (s.mod() === 'bold') && /<\/b>/.test(text.substr(s.position,4))) {
s.emitBlock();
s.bold = false;
s.modStack.shift();
s.position += 3;
} else if (!s.mono && (s.mod() === 'ital') && /<\/i>/.test(text.substr(s.position,4))) {
s.emitBlock();
s.ital = false;
s.modStack.shift();
s.position += 3;
} else if ((s.mod() === 'mono') && /<\/code>/.test(text.substr(s.position,7))) {
s.emitBlock();
s.mono = false;
s.modStack.shift();
s.position += 6;
} else {
s.add(ch);
}
} else if (/&/.test(ch)) {
if (/&lt;/.test(text.substr(s.position,4))) {
s.add("<");
s.position += 3;
} else if (/&amp;/.test(text.substr(s.position,5))) {
s.add("&");
s.position += 4;
} else {
s.add("&");
}
} else {
while (s.position < s.text.length) {
let ch = s.text.charAt(s.position);
let parsed = s.parseWS(ch)
|| (/</.test(ch) && (
s.parseStartTag('bold', '<b>')
|| s.parseStartTag('ital', '<i>')
|| s.parseStartTag('mono', '<code>')
|| s.parseEndTag('bold', '</b>')
|| s.parseEndTag('ital', '</i>')
|| s.parseEndTag('mono', '</code>')))
|| parseEntities(ch);
if (!parsed) {
s.add(ch);
}
s.position++
}
s.emitBlock();
return blocks;
return s.blocks;
}
@ -285,129 +473,49 @@ class LabelSplitter {
* @returns {Array}
*/
splitMarkdownBlocks(text) {
let blocks = [];
// TODO: consolidate following + methods/closures with splitHtmlBlocks()
// NOTE: sequences of tabs and spaces are reduced to single space; scan usage of `this.spacing` within method
let s = {
bold: false,
ital: false,
mono: false,
beginable: true,
spacing: false,
position: 0,
buffer: "",
modStack: []
};
s.mod = function() {
return (this.modStack.length === 0) ? 'normal' : this.modStack[0];
};
s.modName = function() {
if (this.modStack.length === 0)
return 'normal';
else if (this.modStack[0] === 'mono')
return 'mono';
else {
if (s.bold && s.ital) {
return 'boldital';
} else if (s.bold) {
return 'bold';
} else if (s.ital) {
return 'ital';
}
}
};
s.emitBlock = function(override=false) { // eslint-disable-line no-unused-vars
if (this.spacing) {
this.add(" ");
this.spacing = false;
}
if (this.buffer.length > 0) {
blocks.push({ text: this.buffer, mod: this.modName() });
this.buffer = "";
}
};
let s = new MarkupAccumulator(text);
let beginable = true;
s.add = function(text) {
if (text === " ") {
s.spacing = true;
}
if (s.spacing) {
this.buffer += " ";
this.spacing = false;
}
if (text != " ") {
this.buffer += text;
}
};
while (s.position < text.length) {
let ch = text.charAt(s.position);
if (/[ \t]/.test(ch)) {
if (!s.mono) {
s.spacing = true;
} else {
s.add(ch);
}
s.beginable = true
} else if (/\\/.test(ch)) {
if (s.position < text.length+1) {
let parseOverride = (ch) => {
if (/\\/.test(ch)) {
if (s.position < this.text.length + 1) {
s.position++;
ch = text.charAt(s.position);
ch = this.text.charAt(s.position);
if (/ \t/.test(ch)) {
s.spacing = true;
} else {
s.add(ch);
s.beginable = false;
beginable = false;
}
}
} else if (!s.mono && !s.bold && (s.beginable || s.spacing) && /\*/.test(ch)) {
s.emitBlock();
s.bold = true;
s.modStack.unshift("bold");
} else if (!s.mono && !s.ital && (s.beginable || s.spacing) && /\_/.test(ch)) {
s.emitBlock();
s.ital = true;
s.modStack.unshift("ital");
} else if (!s.mono && (s.beginable || s.spacing) && /`/.test(ch)) {
s.emitBlock();
s.mono = true;
s.modStack.unshift("mono");
} else if (!s.mono && (s.mod() === "bold") && /\*/.test(ch)) {
if ((s.position === text.length-1) || /[.,_` \t\n]/.test(text.charAt(s.position+1))) {
s.emitBlock();
s.bold = false;
s.modStack.shift();
} else {
s.add(ch);
}
} else if (!s.mono && (s.mod() === "ital") && /\_/.test(ch)) {
if ((s.position === text.length-1) || /[.,*` \t\n]/.test(text.charAt(s.position+1))) {
s.emitBlock();
s.ital = false;
s.modStack.shift();
} else {
s.add(ch);
}
} else if (s.mono && (s.mod() === "mono") && /`/.test(ch)) {
if ((s.position === text.length-1) || (/[.,*_ \t\n]/.test(text.charAt(s.position+1)))) {
s.emitBlock();
s.mono = false;
s.modStack.shift();
} else {
s.add(ch);
}
} else {
return true
}
return false;
}
while (s.position < s.text.length) {
let ch = s.text.charAt(s.position);
let parsed = s.parseWS(ch)
|| parseOverride(ch)
|| ((beginable || s.spacing) && (
s.parseStartTag('bold', '*')
|| s.parseStartTag('ital', '_')
|| s.parseStartTag('mono', '`')))
|| s.parseEndTag('bold', '*', 'afterBold')
|| s.parseEndTag('ital', '_', 'afterItal')
|| s.parseEndTag('mono', '`', 'afterMono');
if (!parsed) {
s.add(ch);
s.beginable = false;
beginable = false;
}
s.position++
}
s.emitBlock();
return blocks;
return s.blocks;
}

+ 97
- 0
lib/network/typedefs.js View File

@ -0,0 +1,97 @@
// NOTE: When a typedef is isolated in a separate comment block, an actual description is generated for it,
// using the rest of the commenting in the code block. Usage of typedef in other comments then
// link to there. TIL.
//
// Also noteworthy, all typedef's set up in this manner are collected in a single, global page 'global.html'.
// In other words, it doesn't matter *where* the typedef's are defined in the code.
//
//
// TODO: add descriptive commenting to given typedef's
/**
* @typedef {{type:string, point:Point, angle:number, length:number}} ArrowData
*
* Object containing instantiation data for a given endpoint.
*/
/**
* @typedef {{x:number, y:number}} Point
*
* A point in view-coordinates.
*/
/**
* @typedef {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} ArrowOptions
*/
/**
* @typedef {string|number} Id
*/
/**
* @typedef {Id} NodeId
*/
/**
* @typedef {Id} EdgeId
*/
/**
* @typedef {Id} LabelId
*/
/**
* @typedef {{x: number, y: number}} point
*/
/**
* @typedef {{left: number, top: number, width: number, height: number}} rect
*/
/**
* @typedef {{x: number, y:number, angle: number}} rotationPoint
*
* point to rotate around and the angle in radians to rotate. angle == 0 means no rotation
*/
/**
* @typedef {{nodeId:NodeId}} nodeClickItem
*/
/**
* @typedef {{nodeId:NodeId, labelId:LabelId}} nodeLabelClickItem
*/
/**
* @typedef {{edgeId:EdgeId}} edgeClickItem
*/
/**
* @typedef {{edgeId:EdgeId, labelId:LabelId}} edgeLabelClickItem
*/
/**
* @typedef {'bold'|'ital'|'boldital'|'mono'|'normal'} MultiFontStyle
*
* The allowed specifiers of multi-fonts.
*/
/**
* @typedef {{color:string, size:number, face:string, mod:string, vadjust:number}} MultiFontOptions
*
* The full set of options of a given multi-font.
*/
/**
* @typedef {Array.<object>} Pile
*
* Sequence of option objects, the order is significant.
* The sequence is used to determine the value of a given option.
*
* Usage principles:
*
* - All search is done in the sequence of the pile.
* - As soon as a value is found, the searching stops.
* - prototypes are totally ignored. The idea is to add option objects used as prototypes
* to the pile, in the correct order.
*/

+ 5
- 2
lib/timeline/Core.js View File

@ -27,6 +27,7 @@ Core.prototype._create = function (container) {
this.dom = {};
this.dom.container = container;
this.dom.container.style.position = 'relative';
this.dom.root = document.createElement('div');
this.dom.background = document.createElement('div');
@ -47,6 +48,7 @@ Core.prototype._create = function (container) {
this.dom.shadowTopRight = document.createElement('div');
this.dom.shadowBottomRight = document.createElement('div');
this.dom.rollingModeBtn = document.createElement('div');
this.dom.loadingScreen = document.createElement('div');
this.dom.root.className = 'vis-timeline';
this.dom.background.className = 'vis-panel vis-background';
@ -67,6 +69,7 @@ Core.prototype._create = function (container) {
this.dom.shadowTopRight.className = 'vis-shadow vis-top';
this.dom.shadowBottomRight.className = 'vis-shadow vis-bottom';
this.dom.rollingModeBtn.className = 'vis-rolling-mode-btn';
this.dom.loadingScreen.className = 'vis-loading-screen';
this.dom.root.appendChild(this.dom.background);
this.dom.root.appendChild(this.dom.backgroundVertical);
@ -76,7 +79,6 @@ Core.prototype._create = function (container) {
this.dom.root.appendChild(this.dom.rightContainer);
this.dom.root.appendChild(this.dom.top);
this.dom.root.appendChild(this.dom.bottom);
this.dom.root.appendChild(this.dom.bottom);
this.dom.root.appendChild(this.dom.rollingModeBtn);
this.dom.centerContainer.appendChild(this.dom.center);
@ -88,7 +90,7 @@ Core.prototype._create = function (container) {
this.dom.leftContainer.appendChild(this.dom.shadowBottomLeft);
this.dom.rightContainer.appendChild(this.dom.shadowTopRight);
this.dom.rightContainer.appendChild(this.dom.shadowBottomRight);
// size properties of each of the panels
this.props = {
root: {},
@ -334,6 +336,7 @@ Core.prototype._create = function (container) {
// attach the root panel to the provided container
if (!container) throw new Error('No container provided');
container.appendChild(this.dom.root);
container.appendChild(this.dom.loadingScreen);
};
/**

+ 2
- 2
lib/timeline/TimeStep.js View File

@ -73,7 +73,7 @@ TimeStep.FORMAT = {
hour: 'HH:mm',
weekday: 'ddd D',
day: 'D',
week: 'w',
week: 'D',
month: 'MMM',
year: 'YYYY'
},
@ -340,7 +340,7 @@ TimeStep.prototype.setMinimumStep = function(minimumStep) {
if (stepYear > minimumStep) {this.scale = 'year'; this.step = 1;}
if (stepMonth*3 > minimumStep) {this.scale = 'month'; this.step = 3;}
if (stepMonth > minimumStep) {this.scale = 'month'; this.step = 1;}
if (stepDay*5 > minimumStep) {this.scale = 'day'; this.step = 5;}
if (stepDay*7 > minimumStep) {this.scale = 'week'; this.step = 1;}
if (stepDay*2 > minimumStep) {this.scale = 'day'; this.step = 2;}
if (stepDay > minimumStep) {this.scale = 'day'; this.step = 1;}
if (stepDay/2 > minimumStep) {this.scale = 'weekday'; this.step = 1;}

+ 22
- 1
lib/timeline/Timeline.js View File

@ -78,6 +78,26 @@ function Timeline (container, items, groups, options) {
this.options.rollingMode = options && options.rollingMode;
this.options.onInitialDrawComplete = options && options.onInitialDrawComplete;
this.options.loadingScreenTemplate = options && options.loadingScreenTemplate;
// Prepare loading screen
var loadingScreenFragment = document.createElement('div');
if (this.options.loadingScreenTemplate) {
var templateFunction = this.options.loadingScreenTemplate.bind(this);
var loadingScreen = templateFunction(this.dom.loadingScreen);
if ((loadingScreen instanceof Object) && !(loadingScreen instanceof Element)) {
templateFunction(loadingScreenFragment)
} else {
if (loadingScreen instanceof Element) {
loadingScreenFragment.innerHTML = '';
loadingScreenFragment.appendChild(loadingScreen);
}
else if (loadingScreen != undefined) {
loadingScreenFragment.innerHTML = loadingScreen;
}
}
}
this.dom.loadingScreen.appendChild(loadingScreenFragment);
// all components listed here will be repainted automatically
this.components = [];
@ -183,6 +203,7 @@ function Timeline (container, items, groups, options) {
if (!me.initialDrawDone && me.initialRangeChangeDone) {
me.initialDrawDone = true;
me.dom.root.style.visibility = 'visible';
me.dom.loadingScreen.parentNode.removeChild(me.dom.loadingScreen);
if (me.options.onInitialDrawComplete) {
setTimeout(() => {
return me.options.onInitialDrawComplete();
@ -438,7 +459,7 @@ Timeline.prototype.focus = function(id, options) {
me._redraw();
}
};
// Enforces the final vertical scroll position
var setFinalVerticalPosition = function() {
var finalVerticalScroll = getItemVerticalScroll(me, item);

+ 8
- 2
lib/timeline/component/css/timeline.css View File

@ -2,10 +2,16 @@
.vis-timeline {
position: relative;
border: 1px solid #bfbfbf;
overflow: hidden;
padding: 0;
margin: 0;
box-sizing: border-box;
}
.vis-loading-screen {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
}

+ 19
- 0
lib/timeline/component/css/timeline.js View File

@ -0,0 +1,19 @@
import { StyleSheet } from 'react-native';
export default StyleSheet.create({
'vis-timeline': {
'position': 'relative',
'border': [{ 'unit': 'px', 'value': 1 }, { 'unit': 'string', 'value': 'solid' }, { 'unit': 'string', 'value': '#bfbfbf' }],
'overflow': 'hidden',
'padding': [{ 'unit': 'px', 'value': 0 }, { 'unit': 'px', 'value': 0 }, { 'unit': 'px', 'value': 0 }, { 'unit': 'px', 'value': 0 }],
'margin': [{ 'unit': 'px', 'value': 0 }, { 'unit': 'px', 'value': 0 }, { 'unit': 'px', 'value': 0 }, { 'unit': 'px', 'value': 0 }],
'boxSizing': 'border-box'
},
'vis-loading-screen': {
'width': [{ 'unit': '%H', 'value': 1 }],
'height': [{ 'unit': '%V', 'value': 1 }],
'position': 'absolute',
'top': [{ 'unit': 'px', 'value': 0 }],
'left': [{ 'unit': 'px', 'value': 0 }]
}
});

+ 1
- 0
lib/timeline/optionsTimeline.js View File

@ -142,6 +142,7 @@ let allOptions = {
snap: {'function': 'function', 'null': 'null'},
start: {date, number, string, moment},
template: {'function': 'function'},
loadingScreenTemplate: {'function': 'function'},
groupTemplate: {'function': 'function'},
visibleFrameTemplate: {string, 'function': 'function'},
showTooltips: { 'boolean': bool},

+ 3
- 1
package.json View File

@ -38,7 +38,8 @@
"hammerjs": "^2.0.8",
"keycharm": "^0.2.0",
"moment": "^2.18.1",
"propagating-hammerjs": "^1.4.6"
"propagating-hammerjs": "^1.4.6",
"timsort": "^0.3.0"
},
"devDependencies": {
"async": "^2.5.0",
@ -59,6 +60,7 @@
"gulp-eslint": "^4.0.0",
"gulp-rename": "^1.2.2",
"gulp-util": "^3.0.8",
"jsdoc": "^3.5.5",
"jsdom": "9.12.0",
"jsdom-global": "^2.1.1",
"merge-stream": "^1.0.1",

+ 1
- 0
test/Label.test.js View File

@ -2,6 +2,7 @@
* TODO - add tests for:
* ====
*
* - html entities
* - html unclosed or unopened tags
* - html tag combinations with no font defined (e.g. bold within mono)
* - Unit tests for bad font shorthands.

Loading…
Cancel
Save