Browse Source

Added data manipulation functionality

css_transitions
Alex de Mulder 12 years ago
parent
commit
12669bcc54
20 changed files with 1516 additions and 679 deletions
  1. BIN
      dist/img/acceptDeleteIcon.png
  2. BIN
      dist/img/editIcon.png
  3. +743
    -475
      dist/vis.js
  4. +8
    -23
      dist/vis.min.js
  5. +0
    -11
      examples/graph/02_random_nodes.html
  6. +0
    -11
      examples/graph/18_fully_random_nodes_clustering.html
  7. +0
    -11
      examples/graph/19_scale_free_graph_clustering.html
  8. +0
    -1
      examples/graph/20_navigation.html
  9. +98
    -73
      examples/graph/21_data_manipulation.html
  10. +1
    -0
      examples/graph/index.html
  11. +52
    -28
      src/graph/Graph.js
  12. +94
    -15
      src/graph/SelectionMixin.js
  13. BIN
      src/graph/img/acceptDeleteIcon.png
  14. BIN
      src/graph/img/addNodeIcon.png
  15. BIN
      src/graph/img/backIcon.png
  16. BIN
      src/graph/img/connectIcon.png
  17. BIN
      src/graph/img/deleteIcon.png
  18. BIN
      src/graph/img/editIcon.png
  19. +366
    -31
      src/graph/manipulationMixin.js
  20. +154
    -0
      src/util.js

BIN
dist/img/acceptDeleteIcon.png View File

Before After
Width: 24  |  Height: 24  |  Size: 20 KiB

BIN
dist/img/editIcon.png View File

Before After
Width: 24  |  Height: 24  |  Size: 20 KiB

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


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


+ 0
- 11
examples/graph/02_random_nodes.html View File

