jsmetric4java 0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. data/.gitignore +7 -0
  2. data/.rvmrc +1 -0
  3. data/Gemfile +8 -0
  4. data/README +16 -0
  5. data/Rakefile +37 -0
  6. data/bin/jsmetric4java +20 -0
  7. data/boot.rb +5 -0
  8. data/build +1 -0
  9. data/features/cyclometric_complexity/boolean_complexity_counting.feature +46 -0
  10. data/features/cyclometric_complexity/case_complexity_counting.feature +117 -0
  11. data/features/cyclometric_complexity/exception_complexity_counting.feature +81 -0
  12. data/features/cyclometric_complexity/function_detection.feature +128 -0
  13. data/features/cyclometric_complexity/if_else_complexity_counting.feature +178 -0
  14. data/features/cyclometric_complexity/loop_complexity_counting.feature +81 -0
  15. data/features/graphing/draw_basic_graph.feature +14 -0
  16. data/features/reporting/report.feature +13 -0
  17. data/features/sample_js_files_for_test/foobar.js +30 -0
  18. data/features/step_definitions/cyclometric_complexity_steps.rb +31 -0
  19. data/features/step_definitions/graph_steps.rb +10 -0
  20. data/features/step_definitions/reporting_steps.rb +14 -0
  21. data/features/support/env.rb +1 -0
  22. data/jsgraphlib/Curry-1.0.1.js +29 -0
  23. data/jsgraphlib/dracula_algorithms.js +599 -0
  24. data/jsgraphlib/dracula_graffle.js +106 -0
  25. data/jsgraphlib/dracula_graph.js +534 -0
  26. data/jsgraphlib/graphtest.html +57 -0
  27. data/jsgraphlib/jquery-1.4.2.min.js +154 -0
  28. data/jsgraphlib/jsgraphsource.js +12 -0
  29. data/jsgraphlib/raphael-min.js +7 -0
  30. data/jsgraphlib/seedrandom.js +266 -0
  31. data/jsmetric.gemspec +23 -0
  32. data/lib/cc_report.rb +24 -0
  33. data/lib/complexity_analyser.rb +90 -0
  34. data/lib/fulljslint.js +6100 -0
  35. data/lib/graphing/graph_analyser.rb +19 -0
  36. data/lib/js_lint.rb +23 -0
  37. data/lib/json2.js +480 -0
  38. data/lib/options.js +24 -0
  39. data/lib/report.rb +26 -0
  40. data/lib/utils.rb +18 -0
  41. data/lib/version.rb +3 -0
  42. data/spec/spec_helper.rb +1 -0
  43. data/tasks/dev.rb +4 -0
  44. data/tasks/run.rb +55 -0
  45. metadata +129 -0
