sigma-rails 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (23) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +22 -0
  3. data/README.md +37 -0
  4. data/lib/sigma/rails.rb +8 -0
  5. data/lib/sigma/rails/version.rb +5 -0
  6. data/vendor/assets/javascripts/sigma.js +8723 -0
  7. data/vendor/assets/javascripts/sigma.layout.forceAtlas2/README.md +12 -0
  8. data/vendor/assets/javascripts/sigma.layout.forceAtlas2/sigma.layout.forceAtlas2.js +1051 -0
  9. data/vendor/assets/javascripts/sigma.parsers.gexf/README.md +29 -0
  10. data/vendor/assets/javascripts/sigma.parsers.gexf/gexf-parser.js +548 -0
  11. data/vendor/assets/javascripts/sigma.parsers.gexf/sigma.parsers.gexf.js +108 -0
  12. data/vendor/assets/javascripts/sigma.parsers.json/README.md +29 -0
  13. data/vendor/assets/javascripts/sigma.parsers.json/sigma.parsers.json.js +88 -0
  14. data/vendor/assets/javascripts/sigma.plugins.animate/README.md +8 -0
  15. data/vendor/assets/javascripts/sigma.plugins.animate/sigma.plugins.animate.js +165 -0
  16. data/vendor/assets/javascripts/sigma.plugins.dragNodes/README.md +8 -0
  17. data/vendor/assets/javascripts/sigma.plugins.dragNodes/sigma.plugins.dragNodes.js +135 -0
  18. data/vendor/assets/javascripts/sigma.plugins.neighborhoods/README.md +24 -0
  19. data/vendor/assets/javascripts/sigma.plugins.neighborhoods/sigma.plugins.neighborhoods.js +186 -0
  20. data/vendor/assets/javascripts/sigma.renderers.customShapes/README.md +55 -0
  21. data/vendor/assets/javascripts/sigma.renderers.customShapes/shape-library.js +145 -0
  22. data/vendor/assets/javascripts/sigma.renderers.customShapes/sigma.renderers.customShapes.js +112 -0
  23. metadata +121 -0