@ -94,19 +94,8 @@
graph = new vis.Graph(container, data, options);
// add event listeners
<<<<<<< HEAD
<<<<<<< HEAD
vis.events.addListener(graph, 'select', function(params) {
document.getElementById('selection').innerHTML =
'Selection: ' + JSON.stringify(graph.getSelection());
=======
graph.on('select', function(params) {
document.getElementById('selection').innerHTML = 'Selection: ' + params.nodes;
>>>>>>> develop
=======
graph.on('select', function(params) {
document.getElementById('selection').innerHTML = 'Selection: ' + params.nodes;
>>>>>>> origin/gh-pages
});
}
</script>

+ 0
- 11
examples/graph/18_fully_random_nodes_clustering.html View File

@ -64,19 +64,8 @@
graph = new vis.Graph(container, data, options);
// add event listeners
<<<<<<< HEAD
<<<<<<< HEAD
vis.events.addListener(graph, 'select', function(params) {
document.getElementById('selection').innerHTML =
'Selection: ' + JSON.stringify(graph.getSelection());
=======
graph.on('select', function(params) {
document.getElementById('selection').innerHTML = 'Selection: ' + params.nodes;
>>>>>>> develop
=======
graph.on('select', function(params) {
document.getElementById('selection').innerHTML = 'Selection: ' + params.nodes;
>>>>>>> origin/gh-pages
});
}
</script>

+ 0
- 11
examples/graph/19_scale_free_graph_clustering.html View File

@ -100,19 +100,8 @@
graph = new vis.Graph(container, data, options);
// add event listeners
<<<<<<< HEAD
<<<<<<< HEAD
vis.events.addListener(graph, 'select', function(params) {
document.getElementById('selection').innerHTML =
'Selection: ' + JSON.stringify(graph.getSelection());
=======
graph.on('select', function(params) {
document.getElementById('selection').innerHTML = 'Selection: ' + params.nodes;
>>>>>>> develop
=======
graph.on('select', function(params) {
document.getElementById('selection').innerHTML = 'Selection: ' + params.nodes;
>>>>>>> origin/gh-pages
});
}
</script>

+ 0
- 1
examples/graph/20_navigation.html View File

@ -31,7 +31,6 @@
div.table_description {
width:100px;
}
</style>
<script type="text/javascript" src="../../dist/vis.js"></script>

examples/graph/20_UI_example.html → examples/graph/21_data_manipulation.html View File

@ -1,7 +1,7 @@
<!doctype html>
<html>
<head>
<title>Graph | Random nodes</title>
<title>Graph | Navigation</title>
<style type="text/css">
body {
@ -13,24 +13,25 @@
border: 1px solid lightgray;
}
table.legend_table {
font-size: 11px;
border-width:1px;
border-color:#d3d3d3;
border-style:solid;
font-size: 11px;
border-width:1px;
border-color:#d3d3d3;
border-style:solid;
}
table.legend_table,td {
border-width:1px;
border-color:#d3d3d3;
border-style:solid;
padding: 2px;
border-width:1px;
border-color:#d3d3d3;
border-style:solid;
padding: 2px;
}
div.table_content {
width:80px;
text-align:center;
width:80px;
text-align:center;
}
div.table_description {
width:100px;
width:100px;
}
div.graph-manipulationDiv {
border-width:0px;
border-bottom: 1px;
@ -51,10 +52,12 @@
}
span.manipulationUI {
font-family: verdana;
font-size: 12px;
-moz-border-radius: 15px;
border-radius: 15px;
display:inline-block;
background-position: 4px 0px;
background-position: 0px 0px;
background-repeat:no-repeat;
height:24px;
margin: -14px 0px 0px 10px;
@ -88,11 +91,22 @@
span.manipulationUI.none:active {
box-shadow: 1px 1px 8px rgba(0, 0, 0, 0.0);
}
span.manipulationUI.none {
padding: 0px 0px 0px 0px;
}
span.manipulationUI.notification{
margin: 2px;
font-weight: bold;
}
span.manipulationUI.add {
background-image: url("../../dist/img/addNodeIcon.png");
}
span.manipulationUI.edit {
background-image: url("../../dist/img/editIcon.png");
}
span.manipulationUI.connect {
background-image: url("../../dist/img/connectIcon.png");
}
@ -100,19 +114,32 @@
span.manipulationUI.delete {
background-image: url("../../dist/img/deleteIcon.png");
}
span.manipulationUI.acceptDelete {
background-image: url("../../dist/img/acceptDeleteIcon.png");
}
/* top right bottom left */
span.manipulationLabel {
margin: 0px 0px 0px 25px;
margin: 0px 0px 0px 23px;
line-height: 25px;
}
div.seperatorLine {
display:inline-block;
width:1px;
height:20px;
background-color: #bdbdbd;
margin: 5px 7px 0px 15px;
}
input.manipulatorInput[type="text"] {
width:80px;
height:15px;
font-size:11px;
margin: 2px 0px 0px 0px;
}
input.manipulatorInput[type="button"] {
width:80px;
height:22px;
font-size:12px;
margin: 2px 0px 0px 10px;
}
</style>
@ -177,78 +204,76 @@
nodes: nodes,
edges: edges
};
/*
/*
var options = {
nodes: {
shape: 'circle'
},
edges: {
length: 50
},
stabilize: false
};
*/
var options = {
nodes: {
shape: 'circle'
},
edges: {
length: 50
},
stabilize: false
stabilize: false,
clustering:true,
navigation: true,
keyboard: true,
dataManipulationToolbar: true
};
*/
var options = {
edges: {
length: 50
},
stabilize: false,
navigationUI: {
enabled: true
},
keyboardNavigation: {
enabled: true
}
};
graph = new vis.Graph(container, data, options);
// add event listeners
vis.events.addListener(graph, 'select', function(params) {
document.getElementById('selection').innerHTML =
'Selection: ' + JSON.stringify(graph.getSelection());
graph.on('select', function(params) {
document.getElementById('selection').innerHTML = 'Selection: ' + params.nodes;
});
}
</script>
</head>
<body onload="draw();">
<h2>UI - User Interface and Keyboad Navigation</h2>
<h2>Navigation controls and keyboad navigation</h2>
<div style="width: 700px; font-size:14px;">
This example is the same as example 2, except for the UI that has been activated. The UI icons are described below. <br /><br />
<table class="legend_table">
<tr>
<td>Icons: </td>
<td><div class="table_content"><img src="../../dist/img/uparrow.png" /> </div></td>
<td><div class="table_content"><img src="../../dist/img/downarrow.png" /> </div></td>
<td><div class="table_content"><img src="../../dist/img/leftarrow.png" /> </div></td>
<td><div class="table_content"><img src="../../dist/img/rightarrow.png" /> </div></td>
<td><div class="table_content"><img src="../../dist/img/plus.png" /> </div></td>
<td><div class="table_content"><img src="../../dist/img/minus.png" /> </div></td>
<td><div class="table_content"><img src="../../dist/img/zoomExtends.png" /> </div></td>
</tr>
<tr>
<td><div class="table_description">Keyboard shortcuts:</div></td>
<td><div class="table_content">Up arrow</div></td>
<td><div class="table_content">Down arrow</div></td>
<td><div class="table_content">Left arrow</div></td>
<td><div class="table_content">Right arrow</div></td>
<td><div class="table_content">=<br />[<br />Page up</div></td>
<td><div class="table_content">-<br />]<br />Page down</div></td>
<td><div class="table_content">None</div></td>
</tr>
<td><div class="table_description">Description:</div></td>
<td><div class="table_content">Move up</div></td>
<td><div class="table_content">Move down</div></td>
<td><div class="table_content">Move left</div></td>
<td><div class="table_content">Move right</div></td>
<td><div class="table_content">Zoom in</div></td>
<td><div class="table_content">Zoom out</div></td>
<td><div class="table_content">Zoom extends</div></td>
</tr>
</table>
<br />
Apart from clicking the icons, you can also navigate using the keyboard. The buttons are in table above.
Zoom Extends changes the zoom and position of the camera to encompass all visible nodes.
This example is the same as example 2, except for the navigation controls that has been activated. The navigation controls are described below. <br /><br />
<table class="legend_table">
<tr>
<td>Icons: </td>
<td><div class="table_content"><img src="../../dist/img/uparrow.png" /> </div></td>
<td><div class="table_content"><img src="../../dist/img/downarrow.png" /> </div></td>
<td><div class="table_content"><img src="../../dist/img/leftarrow.png" /> </div></td>
<td><div class="table_content"><img src="../../dist/img/rightarrow.png" /> </div></td>
<td><div class="table_content"><img src="../../dist/img/plus.png" /> </div></td>
<td><div class="table_content"><img src="../../dist/img/minus.png" /> </div></td>
<td><div class="table_content"><img src="../../dist/img/zoomExtends.png" /> </div></td>
</tr>
<tr>
<td><div class="table_description">Keyboard shortcuts:</div></td>
<td><div class="table_content">Up arrow</div></td>
<td><div class="table_content">Down arrow</div></td>
<td><div class="table_content">Left arrow</div></td>
<td><div class="table_content">Right arrow</div></td>
<td><div class="table_content">=<br />[<br />Page up</div></td>
<td><div class="table_content">-<br />]<br />Page down</div></td>
<td><div class="table_content">None</div></td>
</tr>
<tr>
<td><div class="table_description">Description:</div></td>
<td><div class="table_content">Move up</div></td>
<td><div class="table_content">Move down</div></td>
<td><div class="table_content">Move left</div></td>
<td><div class="table_content">Move right</div></td>
<td><div class="table_content">Zoom in</div></td>
<td><div class="table_content">Zoom out</div></td>
<td><div class="table_content">Zoom extends</div></td>
</tr>
</table>
<br />
Apart from clicking the icons, you can also navigate using the keyboard. The buttons are in table above.
Zoom Extends changes the zoom and position of the camera to encompass all visible nodes.
</div>

+ 1
- 0
examples/graph/index.html View File

@ -32,6 +32,7 @@
<p><a href="18_fully_random_nodes_clustering.html">18_fully_random_nodes_clustering.html</a></p>
<p><a href="19_scale_free_graph_clustering.html">19_scale_free_graph_clustering.html</a></p>
<p><a href="20_navigation.html">20_navigation.html</a></p>
<p><a href="21_data_manipulation.html">21_data_manipulation.html</a></p>
<p><a href="graphviz/graphviz_gallery.html">graphviz_gallery.html</a></p>
</div>

+ 52
- 28
src/graph/Graph.js View File

@ -94,6 +94,9 @@ function Graph (container, data, options) {
enabled: false,
speed: {x: 10, y: 10, zoom: 0.02}
},
dataManipulationToolbar: {
enabled: false
},
minVelocity: 2, // px/s
maxIterations: 1000 // maximum number of iteration to stabilize
};
@ -110,7 +113,6 @@ function Graph (container, data, options) {
this.yIncrement = 0;
this.zoomIncrement = 0;
// create a frame and canvas
this._create();
@ -123,18 +125,9 @@ function Graph (container, data, options) {
// load the selection system. (mandatory, required by Graph)
this._loadSelectionSystem();
// load the data manipulation system
this._loadManipulationSystem();
// apply options
this.setOptions(options);
// other vars
var graph = this;
this.freezeSimulation = false;// freeze the simulation
@ -145,6 +138,7 @@ function Graph (container, data, options) {
this.canvasTopLeft = {"x": 0,"y": 0}; // coordinates of the top left of the canvas. they will be set during _redraw.
this.canvasBottomRight = {"x": 0,"y": 0}; // coordinates of the bottom right of the canvas. they will be set during _redraw
this.pointerPosition = {"x": 0,"y": 0}; // coordinates of the bottom right of the canvas. they will be set during _redraw
this.areaCenter = {}; // object with x and y elements used for determining the center of the zoom action
this.scale = 1; // defining the global scale variable in the constructor
@ -427,6 +421,17 @@ Graph.prototype.setOptions = function (options) {
this.constants.keyboard.enabled = false;
}
if (options.dataManipulationToolbar) {
this.constants.dataManipulationToolbar.enabled = true;
for (var prop in options.dataManipulationToolbar) {
if (options.dataManipulationToolbar.hasOwnProperty(prop)) {
this.constants.dataManipulationToolbar[prop] = options.dataManipulationToolbar[prop];
}
}
}
else if (options.dataManipulationToolbar !== undefined) {
this.constants.dataManipulationToolbar.enabled = false;
}
// TODO: work out these options and document them
if (options.edges) {
@ -488,16 +493,18 @@ Graph.prototype.setOptions = function (options) {
}
}
this.setSize(this.width, this.height);
this._setTranslation(this.frame.clientWidth / 2, this.frame.clientHeight / 2);
this._setScale(1);
// load the navigation system.
this._loadNavigationControls();
// load the data manipulation system
this._loadManipulationSystem();
// bind keys. If disabled, this will not do anything;
this._createKeyBinds();
this.setSize(this.width, this.height);
this._setTranslation(this.frame.clientWidth / 2, this.frame.clientHeight / 2);
this._setScale(1);
this._redraw();
};
@ -628,6 +635,10 @@ Graph.prototype._createKeyBinds = function() {
this.mousetrap.bind("pagedown",this._zoomOut.bind(me),"keydown");
this.mousetrap.bind("pagedown",this._stopZoom.bind(me), "keyup");
}
if (this.constants.dataManipulationToolbar.enabled == true) {
this.mousetrap.bind("escape",this._createManipulatorBar.bind(me));
}
}
/**
@ -776,6 +787,7 @@ Graph.prototype._onDragEnd = function () {
*/
Graph.prototype._onTap = function (event) {
var pointer = this._getPointer(event.gesture.touches[0]);
this.pointerPosition = pointer;
this._handleTap(pointer);
};
@ -798,6 +810,7 @@ Graph.prototype._onDoubleTap = function (event) {
*/
Graph.prototype._onHold = function (event) {
var pointer = this._getPointer(event.gesture.touches[0]);
this.pointerPosition = pointer;
this._handleOnHold(pointer);
};
@ -1126,7 +1139,9 @@ Graph.prototype.setSize = function(width, height) {
this.frame.canvas.width = this.frame.canvas.clientWidth;
this.frame.canvas.height = this.frame.canvas.clientHeight;
this.manipulationDiv.style.width = this.frame.canvas.clientWidth;
if (this.manipulationDiv !== undefined) {
this.manipulationDiv.style.width = this.frame.canvas.clientWidth;
}
if (this.constants.navigation.enabled == true) {
this._relocateNavigation();
@ -1731,6 +1746,7 @@ Graph.prototype._calculateForces = function() {
// we loop from i over all but the last entree in the array
// j loops from i+1 to the last. This way we do not double count any of the indices, nor i == j
var a_base = (-<