@@ -0,0 +1,534 @@
1
+ /*
2
+ * Dracula Graph Layout and Drawing Framework 0.0.3alpha
3
+ * (c) 2010 Philipp Strathausen <strathausen@gmail.com>, http://strathausen.eu
4
+ *
5
+ * based on the Graph JavaScript framework, version 0.0.1
6
+ * (c) 2006 Aslak Hellesoy <aslak.hellesoy@gmail.com>
7
+ * (c) 2006 Dave Hoover <dave.hoover@gmail.com>
8
+ *
9
+ * Ported from Graph::Layouter::Spring in
10
+ * http://search.cpan.org/~pasky/Graph-Layderer-0.02/
11
+ * The algorithm is based on a spring-style layouter of a Java-based social
12
+ * network tracker PieSpy written by Paul Mutton E<lt>paul@jibble.orgE<gt>.
13
+ *
14
+ * This code is freely distributable under the terms of an MIT-style license.
15
+ * For details, see the Graph web site: http://dev.buildpatternd.com/trac
16
+ *
17
+ * Links:
18
+ *
19
+ * Graph Dracula JavaScript Framework:
20
+ * http://graphdracula.net
21
+ *
22
+ * Demo of the original applet:
23
+ * http://redsquirrel.com/dave/work/webdep/
24
+ *
25
+ * Mirrored original source code at snipplr:
26
+ * http://snipplr.com/view/1950/graph-javascript-framework-version-001/
27
+ *
28
+ * Original usage example:
29
+ * http://ajaxian.com/archives/new-javascriptcanvas-graph-library
30
+ *
31
+ /*--------------------------------------------------------------------------*/
32
+
33
+ // Branched by Jake Stothard <stothardj@gmail.com>.
34
+
35
+ /*
36
+ * Edge Factory
37
+ */
38
+ var AbstractEdge = function() {
39
+ }
40
+ AbstractEdge.prototype = {
41
+ hide: function() {
42
+ this.connection.fg.hide();
43
+ this.connection.bg && this.bg.connection.hide();
44
+ }
45
+ };
46
+ var EdgeFactory = function() {
47
+ this.template = new AbstractEdge();
48
+ this.template.style = new Object();
49
+ this.template.style.directed = false;
50
+ this.template.weight = 1;
51
+ };
52
+ EdgeFactory.prototype = {
53
+ build: function(source, target) {
54
+ var e = jQuery.extend(true, {}, this.template);
55
+ e.source = source;
56
+ e.target = target;
57
+ return e;
58
+ }
59
+ };
60
+
61
+ /*
62
+ * Graph
63
+ */
64
+ var Graph = function() {
65
+ this.nodes = new Object();
66
+ this.edges = [];
67
+ this.snapshots = []; // previous graph states TODO to be implemented
68
+ this.edgeFactory = new EdgeFactory();
69
+ };
70
+ Graph.prototype = {
71
+ /*
72
+ * add a node
73
+ * @id the node's ID (string or number)
74
+ * @content (optional, dictionary) can contain any information that is
75
+ * being interpreted by the layout algorithm or the graph
76
+ * representation
77
+ */
78
+ addNode: function(id, content) {
79
+ /* testing if node is already existing in the graph */
80
+ if(this.nodes[id] == undefined) {
81
+ this.nodes[id] = new Graph.Node(id, content);
82
+ }
83
+ return this.nodes[id];
84
+ },
85
+
86
+ addEdge: function(source, target, style) {
87
+ var s = this.addNode(source);
88
+ var t = this.addNode(target);
89
+ var edge = this.edgeFactory.build(s, t);
90
+ jQuery.extend(edge.style,style);
91
+ s.edges.push(edge);
92
+ this.edges.push(edge);
93
+ // NOTE: Even directed edges are added to both nodes.
94
+ t.edges.push(edge);
95
+ },
96
+
97
+ /* TODO to be implemented
98
+ * Preserve a copy of the graph state (nodes, positions, ...)
99
+ * @comment a comment describing the state
100
+ */
101
+ snapShot: function(comment) {
102
+ /* FIXME
103
+ var graph = new Graph();
104
+ graph.nodes = jQuery.extend(true, {}, this.nodes);
105
+ graph.edges = jQuery.extend(true, {}, this.edges);
106
+ this.snapshots.push({comment: comment, graph: graph});
107
+ */
108
+ },
109
+ removeNode: function(id) {
110
+ delete this.nodes[id];
111
+ for(var i = 0; i < this.edges.length; i++) {
112
+ if (this.edges[i].source.id == id || this.edges[i].target.id == id) {
113
+ this.edges.splice(i, 1);
114
+ i--;
115
+ }
116
+ }
117
+ }
118
+ };
119
+
120
+ /*
121
+ * Node
122
+ */
123
+ Graph.Node = function(id, node){
124
+ node = node || {};
125
+ node.id = id;
126
+ node.edges = [];
127
+ node.hide = function() {
128
+ this.hidden = true;
129
+ this.shape && this.shape.hide(); /* FIXME this is representation specific code and should be elsewhere */
130
+ for(i in this.edges)
131
+ (this.edges[i].source.id == id || this.edges[i].target == id) && this.edges[i].hide && this.edges[i].hide();
132
+ };
133
+ node.show = function() {
134
+ this.hidden = false;
135
+ this.shape && this.shape.show();
136
+ for(i in this.edges)
137
+ (this.edges[i].source.id == id || this.edges[i].target == id) && this.edges[i].show && this.edges[i].show();
138
+ };
139
+ return node;
140
+ };
141
+ Graph.Node.prototype = {
142
+ };
143
+
144
+ /*
145
+ * Renderer base class
146
+ */
147
+ Graph.Renderer = {};
148
+
149
+ /*
150
+ * Renderer implementation using RaphaelJS
151
+ */
152
+ Graph.Renderer.Raphael = function(element, graph, width, height) {
153
+ this.width = width || 400;
154
+ this.height = height || 400;
155
+ var selfRef = this;
156
+ this.r = Raphael(element, this.width, this.height);
157
+ this.radius = 40; /* max dimension of a node */
158
+ this.graph = graph;
159
+ this.mouse_in = false;
160
+
161
+ /* TODO default node rendering function */
162
+ if(!this.graph.render) {
163
+ this.graph.render = function() {
164
+ return;
165
+ }
166
+ }
167
+
168
+ /*
169
+ * Dragging
170
+ */
171
+ this.isDrag = false;
172
+ this.dragger = function (e) {
173
+ this.dx = e.clientX;
174
+ this.dy = e.clientY;
175
+ selfRef.isDrag = this;
176
+ this.set && this.set.animate({"fill-opacity": .1}, 200) && this.set.toFront();
177
+ e.preventDefault && e.preventDefault();
178
+ };
179
+
180
+ document.onmousemove = function (e) {
181
+ e = e || window.event;
182
+ if (selfRef.isDrag) {
183
+ var bBox = selfRef.isDrag.set.getBBox();
184
+ // TODO round the coordinates here (eg. for proper image representation)
185
+ var newX = e.clientX - selfRef.isDrag.dx + (bBox.x + bBox.width / 2);
186
+ var newY = e.clientY - selfRef.isDrag.dy + (bBox.y + bBox.height / 2);
187
+ /* prevent shapes from being dragged out of the canvas */
188
+ var clientX = e.clientX - (newX < 20 ? newX - 20 : newX > selfRef.width - 20 ? newX - selfRef.width + 20 : 0);
189
+ var clientY = e.clientY - (newY < 20 ? newY - 20 : newY > selfRef.height - 20 ? newY - selfRef.height + 20 : 0);
190
+ selfRef.isDrag.set.translate(clientX - Math.round(selfRef.isDrag.dx), clientY - Math.round(selfRef.isDrag.dy));
191
+ // console.log(clientX - Math.round(selfRef.isDrag.dx), clientY - Math.round(selfRef.isDrag.dy));
192
+ for (var i in selfRef.graph.edges) {
193
+ selfRef.graph.edges[i].connection && selfRef.graph.edges[i].connection.draw();
194
+ }
195
+ //selfRef.r.safari();
196
+ selfRef.isDrag.dx = clientX;
197
+ selfRef.isDrag.dy = clientY;
198
+ }
199
+ };
200
+ document.onmouseup = function () {
201
+ selfRef.isDrag && selfRef.isDrag.set.animate({"fill-opacity": .6}, 500);
202
+ selfRef.isDrag = false;
203
+ };
204
+ this.draw();
205
+ };
206
+ Graph.Renderer.Raphael.prototype = {
207
+ translate: function(point) {
208
+ return [
209
+ (point[0] - this.graph.layoutMinX) * this.factorX + this.radius,
210
+ (point[1] - this.graph.layoutMinY) * this.factorY + this.radius
211
+ ];
212
+ },
213
+
214
+ rotate: function(point, length, angle) {
215
+ var dx = length * Math.cos(angle);
216
+ var dy = length * Math.sin(angle);
217
+ return [point[0]+dx, point[1]+dy];
218
+ },
219
+
220
+ draw: function() {
221
+ this.factorX = (this.width - 2 * this.radius) / (this.graph.layoutMaxX - this.graph.layoutMinX);
222
+ this.factorY = (this.height - 2 * this.radius) / (this.graph.layoutMaxY - this.graph.layoutMinY);
223
+ for (i in this.graph.nodes) {
224
+ this.drawNode(this.graph.nodes[i]);
225
+ }
226
+ for (var i = 0; i < this.graph.edges.length; i++) {
227
+ this.drawEdge(this.graph.edges[i]);
228
+ }
229
+ },
230
+
231
+ drawNode: function(node) {
232
+ var point = this.translate([node.layoutPosX, node.layoutPosY]);
233
+ node.point = point;
234
+
235
+ /* if node has already been drawn, move the nodes */
236
+ if(node.shape) {
237
+ var oBBox = node.shape.getBBox();
238
+ var opoint = { x: oBBox.x + oBBox.width / 2, y: oBBox.y + oBBox.height / 2};
239
+ node.shape.translate(Math.round(point[0] - opoint.x), Math.round(point[1] - opoint.y));
240
+ this.r.safari();
241
+ return node;
242
+ }/* else, draw new nodes */
243
+
244
+ var shape;
245
+
246
+ /* if a node renderer function is provided by the user, then use it
247
+ or the default render function instead */
248
+ if(!node.render) {
249
+ node.render = function(r, node) {
250
+ /* the default node drawing */
251
+ var color = Raphael.getColor();
252
+ var ellipse = r.ellipse(0, 0, 30, 20).attr({fill: color, stroke: color, "stroke-width": 2});
253
+ /* set DOM node ID */
254
+ ellipse.node.id = node.label || node.id;
255
+ shape = r.set().
256
+ push(ellipse).
257
+ push(r.text(0, 30, node.label || node.id));
258
+ return shape;
259
+ }
260
+ }
261
+ /* or check for an ajax representation of the nodes */
262
+ if(node.shapes) {
263
+ // TODO ajax representation evaluation
264
+ }
265
+
266
+ shape = node.render(this.r, node).hide();
267
+
268
+ shape.attr({"fill-opacity": .6});
269
+ /* re-reference to the node an element belongs to, needed for dragging all elements of a node */
270
+ shape.items.forEach(function(item){ item.set = shape; item.node.style.cursor = "move"; });
271
+ shape.mousedown(this.dragger);
272
+
273
+ var box = shape.getBBox();
274
+ shape.translate(Math.round(point[0]-(box.x+box.width/2)),Math.round(point[1]-(box.y+box.height/2)))
275
+ //console.log(box,point);
276
+ node.hidden || shape.show();
277
+ node.shape = shape;
278
+ },
279
+ drawEdge: function(edge) {
280
+ /* if this edge already exists the other way around and is undirected */
281
+ if(edge.backedge)
282
+ return;
283
+ if(edge.source.hidden || edge.target.hidden) {
284
+ edge.connection && edge.connection.fg.hide() | edge.connection.bg && edge.connection.bg.hide();
285
+ return;
286
+ }
287
+ /* if edge already has been drawn, only refresh the edge */
288
+ if(!edge.connection) {
289
+ edge.style && edge.style.callback && edge.style.callback(edge); // TODO move this somewhere else
290
+ edge.connection = this.r.connection(edge.source.shape, edge.target.shape, edge.style);
291
+ return;
292
+ }
293
+ //FIXME showing doesn't work well
294
+ edge.connection.fg.show();
295
+ edge.connection.bg && edge.connection.bg.show();
296
+ edge.connection.draw();
297
+ }
298
+ };
299
+ Graph.Layout = {};
300
+ Graph.Layout.Spring = function(graph) {
301
+ this.graph = graph;
302
+ this.iterations = 500;
303
+ this.maxRepulsiveForceDistance = 6;
304
+ this.k = 2;
305
+ this.c = 0.01;
306
+ this.maxVertexMovement = 0.5;
307
+ this.layout();
308
+ };
309
+ Graph.Layout.Spring.prototype = {
310
+ layout: function() {
311
+ this.layoutPrepare();
312
+ for (var i = 0; i < this.iterations; i++) {
313
+ this.layoutIteration();
314
+ }
315
+ this.layoutCalcBounds();
316
+ },
317
+
318
+ layoutPrepare: function() {
319
+ for (i in this.graph.nodes) {
320
+ var node = this.graph.nodes[i];
321
+ node.layoutPosX = 0;
322
+ node.layoutPosY = 0;
323
+ node.layoutForceX = 0;
324
+ node.layoutForceY = 0;
325
+ }
326
+
327
+ },
328
+
329
+ layoutCalcBounds: function() {
330
+ var minx = Infinity, maxx = -Infinity, miny = Infinity, maxy = -Infinity;
331
+
332
+ for (i in this.graph.nodes) {
333
+ var x = this.graph.nodes[i].layoutPosX;
334
+ var y = this.graph.nodes[i].layoutPosY;
335
+
336
+ if(x > maxx) maxx = x;
337
+ if(x < minx) minx = x;
338
+ if(y > maxy) maxy = y;
339
+ if(y < miny) miny = y;
340
+ }
341
+
342
+ this.graph.layoutMinX = minx;
343
+ this.graph.layoutMaxX = maxx;
344
+ this.graph.layoutMinY = miny;
345
+ this.graph.layoutMaxY = maxy;
346
+ },
347
+
348
+ layoutIteration: function() {
349
+ // Forces on nodes due to node-node repulsions
350
+
351
+ var prev = new Array();
352
+ for(var c in this.graph.nodes) {
353
+ var node1 = this.graph.nodes[c];
354
+ for (var d in prev) {
355
+ var node2 = this.graph.nodes[prev[d]];
356
+ this.layoutRepulsive(node1, node2);
357
+
358
+ }
359
+ prev.push(c);
360
+ }
361
+
362
+ // Forces on nodes due to edge attractions
363
+ for (var i = 0; i < this.graph.edges.length; i++) {
364
+ var edge = this.graph.edges[i];
365
+ this.layoutAttractive(edge);
366
+ }
367
+
368
+ // Move by the given force
369
+ for (i in this.graph.nodes) {
370
+ var node = this.graph.nodes[i];
371
+ var xmove = this.c * node.layoutForceX;
372
+ var ymove = this.c * node.layoutForceY;
373
+
374
+ var max = this.maxVertexMovement;
375
+ if(xmove > max) xmove = max;
376
+ if(xmove < -max) xmove = -max;
377
+ if(ymove > max) ymove = max;
378
+ if(ymove < -max) ymove = -max;
379
+
380
+ node.layoutPosX += xmove;
381
+ node.layoutPosY += ymove;
382
+ node.layoutForceX = 0;
383
+ node.layoutForceY = 0;
384
+ }
385
+ },
386
+
387
+ layoutRepulsive: function(node1, node2) {
388
+ var dx = node2.layoutPosX - node1.layoutPosX;
389
+ var dy = node2.layoutPosY - node1.layoutPosY;
390
+ var d2 = dx * dx + dy * dy;
391
+ if(d2 < 0.01) {
392
+ dx = 0.1 * Math.random() + 0.1;
393
+ dy = 0.1 * Math.random() + 0.1;
394
+ var d2 = dx * dx + dy * dy;
395
+ }
396
+ var d = Math.sqrt(d2);
397
+ if(d < this.maxRepulsiveForceDistance) {
398
+ var repulsiveForce = this.k * this.k / d;
399
+ node2.layoutForceX += repulsiveForce * dx / d;
400
+ node2.layoutForceY += repulsiveForce * dy / d;
401
+ node1.layoutForceX -= repulsiveForce * dx / d;
402
+ node1.layoutForceY -= repulsiveForce * dy / d;
403
+ }
404
+ },
405
+
406
+ layoutAttractive: function(edge) {
407
+ var node1 = edge.source;
408
+ var node2 = edge.target;
409
+
410
+ var dx = node2.layoutPosX - node1.layoutPosX;
411
+ var dy = node2.layoutPosY - node1.layoutPosY;
412
+ var d2 = dx * dx + dy * dy;
413
+ if(d2 < 0.01) {
414
+ dx = 0.1 * Math.random() + 0.1;
415
+ dy = 0.1 * Math.random() + 0.1;
416
+ var d2 = dx * dx + dy * dy;
417
+ }
418
+ var d = Math.sqrt(d2);
419
+ if(d > this.maxRepulsiveForceDistance) {
420
+ d = this.maxRepulsiveForceDistance;
421
+ d2 = d * d;
422
+ }
423
+ var attractiveForce = (d2 - this.k * this.k) / this.k;
424
+ if(edge.attraction == undefined) edge.attraction = 1;
425
+ attractiveForce *= Math.log(edge.attraction) * 0.5 + 1;
426
+
427
+ node2.layoutForceX -= attractiveForce * dx / d;
428
+ node2.layoutForceY -= attractiveForce * dy / d;
429
+ node1.layoutForceX += attractiveForce * dx / d;
430
+ node1.layoutForceY += attractiveForce * dy / d;
431
+ }
432
+ };
433
+
434
+ Graph.Layout.Ordered = function(graph, order) {
435
+ this.graph = graph;
436
+ this.order = order;
437
+ this.layout();
438
+ };
439
+ Graph.Layout.Ordered.prototype = {
440
+ layout: function() {
441
+ this.layoutPrepare();
442
+ this.layoutCalcBounds();
443
+ },
444
+
445
+ layoutPrepare: function(order) {
446
+ for (i in this.graph.nodes) {
447
+ var node = this.graph.nodes[i];
448
+ node.layoutPosX = 0;
449
+ node.layoutPosY = 0;
450
+ }
451
+ var counter = 0;
452
+ for (i in this.order) {
453
+ var node = this.order[i];
454
+ node.layoutPosX = counter;
455
+ node.layoutPosY = Math.random();
456
+ counter++;
457
+ }
458
+ },
459
+
460
+ layoutCalcBounds: function() {
461
+ var minx = Infinity, maxx = -Infinity, miny = Infinity, maxy = -Infinity;
462
+
463
+ for (i in this.graph.nodes) {
464
+ var x = this.graph.nodes[i].layoutPosX;
465
+ var y = this.graph.nodes[i].layoutPosY;
466
+
467
+ if(x > maxx) maxx = x;
468
+ if(x < minx) minx = x;
469
+ if(y > maxy) maxy = y;
470
+ if(y < miny) miny = y;
471
+ }
472
+
473
+ this.graph.layoutMinX = minx;
474
+ this.graph.layoutMaxX = maxx;
475
+
476
+ this.graph.layoutMinY = miny;
477
+ this.graph.layoutMaxY = maxy;
478
+ },
479
+ };
480
+
481
+ /*
482
+ * usefull JavaScript extensions,
483
+ */
484
+
485
+ function log(a) {console.log&&console.log(a);}
486
+
487
+ /*
488
+ * Raphael Tooltip Plugin
489
+ * - attaches an element as a tooltip to another element
490
+ *
491
+ * Usage example, adding a rectangle as a tooltip to a circle:
492
+ *
493
+ * paper.circle(100,100,10).tooltip(paper.rect(0,0,20,30));
494
+ *
495
+ * If you want to use more shapes, you'll have to put them into a set.
496
+ *
497
+ */
498
+ Raphael.el.tooltip = function (tp) {
499
+ this.tp = tp;
500
+ this.tp.o = {x: 0, y: 0};
501
+ this.tp.hide();
502
+ this.hover(
503
+ function(event){
504
+ this.mousemove(function(event){
505
+ this.tp.translate(event.clientX -
506
+ this.tp.o.x,event.clientY - this.tp.o.y);
507
+ this.tp.o = {x: event.clientX, y: event.clientY};
508
+ });
509
+ this.tp.show().toFront();
510
+ },
511
+ function(event){
512
+ this.tp.hide();
513
+ this.unmousemove();
514
+ });
515
+ return this;
516
+ };
517
+
518
+ /* For IE */
519
+ if (!Array.prototype.forEach)
520
+ {
521
+ Array.prototype.forEach = function(fun /*, thisp*/)
522
+ {
523
+ var len = this.length;
524
+ if (typeof fun != "function")
525
+ throw new TypeError();
526
+
527
+ var thisp = arguments[1];
528
+ for (var i = 0; i < len; i++)
529
+ {
530
+ if (i in this)
531
+ fun.call(thisp, this[i], i, this);
532
+ }
533
+ };
534
+ }
@@ -0,0 +1,57 @@
1
+ <html>
2
+ <head>
3
+ <title>Graphing JavaScript with JavaScript</title>
4
+
5
+ </head>
6
+ <body>
7
+ <div id='canvas'></div>
8
+
9
+ <script type="text/javascript" src="raphael-min.js"></script>
10
+ <script type="text/javascript" src="dracula_graffle.js"></script>
11
+ <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script>
12
+ <script type="text/javascript" src="dracula_graph.js"></script>
13
+ <script type="text/javascript" src="dracula_algorithms.js"></script>
14
+ <script type="text/javascript" src="jsgraphsource.js"></script>
15
+ <script type="text/javascript">
16
+ $(document).ready(function() {
17
+
18
+ for (var js_class in graphdata) {
19
+ if (graphdata.hasOwnProperty(js_class)) {
20
+ process_class(graphdata[js_class]);
21
+ }
22
+ }
23
+ });
24
+
25
+ function process_class(js_class) {
26
+ var width = 300;
27
+ var height = 300;
28
+
29
+ var g = new Graph();
30
+ g.edgeFactory.template.style.directed = true;
31
+ for (js_method in js_class) {
32
+ if (js_class.hasOwnProperty(js_method)) {
33
+ process_method(g, js_method, js_class[js_method]);
34
+ }
35
+ }
36
+ var layouter = new Graph.Layout.Ordered(g, topological_sort(g));
37
+ var renderer = new Graph.Renderer.Raphael('canvas', g, width, height);
38
+ }
39
+
40
+ function process_method(graph, js_method_name, js_calls) {
41
+ var i;
42
+ for (i = 0; i < js_calls.length; i++) {
43
+ graph.addEdge(js_method_name, js_calls[i]);
44
+ }
45
+ }
46
+
47
+
48
+ </script>
49
+
50
+
51
+ </body>
52
+ </html>
53
+ <!-- Ideas - to do
54
+ Initial load produces a list of classes
55
+ click a link to view a graph for that class instead of all graphs on one page
56
+
57
+ -->