@@ -0,0 +1,108 @@
1
+ ;(function(undefined) {
2
+ 'use strict';
3
+
4
+ if (typeof sigma === 'undefined')
5
+ throw 'sigma is not declared';
6
+
7
+ // Initialize package:
8
+ sigma.utils.pkg('sigma.parsers');
9
+
10
+ // Just a basic ID generator:
11
+ var _id = 0;
12
+ function edgeId() {
13
+ return 'e' + (_id++);
14
+ }
15
+
16
+ /**
17
+ * If the first arguments is a valid URL, this function loads a GEXF file and
18
+ * creates a new sigma instance or updates the graph of a given instance. It
19
+ * is possible to give a callback that will be executed at the end of the
20
+ * process. And if the first argument is a DOM element, it will skip the
21
+ * loading step and parse the given XML tree to fill the graph.
22
+ *
23
+ * @param {string|DOMElement} target The URL of the GEXF file or a valid
24
+ * GEXF tree.
25
+ * @param {object|sigma} sig A sigma configuration object or a
26
+ * sigma instance.
27
+ * @param {?function} callback Eventually a callback to execute
28
+ * after having parsed the file. It will
29
+ * be called with the related sigma
30
+ * instance as parameter.
31
+ */
32
+ sigma.parsers.gexf = function(target, sig, callback) {
33
+ var i,
34
+ l,
35
+ arr,
36
+ obj;
37
+
38
+ function parse(graph) {
39
+ // Adapt the graph:
40
+ arr = graph.nodes;
41
+ for (i = 0, l = arr.length; i < l; i++) {
42
+ obj = arr[i];
43
+
44
+ obj.id = obj.id;
45
+ if (obj.viz && typeof obj.viz === 'object') {
46
+ if (obj.viz.position && typeof obj.viz.position === 'object') {
47
+ obj.x = obj.viz.position.x;
48
+ obj.y = obj.viz.position.y;
49
+ }
50
+ obj.size = obj.viz.size;
51
+ obj.color = obj.viz.color;
52
+ }
53
+ }
54
+
55
+ arr = graph.edges;
56
+ for (i = 0, l = arr.length; i < l; i++) {
57
+ obj = arr[i];
58
+
59
+ obj.id = typeof obj.id === 'string' ? obj.id : edgeId();
60
+ obj.source = '' + obj.source;
61
+ obj.target = '' + obj.target;
62
+
63
+ if (obj.viz && typeof obj.viz === 'object') {
64
+ obj.color = obj.viz.color;
65
+ obj.size = obj.viz.thickness;
66
+ }
67
+
68
+ // Weight over viz.thickness?
69
+ obj.size = obj.weight;
70
+ }
71
+
72
+ // Update the instance's graph:
73
+ if (sig instanceof sigma) {
74
+ sig.graph.clear();
75
+
76
+ arr = graph.nodes;
77
+ for (i = 0, l = arr.length; i < l; i++)
78
+ sig.graph.addNode(arr[i]);
79
+
80
+ arr = graph.edges;
81
+ for (i = 0, l = arr.length; i < l; i++)
82
+ sig.graph.addEdge(arr[i]);
83
+
84
+ // ...or instanciate sigma if needed:
85
+ } else if (typeof sig === 'object') {
86
+ sig.graph = graph;
87
+ sig = new sigma(sig);
88
+
89
+ // ...or it's finally the callback:
90
+ } else if (typeof sig === 'function') {
91
+ callback = sig;
92
+ sig = null;
93
+ }
94
+
95
+ // Call the callback if specified:
96
+ if (callback) {
97
+ callback(sig || graph);
98
+ return;
99
+ } else
100
+ return graph;
101
+ }
102
+
103
+ if (typeof target === 'string')
104
+ gexf.fetch(target, parse);
105
+ else if (typeof target === 'object')
106
+ return parse(gexf.parse(target));
107
+ };
108
+ }).call(this);
@@ -0,0 +1,29 @@
1
+ sigma.parsers.json
2
+ ==================
3
+
4
+ Plugin developed by [Alexis Jacomy](https://github.com/jacomyal).
5
+
6
+ ---
7
+
8
+ This plugin provides a single function, `sigma.parsers.json()`, that will load a JSON encoded file, parse it, eventually instanciate sigma and fill the graph with the `graph.read()` method. The main goal is to avoid using jQuery only to load an external JSON file.
9
+
10
+ The most basic way to use this helper is to call it with a path and a sigma configuration object. It will then instanciate sigma, but after having added the graph into the config object.
11
+
12
+ ````javascript
13
+ sigma.parsers.json(
14
+ 'myGraph.json',
15
+ { container: 'myContainer' }
16
+ );
17
+ ````
18
+
19
+ It is also possible to update an existing instance's graph instead.
20
+
21
+ ````javascript
22
+ sigma.parsers.json(
23
+ 'myGraph.json',
24
+ myExistingInstance,
25
+ function() {
26
+ myExistingInstance.refresh();
27
+ }
28
+ );
29
+ ````
@@ -0,0 +1,88 @@
1
+ ;(function(undefined) {
2
+ 'use strict';
3
+
4
+ if (typeof sigma === 'undefined')
5
+ throw 'sigma is not declared';
6
+
7
+ // Initialize package:
8
+ sigma.utils.pkg('sigma.parsers');
9
+ sigma.utils.pkg('sigma.utils');
10
+
11
+ /**
12
+ * Just an XmlHttpRequest polyfill for different IE versions.
13
+ *
14
+ * @return {*} The XHR like object.
15
+ */
16
+ sigma.utils.xhr = function() {
17
+ if (window.XMLHttpRequest)
18
+ return new XMLHttpRequest();
19
+
20
+ var names,
21
+ i;
22
+
23
+ if (window.ActiveXObject) {
24
+ names = [
25
+ 'Msxml2.XMLHTTP.6.0',
26
+ 'Msxml2.XMLHTTP.3.0',
27
+ 'Msxml2.XMLHTTP',
28
+ 'Microsoft.XMLHTTP'
29
+ ];
30
+
31
+ for (i in names)
32
+ try {
33
+ return new ActiveXObject(names[i]);
34
+ } catch (e) {}
35
+ }
36
+
37
+ return null;
38
+ };
39
+
40
+ /**
41
+ * This function loads a JSON file and creates a new sigma instance or
42
+ * updates the graph of a given instance. It is possible to give a callback
43
+ * that will be executed at the end of the process.
44
+ *
45
+ * @param {string} url The URL of the JSON file.
46
+ * @param {object|sigma} sig A sigma configuration object or a sigma
47
+ * instance.
48
+ * @param {?function} callback Eventually a callback to execute after
49
+ * having parsed the file. It will be called
50
+ * with the related sigma instance as
51
+ * parameter.
52
+ */
53
+ sigma.parsers.json = function(url, sig, callback) {
54
+ var graph,
55
+ xhr = sigma.utils.xhr();
56
+
57
+ if (!xhr)
58
+ throw 'XMLHttpRequest not supported, cannot load the file.';
59
+
60
+ xhr.open('GET', url, true);
61
+ xhr.onreadystatechange = function() {
62
+ if (xhr.readyState === 4) {
63
+ graph = JSON.parse(xhr.responseText);
64
+
65
+ // Update the instance's graph:
66
+ if (sig instanceof sigma) {
67
+ sig.graph.clear();
68
+ sig.graph.read(graph);
69
+
70
+ // ...or instanciate sigma if needed:
71
+ } else if (typeof sig === 'object') {
72
+ sig.graph = graph;
73
+ sig = new sigma(sig);
74
+
75
+ // ...or it's finally the callback:
76
+ } else if (typeof sig === 'function') {
77
+ callback = sig;
78
+ sig = null;
79
+ }
80
+
81
+ // Call the callback if specified:
82
+ if (callback)
83
+ callback(sig || graph);
84
+ }
85
+ };
86
+ xhr.send();
87
+ };
88
+ }).call(this);
@@ -0,0 +1,8 @@
1
+ sigma.plugins.animate
2
+ =====================
3
+
4
+ Plugin developed by [Alexis Jacomy](https://github.com/jacomyal).
5
+
6
+ ---
7
+
8
+ This plugin provides a method to animate a sigma instance by interpolating some node properties. Check the `sigma.plugins.animate` function doc or the `examples/animate.html` code sample to know more.
@@ -0,0 +1,165 @@
1
+ /**
2
+ * This plugin provides a method to animate a sigma instance by interpolating
3
+ * some node properties. Check the sigma.plugins.animate function doc or the
4
+ * examples/animate.html code sample to know more.
5
+ */
6
+ (function() {
7
+ 'use strict';
8
+
9
+ if (typeof sigma === 'undefined')
10
+ throw 'sigma is not declared';
11
+
12
+ sigma.utils.pkg('sigma.plugins');
13
+
14
+ var _id = 0,
15
+ _cache = {};
16
+
17
+ // TOOLING FUNCTIONS:
18
+ // ******************
19
+ function parseColor(val) {
20
+ if (_cache[val])
21
+ return _cache[val];
22
+
23
+ var result = [0, 0, 0];
24
+
25
+ if (val.match(/^#/)) {
26
+ val = (val || '').replace(/^#/, '');
27
+ result = (val.length === 3) ?
28
+ [
29
+ parseInt(val.charAt(0) + val.charAt(0), 16),
30
+ parseInt(val.charAt(1) + val.charAt(1), 16),
31
+ parseInt(val.charAt(2) + val.charAt(2), 16)
32
+ ] :
33
+ [
34
+ parseInt(val.charAt(0) + val.charAt(1), 16),
35
+ parseInt(val.charAt(2) + val.charAt(3), 16),
36
+ parseInt(val.charAt(4) + val.charAt(5), 16)
37
+ ];
38
+ } else if (val.match(/^ *rgba? *\(/)) {
39
+ val = val.match(
40
+ /^ *rgba? *\( *([0-9]*) *, *([0-9]*) *, *([0-9]*) *(,.*)?\) *$/
41
+ );
42
+ result = [
43
+ +val[1],
44
+ +val[2],
45
+ +val[3]
46
+ ];
47
+ }
48
+
49
+ _cache[val] = {
50
+ r: result[0],
51
+ g: result[1],
52
+ b: result[2]
53
+ };
54
+
55
+ return _cache[val];
56
+ }
57
+
58
+ function interpolateColors(c1, c2, p) {
59
+ c1 = parseColor(c1);
60
+ c2 = parseColor(c2);
61
+
62
+ var c = {
63
+ r: c1.r * (1 - p) + c2.r * p,
64
+ g: c1.g * (1 - p) + c2.g * p,
65
+ b: c1.b * (1 - p) + c2.b * p
66
+ };
67
+
68
+ return 'rgb(' + [c.r | 0, c.g | 0, c.b | 0].join(',') + ')';
69
+ }
70
+
71
+ /**
72
+ * This function will animate some specified node properties. It will
73
+ * basically call requestAnimationFrame, interpolate the values and call the
74
+ * refresh method during a specified duration.
75
+ *
76
+ * Recognized parameters:
77
+ * **********************
78
+ * Here is the exhaustive list of every accepted parameters in the settings
79
+ * object:
80
+ *
81
+ * {?(function|string)} easing Either the name of an easing in the
82
+ * sigma.utils.easings package or a
83
+ * function. If not specified, the
84
+ * quadraticInOut easing from this package
85
+ * will be used instead.
86
+ * {?number} duration The duration of the animation. If not
87
+ * specified, the "animationsTime" setting
88
+ * value of the sigma instance will be used
89
+ * instead.
90
+ * {?function} onComplete Eventually a function to call when the
91
+ * animation is ended.
92
+ *
93
+ * @param {sigma} s The related sigma instance.
94
+ * @param {object} animate An hash with the keys being the node properties
95
+ * to interpolate, and the values being the related
96
+ * target values.
97
+ * @param {?object} options Eventually an object with options.
98
+ */
99
+ sigma.plugins.animate = function(s, animate, options) {
100
+ var o = options || {},
101
+ id = ++_id,
102
+ duration = o.duration || s.settings('animationsTime'),
103
+ easing = typeof o.easing === 'string' ?
104
+ sigma.utils.easings[o.easing] :
105
+ typeof o.easing === 'function' ?
106
+ o.easing :
107
+ sigma.utils.easings.quadraticInOut,
108
+ start = sigma.utils.dateNow(),
109
+ // Store initial positions:
110
+ startPositions = s.graph.nodes().reduce(function(res, node) {
111
+ var k;
112
+ res[node.id] = {};
113
+ for (k in animate)
114
+ if (k in node)
115
+ res[node.id][k] = node[k];
116
+ return res;
117
+ }, {});
118
+
119
+ s.animations = s.animations || Object.create({});
120
+ sigma.plugins.kill(s);
121
+
122
+ function step() {
123
+ var p = (sigma.utils.dateNow() - start) / duration;
124
+
125
+ if (p >= 1) {
126
+ s.graph.nodes().forEach(function(node) {
127
+ for (var k in animate)
128
+ if (k in animate)
129
+ node[k] = node[animate[k]];
130
+ });
131
+
132
+ s.refresh();
133
+ if (typeof o.onComplete === 'function')
134
+ o.onComplete();
135
+ } else {
136
+ p = easing(p);
137
+ s.graph.nodes().forEach(function(node) {
138
+ for (var k in animate)
139
+ if (k in animate) {
140
+ if (k.match(/color$/))
141
+ node[k] = interpolateColors(
142
+ startPositions[node.id][k],
143
+ node[animate[k]],
144
+ p
145
+ );
146
+ else
147
+ node[k] =
148
+ node[animate[k]] * p +
149
+ startPositions[node.id][k] * (1 - p);
150
+ }
151
+ });
152
+
153
+ s.refresh();
154
+ s.animations[id] = requestAnimationFrame(step);
155
+ }
156
+ }
157
+
158
+ step();
159
+ };
160
+
161
+ sigma.plugins.kill = function(s) {
162
+ for (var k in (s.animations || {}))
163
+ cancelAnimationFrame(s.animations[k]);
164
+ };
165
+ }).call(window);
@@ -0,0 +1,8 @@
1
+ sigma.plugins.dragNodes
2
+ =====================
3
+
4
+ Plugin developed by [José M. Camacho](https://github.com/josemazo).
5
+
6
+ ---
7
+
8
+ This plugin provides a method to drag & drop nodes. At the moment, this plugin is not compatible with the WebGL renderer. Check the sigma.plugins.dragNodes function doc or the examples/drag-nodes.html code sample to know more.
@@ -0,0 +1,135 @@
1
+ /**
2
+ * This plugin provides a method to drag & drop nodes. Check the
3
+ * sigma.plugins.dragNodes function doc or the examples/basic.html &
4
+ * examples/api-candy.html code samples to know more.
5
+ */
6
+ (function() {
7
+ 'use strict';
8
+
9
+ if (typeof sigma === 'undefined')
10
+ throw 'sigma is not declared';
11
+
12
+ sigma.utils.pkg('sigma.plugins');
13
+
14
+ /**
15
+ * This function will add `mousedown`, `mouseup` & `mousemove` events to the
16
+ * nodes in the `overNode`event to perform drag & drop operations. It uses
17
+ * `linear interpolation` [http://en.wikipedia.org/wiki/Linear_interpolation]
18
+ * and `rotation matrix` [http://en.wikipedia.org/wiki/Rotation_matrix] to
19
+ * calculate the X and Y coordinates from the `cam` or `renderer` node
20
+ * attributes. These attributes represent the coordinates of the nodes in
21
+ * the real container, not in canvas.
22
+ *
23
+ * Recognized parameters:
24
+ * **********************
25
+ * @param {sigma} s The related sigma instance.
26
+ * @param {renderer} renderer The related renderer instance.
27
+ */
28
+ sigma.plugins.dragNodes = function(s, renderer) {
29
+ // A quick hardcoded rule to prevent people from using this plugin with the
30
+ // WebGL renderer (which is impossible at the moment):
31
+ if (
32
+ sigma.renderers.webgl &&
33
+ renderer instanceof sigma.renderers.webgl
34
+ )
35
+ throw new Error(
36
+ 'The sigma.plugins.dragNodes is not compatible with the WebGL renderer'
37
+ );
38
+
39
+ var _body = document.body,
40
+ _container = renderer.container,
41
+ _mouse = _container.lastChild,
42
+ _camera = renderer.camera,
43
+ _node = null,
44
+ _prefix = '',
45
+ _isOverNode = false,
46
+ _isMouseOverCanvas = false;
47
+
48
+ // It removes the initial substring ('read_') if it's a WegGL renderer.
49
+ if (renderer instanceof sigma.renderers.webgl) {
50
+ _prefix = renderer.options.prefix.substr(5);
51
+ } else {
52
+ _prefix = renderer.options.prefix;
53
+ }
54
+
55
+ var nodeMouseOver = function(event) {
56
+ if (!_isOverNode) {
57
+ _node = event.data.node;
58
+ _mouse.addEventListener('mousedown', nodeMouseDown);
59
+ _isOverNode = true;
60
+ }
61
+ };
62
+
63
+ var treatOutNode = function(event) {
64
+ if (_isOverNode) {
65
+ _mouse.removeEventListener('mousedown', nodeMouseDown);
66
+ _isOverNode = false;
67
+ }
68
+ };
69
+
70
+ var nodeMouseDown = function(event) {
71
+ var size = s.graph.nodes().length;
72
+ if (size > 1) {
73
+ _mouse.removeEventListener('mousedown', nodeMouseDown);
74
+ _body.addEventListener('mousemove', nodeMouseMove);
75
+ _body.addEventListener('mouseup', nodeMouseUp);
76
+
77
+ renderer.unbind('outNode', treatOutNode);
78
+
79
+ // Deactivate drag graph.
80
+ renderer.settings({mouseEnabled: false, enableHovering: false});
81
+ s.refresh();
82
+ }
83
+ };
84
+
85
+ var nodeMouseUp = function(event) {
86
+ _mouse.addEventListener('mousedown', nodeMouseDown);
87
+ _body.removeEventListener('mousemove', nodeMouseMove);
88
+ _body.removeEventListener('mouseup', nodeMouseUp);
89
+
90
+ treatOutNode();
91
+ renderer.bind('outNode', treatOutNode);
92
+
93
+ // Activate drag graph.
94
+ renderer.settings({mouseEnabled: true, enableHovering: true});
95
+ s.refresh();
96
+ };
97
+
98
+ var nodeMouseMove = function(event) {
99
+ var x = event.pageX - _container.offsetLeft,
100
+ y = event.pageY - _container.offsetTop,
101
+ cos = Math.cos(_camera.angle),
102
+ sin = Math.sin(_camera.angle),
103
+ nodes = s.graph.nodes(),
104
+ ref = [];
105
+
106
+ // Getting and derotating the reference coordinates.
107
+ for (var i = 0; i < 2; i++) {
108
+ var n = nodes[i];
109
+ var aux = {
110
+ x: n.x * cos + n.y * sin,
111
+ y: n.y * cos - n.x * sin,
112
+ renX: n[_prefix + 'x'],
113
+ renY: n[_prefix + 'y'],
114
+ };
115
+ ref.push(aux);
116
+ }
117
+
118
+ // Applying linear interpolation.
119
+ x = ((x - ref[0].renX) / (ref[1].renX - ref[0].renX)) *
120
+ (ref[1].x - ref[0].x) + ref[0].x;
121
+ y = ((y - ref[0].renY) / (ref[1].renY - ref[0].renY)) *
122
+ (ref[1].y - ref[0].y) + ref[0].y;
123
+
124
+ // Rotating the coordinates.
125
+ _node.x = x * cos - y * sin;
126
+ _node.y = y * cos + x * sin;
127
+
128
+ s.refresh();
129
+ };
130
+
131
+ renderer.bind('overNode', nodeMouseOver);
132
+ renderer.bind('outNode', treatOutNode);
133
+ };
134
+
135
+ }).call(window);