Browse Source

Merge branch 'develop' of https://github.com/almende/vis into feat-network-setselection

fixDataView
Maxime Douailin 8 years ago
parent
commit
11288efaeb
15 changed files with 1777 additions and 1658 deletions
  1. +11
    -0
      HISTORY.md
  2. +1508
    -1465
      dist/vis.js
  3. +1
    -1
      docs/data/dataset.html
  4. +1
    -1
      docs/data/dataview.html
  5. +1
    -1
      docs/timeline/index.html
  6. +3
    -2
      index.js
  7. +139
    -121
      lib/DataSet.js
  8. +12
    -17
      lib/DataView.js
  9. +1
    -0
      lib/network/modules/components/Edge.js
  10. +2
    -0
      lib/network/modules/components/Node.js
  11. +13
    -2
      lib/network/modules/components/edges/BezierEdgeDynamic.js
  12. +1
    -0
      lib/network/modules/components/edges/util/EdgeBase.js
  13. +1
    -1
      lib/timeline/component/LineGraph.js
  14. +1
    -0
      lib/timeline/optionsTimeline.js
  15. +82
    -47
      test/networkTest.html

+ 11
- 0
HISTORY.md View File

@ -12,10 +12,21 @@ http://visjs.org
### Network
- Fixed #1343: Connected edges are now deselected too when deselecting a node.
- Fixed #1398: Support nodes start with the correct positions.
- Fixed #1324: Labels now scale again.
### Timeline
- Implemented option `multiselectPerGroup`. Thanks @hansmaulwurf23.
- Expose `vis.timeline.Core` for customization purposes.
### Graph2d
- Fixed #1385: Draw lines on top of bars.
### DataSet/DataView
- Performance improvements (see #1381). Thanks @phimimms.
## 2015-01-01, version 4.9.0

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


+ 1
- 1
docs/data/dataset.html View File

@ -312,7 +312,7 @@ var data = new vis.DataSet([data] [, options])
<td>Object | Array</td>
<td>
Get a single item, multiple items, or all items from the DataSet.
Usage examples can be found in section <a href="#Getting_Data">Getting Data</a>, and the available <code>options</code> are described in section <a href="#Data_Selection">Data Selection</a>.
Usage examples can be found in section <a href="#Getting_Data">Getting Data</a>, and the available <code>options</code> are described in section <a href="#Data_Selection">Data Selection</a>. When no item is found, <code>null</code> is returned when a single item was requested, and and empty Array is returned in case of multiple id's.
</td>
</tr>

+ 1
- 1
docs/data/dataview.html View File

@ -248,7 +248,7 @@ var data = new vis.DataView(dataset, options)
<td>Object | Array</td>
<td>
Get a single item, multiple items, or all items from the DataView.
Usage examples can be found in section <a href="#Getting_Data">Getting Data</a>, and the available <code>options</code> are described in section <a href="#Data_Selection">Data Selection</a>.
Usage examples can be found in section <a href="#Getting_Data">Getting Data</a>, and the available <code>options</code> are described in section <a href="#Data_Selection">Data Selection</a>. When no item is found, <code>null</code> is returned when a single item was requested, and and empty Array is returned in case of multiple id's.
</td>
</tr>

+ 1
- 1
docs/timeline/index.html View File

@ -115,7 +115,7 @@
<h2 id="Example">Example</h2>
<p>
The following code shows how to create a Timeline and provide it with data.
More examples can be found in the <a href="../examples">examples</a> directory.
More examples can be found in the <a href="../../timeline_examples.html">timeline examples</a> page.
</p>
<pre class="prettyprint lang-html">&lt;!DOCTYPE HTML&gt;

+ 3
- 2
index.js View File

@ -22,8 +22,9 @@ exports.graph3d = {
exports.Timeline = require('./lib/timeline/Timeline');
exports.Graph2d = require('./lib/timeline/Graph2d');
exports.timeline = {
DateUtil: require('./lib/timeline/DateUtil'),
Core: require('./lib/timeline/Core'),
DataStep: require('./lib/timeline/DataStep'),
DateUtil: require('./lib/timeline/DateUtil'),
Range: require('./lib/timeline/Range'),
stack: require('./lib/timeline/Stack'),
TimeStep: require('./lib/timeline/TimeStep'),
@ -37,13 +38,13 @@ exports.timeline = {
RangeItem: require('./lib/timeline/component/item/RangeItem')
},
BackgroundGroup: require('./lib/timeline/component/BackgroundGroup'),
Component: require('./lib/timeline/component/Component'),
CurrentTime: require('./lib/timeline/component/CurrentTime'),
CustomTime: require('./lib/timeline/component/CustomTime'),
DataAxis: require('./lib/timeline/component/DataAxis'),
GraphGroup: require('./lib/timeline/component/GraphGroup'),
Group: require('./lib/timeline/component/Group'),
BackgroundGroup: require('./lib/timeline/component/BackgroundGroup'),
ItemSet: require('./lib/timeline/component/ItemSet'),
Legend: require('./lib/timeline/component/Legend'),
LineGraph: require('./lib/timeline/component/LineGraph'),

+ 139
- 121
lib/DataSet.js View File

@ -60,15 +60,15 @@ function DataSet (data, options) {
// all variants of a Date are internally stored as Date, so we can convert
// from everything to everything (also from ISODate to Number for example)
if (this._options.type) {
for (var field in this._options.type) {
if (this._options.type.hasOwnProperty(field)) {
var value = this._options.type[field];
if (value == 'Date' || value == 'ISODate' || value == 'ASPDate') {
this._type[field] = 'Date';
}
else {
this._type[field] = value;
}
var fields = Object.keys(this._options.type);
for (var i = 0, len = fields.length; i < len; i++) {
var field = fields[i];
var value = this._options.type[field];
if (value == 'Date' || value == 'ISODate' || value == 'ASPDate') {
this._type[field] = 'Date';
}
else {
this._type[field] = value;
}
}
}
@ -184,7 +184,7 @@ DataSet.prototype._trigger = function (event, params, senderId) {
subscribers = subscribers.concat(this._subscribers['*']);
}
for (var i = 0; i < subscribers.length; i++) {
for (var i = 0, len = subscribers.length; i < len; i++) {
var subscriber = subscribers[i];
if (subscriber.callback) {
subscriber.callback(event, params, senderId || null);
@ -340,7 +340,7 @@ DataSet.prototype.get = function (args) {
// build options
var type = options && options.type || this._options.type;
var filter = options && options.filter;
var items = [], item, itemId, i, len;
var items = [], item, itemIds, itemId, i, len;
// convert items
if (id != undefined) {
@ -361,12 +361,12 @@ DataSet.prototype.get = function (args) {
}
else {
// return all items
for (itemId in this._data) {
if (this._data.hasOwnProperty(itemId)) {
item = me._getItem(itemId, type);
if (!filter || filter(item)) {
items.push(item);
}
itemIds = Object.keys(this._data);
for (i = 0, len = itemIds.length; i < len; i++) {
itemId = itemIds[i];
item = me._getItem(itemId, type);
if (!filter || filter(item)) {
items.push(item);
}
}
}
@ -391,9 +391,11 @@ DataSet.prototype.get = function (args) {
// return the results
if (returnType == 'Object') {
var result = {};
for (i = 0; i < items.length; i++) {
result[items[i].id] = items[i];
var result = {},
resultant;
for (i = 0, len = items.length; i < len; i++) {
resultant = items[i];
result[resultant.id] = resultant;
}
return result;
}
@ -422,6 +424,7 @@ DataSet.prototype.getIds = function (options) {
filter = options && options.filter,
order = options && options.order,
type = options && options.type || this._options.type,
itemIds = Object.keys(data),
i,
len,
id,
@ -434,29 +437,27 @@ DataSet.prototype.getIds = function (options) {
if (order) {
// create ordered list
items = [];
for (id in data) {
if (data.hasOwnProperty(id)) {
item = this._getItem(id, type);
if (filter(item)) {
items.push(item);
}
for (i = 0, len = itemIds.length; i < len; i++) {
id = itemIds[i];
item = this._getItem(id, type);
if (filter(item)) {
items.push(item);
}
}
this._sort(items, order);
for (i = 0, len = items.length; i < len; i++) {
ids[i] = items[i][this._fieldId];
ids.push(items[i][this._fieldId]);
}
}
else {
// create unordered list
for (id in data) {
if (data.hasOwnProperty(id)) {
item = this._getItem(id, type);
if (filter(item)) {
ids.push(item[this._fieldId]);
}
for (i = 0, len = itemIds.length; i < len; i++) {
id = itemIds[i];
item = this._getItem(id, type);
if (filter(item)) {
ids.push(item[this._fieldId]);
}
}
}
@ -466,25 +467,23 @@ DataSet.prototype.getIds = function (options) {
if (order) {
// create an ordered list
items = [];
for (id in data) {
if (data.hasOwnProperty(id)) {
items.push(data[id]);
}
for (i = 0, len = itemIds.length; i < len; i++) {
id = itemIds[i];
items.push(data[id]);
}
this._sort(items, order);
for (i = 0, len = items.length; i < len; i++) {
ids[i] = items[i][this._fieldId];
ids.push(items[i][this._fieldId]);
}
}
else {
// create unordered list
for (id in data) {
if (data.hasOwnProperty(id)) {
item = data[id];
ids.push(item[this._fieldId]);
}
for (i = 0, len = itemIds.length; i < len; i++) {
id = itemIds[i];
item = data[id];
ids.push(item[this._fieldId]);
}
}
}
@ -514,6 +513,9 @@ DataSet.prototype.forEach = function (callback, options) {
var filter = options && options.filter,
type = options && options.type || this._options.type,
data = this._data,
itemIds = Object.key(data),
i,
len,
item,
id;
@ -521,7 +523,7 @@ DataSet.prototype.forEach = function (callback, options) {
// execute forEach on ordered list
var items = this.get(options);
for (var i = 0, len = items.length; i < len; i++) {
for (i = 0, len = items.length; i < len; i++) {
item = items[i];
id = item[this._fieldId];
callback(item, id);
@ -529,12 +531,11 @@ DataSet.prototype.forEach = function (callback, options) {
}
else {
// unordered
for (id in data) {
if (data.hasOwnProperty(id)) {
item = this._getItem(id, type);
if (!filter || filter(item)) {
callback(item, id);
}
for (i = 0, len = itemIds.length; i < len; i++) {
id = itemIds[i];
item = this._getItem(id, type);
if (!filter || filter(item)) {
callback(item, id);
}
}
}
@ -556,15 +557,18 @@ DataSet.prototype.map = function (callback, options) {
type = options && options.type || this._options.type,
mappedItems = [],
data = this._data,
itemIds = Object.keys(data),
i,
len,
id,
item;
// convert and filter items
for (var id in data) {
if (data.hasOwnProperty(id)) {
item = this._getItem(id, type);
if (!filter || filter(item)) {
mappedItems.push(callback(item, id));
}
for (i = 0, len = itemIds.length; i < len; i++) {
id = itemIds[i];
item = this._getItem(id, type);
if (!filter || filter(item)) {
mappedItems.push(callback(item, id));
}
}
@ -588,17 +592,23 @@ DataSet.prototype._filterFields = function (item, fields) {
return item;
}
var filteredItem = {};
var filteredItem = {},
itemFields = Object.keys(item),
len = itemFields.length,
i,
field;
if(Array.isArray(fields)){
for (var field in item) {
if (item.hasOwnProperty(field) && (fields.indexOf(field) != -1)) {
for (i = 0; i < len; i++) {
field = itemFields[i];
if (fields.indexOf(field) != -1) {
filteredItem[field] = item[field];
}
}
}else{
for (var field in item) {
if (item.hasOwnProperty(field) && fields.hasOwnProperty(field)) {
for (i = 0; i < len; i++) {
field = itemFields[i];
if (fields.hasOwnProperty(field)) {
filteredItem[fields[field]] = item[field];
}
}
@ -715,17 +725,19 @@ DataSet.prototype.clear = function (senderId) {
*/
DataSet.prototype.max = function (field) {
var data = this._data,
itemIds = Object.keys(data),
max = null,
maxField = null;
for (var id in data) {
if (data.hasOwnProperty(id)) {
var item = data[id];
var itemField = item[field];
if (itemField != null && (!max || itemField > maxField)) {
max = item;
maxField = itemField;
}
maxField = null,
i,
len;
for (i = 0, len = itemIds.length; i < len; i++) {
var id = itemIds[i];
var item = data[id];
var itemField = item[field];
if (itemField != null && (!max || itemField > maxField)) {
max = item;
maxField = itemField;
}
}
@ -739,17 +751,19 @@ DataSet.prototype.max = function (field) {
*/
DataSet.prototype.min = function (field) {
var data = this._data,
itemIds = Object.keys(data),
min = null,
minField = null;
for (var id in data) {
if (data.hasOwnProperty(id)) {
var item = data[id];
var itemField = item[field];
if (itemField != null && (!min || itemField < minField)) {
min = item;
minField = itemField;
}
minField = null,
i,
len;
for (i = 0, len = itemIds.length; i < len; i++) {
var id = itemIds[i];
var item = data[id];
var itemField = item[field];
if (itemField != null && (!min || itemField < minField)) {
min = item;
minField = itemField;
}
}
@ -765,31 +779,33 @@ DataSet.prototype.min = function (field) {
*/
DataSet.prototype.distinct = function (field) {
var data = this._data;
var itemIds = Object.keys(data);
var values = [];
var fieldType = this._options.type && this._options.type[field] || null;
var count = 0;
var i;
for (var prop in data) {
if (data.hasOwnProperty(prop)) {
var item = data[prop];
var value = item[field];
var exists = false;
for (i = 0; i < count; i++) {
if (values[i] == value) {
exists = true;
break;
}
}
if (!exists && (value !== undefined)) {
values[count] = value;
count++;
var i,
j,
len;
for (i = 0, len = itemIds.length; i < len; i++) {
var id = itemIds[i];
var item = data[id];
var value = item[field];
var exists = false;
for (j = 0; j < count; j++) {
if (values[j] == value) {
exists = true;
break;
}
}
if (!exists && (value !== undefined)) {
values[count] = value;
count++;
}
}
if (fieldType) {
for (i = 0; i < values.length; i++) {
for (i = 0, len = values.length; i < len; i++) {
values[i] = util.convert(values[i], fieldType);
}
}
@ -819,12 +835,14 @@ DataSet.prototype._addItem = function (item) {
item[this._fieldId] = id;
}
var d = {};
for (var field in item) {
if (item.hasOwnProperty(field)) {
var fieldType = this._type[field]; // type may be undefined
d[field] = util.convert(item[field], fieldType);
}
var d = {},
fields = Object.keys(item),
i,
len;
for (i = 0, len = fields.length; i < len; i++) {
var field = fields[i];
var fieldType = this._type[field]; // type may be undefined
d[field] = util.convert(item[field], fieldType);
}
this._data[id] = d;
this.length++;
@ -840,7 +858,7 @@ DataSet.prototype._addItem = function (item) {
* @private
*/
DataSet.prototype._getItem = function (id, types) {
var field, value;
var field, value, i, len;
// get the item from the dataset
var raw = this._data[id];
@ -849,22 +867,22 @@ DataSet.prototype._getItem = function (id, types) {
}
// convert the items field types
var converted = {};
var converted = {},
fields = Object.keys(raw);
if (types) {
for (field in raw) {
if (raw.hasOwnProperty(field)) {
value = raw[field];
converted[field] = util.convert(value, types[field]);
}
for (i = 0, len = fields.length; i < len; i++) {
field = fields[i];
value = raw[field];
converted[field] = util.convert(value, types[field]);
}
}
else {
// no field types specified, no converting needed
for (field in raw) {
if (raw.hasOwnProperty(field)) {
value = raw[field];
converted[field] = value;
}
for (i = 0, len = fields.length; i < len; i++) {
field = fields[i];
value = raw[field];
converted[field] = value;
}
}
return converted;
@ -890,11 +908,11 @@ DataSet.prototype._updateItem = function (item) {
}
// merge with current item
for (var field in item) {
if (item.hasOwnProperty(field)) {
var fieldType = this._type[field]; // type may be undefined
d[field] = util.convert(item[field], fieldType);
}
var fields = Object.keys(item);
for (var i = 0, len = fields.length; i < len; i++) {
var field = fields[i];
var fieldType = this._type[field]; // type may be undefined
d[field] = util.convert(item[field], fieldType);
}
return id;

+ 12
- 17
lib/DataView.js View File

@ -35,7 +35,7 @@ function DataView (data, options) {
* @param {DataSet | DataView} data
*/
DataView.prototype.setData = function (data) {
var ids, i, len;
var ids, id, i, len;
if (this._data) {
// unsubscribe from current dataset
@ -44,12 +44,7 @@ DataView.prototype.setData = function (data) {
}
// trigger a remove of all items in memory
ids = [];
for (var id in this._ids) {
if (this._ids.hasOwnProperty(id)) {
ids.push(id);
}
}
ids = Object.keys(this._ids);
this._ids = {};
this.length = 0;
this._trigger('remove', {items: ids});
@ -84,34 +79,34 @@ DataView.prototype.setData = function (data) {
* containing a variable parameter.
*/
DataView.prototype.refresh = function () {
var id;
var id, i, len;
var ids = this._data.getIds({filter: this._options && this._options.filter});
var oldIds = Object.keys(this._ids);
var newIds = {};
var added = [];
var removed = [];
// check for additions
for (var i = 0; i < ids.length; i++) {
for (i = 0, len = ids.length; i < len; i++) {
id = ids[i];
newIds[id] = true;
if (!this._ids[id]) {
added.push(id);
this._ids[id] = true;
this.length++;
}
}
// check for removals
for (id in this._ids) {
if (this._ids.hasOwnProperty(id)) {
if (!newIds[id]) {
removed.push(id);
delete this._ids[id];
this.length--;
}
for (i = 0, len = oldIds.length; i < len; i++) {
id = oldIds[i];
if (!newIds[id]) {
removed.push(id);
delete this._ids[id];
}
}
this.length += added.length - removed.length;
// trigger events
if (added.length) {
this._trigger('add', {items: added});

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

@ -344,6 +344,7 @@ class Edge {
}
this._setInteractionWidths();
this.updateLabelModule();
}
_setInteractionWidths() {

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

@ -381,6 +381,8 @@ class Node {
this.options.size = this.baseSize;
this.options.font.size = this.baseFontSize;
}
this.updateLabelModule();
}

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

@ -9,16 +9,27 @@ class BezierEdgeDynamic extends BezierEdgeBase {
}
setOptions(options) {
// check if the physics has changed.
let physicsChange = false;
if (this.options.physics !== options.physics) {
physicsChange = true;
}
// set the options and the to and from nodes
this.options = options;
this.id = this.options.id;
this.from = this.body.nodes[this.options.from];
this.to = this.body.nodes[this.options.to];
// setup the support node and connect
this.setupSupportNode();
this.connect();
// when we change the physics state of the edge, we reposition the support node.
if (this.options.physics !== options.physics) {
if (physicsChange === true) {
this.via.setOptions({physics: this.options.physics})
this.positionBezierNode();
}
this.connect();
}
connect() {

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

@ -4,6 +4,7 @@ class EdgeBase {
constructor(options, body, labelModule) {
this.body = body;
this.labelModule = labelModule;
this.options = {};
this.setOptions(options);
this.colorDirty = true;
this.color = {};

+ 1
- 1
lib/timeline/component/LineGraph.js View File

@ -671,13 +671,13 @@ LineGraph.prototype._updateGraph = function () {
}
// draw the groups
BarFunctions.draw(groupIds, processedGroupData, this.framework);
for (i = 0; i < groupIds.length; i++) {
group = this.groups[groupIds[i]];
if (group.options.style != 'bar') { // bar needs to be drawn enmasse
group.draw(processedGroupData[groupIds[i]], group, this.framework);
}
}
BarFunctions.draw(groupIds, processedGroupData, this.framework);
}
}
}

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

@ -81,6 +81,7 @@ let allOptions = {
},
locale:{string},
locales:{
__any__: {any},
__type__: {object}
},
margin: {

+ 82
- 47
test/networkTest.html View File

@ -1,60 +1,95 @@
<!doctype html>
<!DOCTYPE html>
<html>
<head>
<title>Network | Basic usage</title>
<script src="../dist/vis.js"></script>
<link type="text/css" rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/vis/4.9.0/vis.min.css">
<script type="text/javascript" src="../dist/vis.js"></script>
<link href="../dist/vis.css" rel="stylesheet" type="text/css" />
<style type="text/css">
<style>
#mynetwork {
width: 600px;
height: 400px;
border: 1px solid lightgray;
width: 1400px;
height: 800px;
border: 1px solid gray;
}
</style>
</head>
<body>
<body onload="draw();">
<script src="https://rawgit.com/Tooa/6e17f2d7b8e34ef94719/raw/a10096a6b88c992c57d032b1ed3079d7cc4b1f51/data.js"></script>
<div id="mynetwork"></div>
<script>
<p>
Create a simple network with some nodes and edges.
</p>
for (var i = 0; i < nodes.length; i++) {
nodes[i].mass = Math.ceil(2000* nodes[i].value);
}
<div id="mynetwork"></div>
var nodesDataset = new vis.DataSet(nodes);
var edgesDataset = new vis.DataSet(edges);
<script type="text/javascript">
// create an array with nodes
var nodes = new vis.DataSet([
{id: 1, label: 'Node 1'},
{id: 2, label: 'Node 2'},
{id: 3, label: 'Node 3'},
{id: 4, label: 'Node 4'},
{id: 5, label: 'Node 5'}
]);
// create an array with edges
var edges = new vis.DataSet([
{from: 1, to: 3},
{from: 1, to: 2},
{from: 2, to: 4},
{from: 2, to: 5}
]);
// create a network
var container = document.getElementById('mynetwork');
var data = {
nodes: nodes,
edges: edges
};
var options = {manipulation:{
initiallyActive:true,
addNode: false,
// addEdge: false
// editNode: true
}};
var network = new vis.Network(container, data, options);
</script>
function redrawAll() {
var container = document.getElementById('mynetwork');
var options = {
nodes: {
borderWidth:4,
color: {
border: '#406897',
background: '#6AAFFF'
},
scaling: {
min: 10,
max: 200,
label: {
min: 50,
max: 100,
drawThreshold: 10,
maxVisible: 60
}
},
font: {
size: 20,
color:'#000000'
},
shapeProperties: {
useBorderWithImage: true
},
},
edges: {
scaling: {
min: 2,
max: 50
},
color: { inherit: 'from' },
smooth: {
type: 'continuous'
}
},
physics: {
"barnesHut": {
"gravitationalConstant": -19050,
"centralGravity": 1.3,
"springLength": 170,
"springConstant": 0.035,
"damping": 0.23
},
"minVelocity": 0.75,
stabilization: {
enabled: false,
iterations: 2000,
updateInterval: 25
}
},
configure:'physics',
interaction: {
tooltipDelay: 200,
hideEdgesOnDrag: true
},
layout:{improvedLayout:false}
};
<script src="../googleAnalytics.js"></script>
network = new vis.Network(container, {nodes: nodesDataset, edges: edgesDataset}, options);
}
redrawAll();
</script>
</body>
</html>

Loading…
Cancel
Save