neo-viz 1.0.1
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.
- data/.gitignore +9 -0
- data/.livereload +20 -0
- data/.rspec +2 -0
- data/.rvmrc +3 -0
- data/Gemfile +6 -0
- data/LICENSE +19 -0
- data/README.md +120 -0
- data/Rakefile +12 -0
- data/bin/neo-viz +12 -0
- data/config.ru +35 -0
- data/lib/neo-viz.rb +185 -0
- data/lib/neo-viz/version.rb +6 -0
- data/neo-viz.gemspec +37 -0
- data/public/coffeescripts/app_context.coffee +89 -0
- data/public/coffeescripts/canvas_util.coffee +68 -0
- data/public/coffeescripts/event_broker.coffee +16 -0
- data/public/coffeescripts/filters.coffee +113 -0
- data/public/coffeescripts/main.coffee.erb +132 -0
- data/public/coffeescripts/neo4j.coffee +90 -0
- data/public/coffeescripts/renderer.coffee +141 -0
- data/public/coffeescripts/space.coffee +81 -0
- data/public/images/ajax-loader.gif +0 -0
- data/public/javascripts/data.js +45 -0
- data/public/javascripts/data2.js +1287 -0
- data/public/javascripts/main.sprockets.js +9 -0
- data/public/lib/arbor/arbor-tween.js +86 -0
- data/public/lib/arbor/arbor.js +67 -0
- data/public/lib/jQuery/jquery-1.6.1.min.js +18 -0
- data/public/lib/jasmine-1.1.0/MIT.LICENSE +20 -0
- data/public/lib/jasmine-1.1.0/jasmine-html.js +190 -0
- data/public/lib/jasmine-1.1.0/jasmine.css +166 -0
- data/public/lib/jasmine-1.1.0/jasmine.js +2476 -0
- data/public/lib/jasmine-1.1.0/jasmine_favicon.png +0 -0
- data/public/lib/stdlib/stdlib.js +115 -0
- data/public/lib/sylvester-0.1.3/CHANGELOG.txt +29 -0
- data/public/lib/sylvester-0.1.3/sylvester.js +1 -0
- data/public/lib/sylvester-0.1.3/sylvester.js.gz +0 -0
- data/public/lib/sylvester-0.1.3/sylvester.src.js +1254 -0
- data/public/scss/main.scss +152 -0
- data/public/scss/mixins.scss +37 -0
- data/spec/coffeescripts/canvas_util_spec.coffee +4 -0
- data/spec/coffeescripts/filters_spec.coffee +37 -0
- data/spec/coffeescripts/neo4j_spec.coffee +76 -0
- data/spec/neo_viz_spec.rb +48 -0
- data/spec/spec_helper.rb +17 -0
- data/spec/support/struct_matcher.rb +117 -0
- data/views/_filters.haml +22 -0
- data/views/_partial.haml +39 -0
- data/views/embedded.haml +15 -0
- data/views/index.haml +19 -0
- data/views/jasmine_specs_runner.haml +50 -0
- metadata +236 -0
data/neo-viz.gemspec
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "neo-viz/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "neo-viz"
|
7
|
+
s.version = Neo::Viz::VERSION
|
8
|
+
s.authors = ["Anders Janmyr"]
|
9
|
+
s.email = ["anders.janmyr@jayway.com"]
|
10
|
+
s.homepage = ""
|
11
|
+
s.summary = %q{A gem for visualizing a Neo database with Javascript}
|
12
|
+
s.description = %q{A gem for visualizing a Neo database with Javascript}
|
13
|
+
|
14
|
+
s.rubyforge_project = "neo-viz"
|
15
|
+
|
16
|
+
s.add_dependency 'sprockets'
|
17
|
+
s.add_dependency 'sinatra'
|
18
|
+
s.add_dependency 'sinatra-reloader'
|
19
|
+
s.add_dependency 'neo4j', '~> 1.1'
|
20
|
+
s.add_dependency 'coffee-script'
|
21
|
+
s.add_dependency 'haml'
|
22
|
+
s.add_dependency 'sass'
|
23
|
+
s.add_dependency 'json'
|
24
|
+
s.add_dependency 'pry'
|
25
|
+
|
26
|
+
|
27
|
+
s.add_development_dependency 'rspec'
|
28
|
+
s.add_development_dependency 'rack-test'
|
29
|
+
s.add_development_dependency 'jasmine'
|
30
|
+
|
31
|
+
s.requirements << 'coffee-script'
|
32
|
+
|
33
|
+
s.files = `git ls-files`.split("\n")
|
34
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
35
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
36
|
+
s.require_paths = ["lib"]
|
37
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
$ = jQuery
|
2
|
+
|
3
|
+
class AppContext
|
4
|
+
|
5
|
+
constructor: (@eventBroker)->
|
6
|
+
@nodeFilter = ''
|
7
|
+
@keyFilter = ''
|
8
|
+
@nodeData = null
|
9
|
+
@nodeCount = 10
|
10
|
+
@activatedNodeId = null
|
11
|
+
@selectedObject = {"id":0, "kind":""}
|
12
|
+
|
13
|
+
setNodeCount: (n) ->
|
14
|
+
if (@nodeCount != n)
|
15
|
+
@nodeCount = n
|
16
|
+
@publish("nodeCountChanged")
|
17
|
+
|
18
|
+
getNodeCount: () ->
|
19
|
+
@nodeCount
|
20
|
+
|
21
|
+
setKeyFilter: (keyFilter) ->
|
22
|
+
if (@keyFilter != keyFilter)
|
23
|
+
@keyFilter = keyFilter
|
24
|
+
@publish("keyFilterChanged")
|
25
|
+
|
26
|
+
getKeyFilter: ->
|
27
|
+
@keyFilter
|
28
|
+
|
29
|
+
setNodeFilter: (filter) ->
|
30
|
+
if (@nodeFilter != filter)
|
31
|
+
@nodeFilter = filter
|
32
|
+
@publish("nodeFilterChanged")
|
33
|
+
|
34
|
+
getNodeFilter: ->
|
35
|
+
@nodeFilter
|
36
|
+
|
37
|
+
setActivatedNodeId: (nodeId, suppressChangedEvent=false) ->
|
38
|
+
if (@activatedNodeId != nodeId)
|
39
|
+
@activatedNodeId = nodeId
|
40
|
+
if (!suppressChangedEvent)
|
41
|
+
@publish("activatedNodeIdChanged")
|
42
|
+
|
43
|
+
getActivatedNodeId: ->
|
44
|
+
@activatedNodeId
|
45
|
+
|
46
|
+
setSelectedObject: (id, kind) ->
|
47
|
+
if (@selectedObjectId != id && @selectedObjectKind != kind)
|
48
|
+
@selectedObject.id = id
|
49
|
+
@selectedObject.kind = kind
|
50
|
+
@publish("selectedObjectChanged")
|
51
|
+
|
52
|
+
getSelectedObject: ->
|
53
|
+
@selectedObject
|
54
|
+
|
55
|
+
|
56
|
+
# I.e. nodeData.nodes, nodeData.rels
|
57
|
+
setNodeData: (nodeData) ->
|
58
|
+
if (@nodeData != nodeData)
|
59
|
+
@nodeData = nodeData
|
60
|
+
@graph = new Graph(nodeData.nodes, nodeData.rels)
|
61
|
+
@publish("nodeDataChanged")
|
62
|
+
|
63
|
+
getNodeData: ->
|
64
|
+
@nodeData
|
65
|
+
|
66
|
+
getGraph: ->
|
67
|
+
@graph
|
68
|
+
|
69
|
+
# I.e. hiddenNodeData.nodeIds, hiddenNodeData.relIds
|
70
|
+
setHiddenNodeData: (hiddenNodeData) ->
|
71
|
+
if (@hiddenNodeData != hiddenNodeData)
|
72
|
+
@hiddenNodeData = hiddenNodeData
|
73
|
+
@publish("hiddenNodeDataChanged")
|
74
|
+
|
75
|
+
getHiddenNodeData: ->
|
76
|
+
@hiddenNodeData
|
77
|
+
|
78
|
+
clearHiddenNodeData: ->
|
79
|
+
@hiddenNodeData = {nodeIds:[], relIds:[]}
|
80
|
+
@publish("hiddenNodeDataChanged")
|
81
|
+
|
82
|
+
# TODO: How do we make this a private method?
|
83
|
+
publish: (eventName) ->
|
84
|
+
@eventBroker.publish(eventName)
|
85
|
+
|
86
|
+
$ ->
|
87
|
+
root = exports ? this
|
88
|
+
root.appContext = new AppContext(root.eventBroker)
|
89
|
+
|
@@ -0,0 +1,68 @@
|
|
1
|
+
root = exports ? window
|
2
|
+
|
3
|
+
root.CanvasUtil =
|
4
|
+
centerToEdge: (val, delta) ->
|
5
|
+
val - delta/2
|
6
|
+
|
7
|
+
roundRect: (ctx, point, width, height, color, radius=5) ->
|
8
|
+
x = @centerToEdge(point.x, width)
|
9
|
+
y = @centerToEdge(point.y, height)
|
10
|
+
ctx.beginPath()
|
11
|
+
ctx.moveTo(x + radius, y)
|
12
|
+
ctx.fillStyle = @createGradient(ctx, color, y, height)
|
13
|
+
ctx.lineTo(x + width - radius, y)
|
14
|
+
ctx.quadraticCurveTo(x + width, y, x + width, y + radius)
|
15
|
+
ctx.lineTo(x + width, y + height - radius)
|
16
|
+
ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height)
|
17
|
+
ctx.lineTo(x + radius, y + height)
|
18
|
+
ctx.quadraticCurveTo(x, y + height, x, y + height - radius)
|
19
|
+
ctx.lineTo(x, y + radius)
|
20
|
+
ctx.quadraticCurveTo(x, y, x + radius, y)
|
21
|
+
ctx.closePath()
|
22
|
+
ctx.fill()
|
23
|
+
|
24
|
+
line: (ctx, fromPoint, toPoint, width = 2) ->
|
25
|
+
ctx.lineWidth = width
|
26
|
+
ctx.beginPath()
|
27
|
+
ctx.moveTo fromPoint.x, fromPoint.y
|
28
|
+
ctx.lineTo toPoint.x, toPoint.y
|
29
|
+
@arrow(ctx, fromPoint, toPoint, width)
|
30
|
+
ctx.stroke()
|
31
|
+
|
32
|
+
arrow: (ctx, fromPoint, toPoint, width = 2) ->
|
33
|
+
ctx.save()
|
34
|
+
mx = (toPoint.x + fromPoint.x) / 2
|
35
|
+
my = (toPoint.y + fromPoint.y) / 2
|
36
|
+
|
37
|
+
ctx.translate(mx, my)
|
38
|
+
# draw your arrow, with its origin at [0, 0]
|
39
|
+
angle = Math.atan2(toPoint.y-fromPoint.y, toPoint.x-fromPoint.x)
|
40
|
+
ctx.rotate(angle)
|
41
|
+
arrowSize = 6
|
42
|
+
ctx.moveTo(0, 0)
|
43
|
+
ctx.lineTo(-arrowSize, -arrowSize)
|
44
|
+
ctx.moveTo(0, 0)
|
45
|
+
ctx.lineTo(-arrowSize, arrowSize)
|
46
|
+
ctx.restore()
|
47
|
+
|
48
|
+
textSize: (ctx, text) ->
|
49
|
+
lineHeight = ctx.measureText(text[0]).height or 16
|
50
|
+
width = 0
|
51
|
+
count = text.length
|
52
|
+
height = count * lineHeight + 20
|
53
|
+
for line in text
|
54
|
+
width = Math.max ctx.measureText(line).width, width
|
55
|
+
{width, height, count, lineHeight }
|
56
|
+
|
57
|
+
drawText: (ctx, text, left, top) ->
|
58
|
+
textSize = @textSize(ctx, text)
|
59
|
+
for i in [0...textSize.count]
|
60
|
+
line = text[i]
|
61
|
+
ctx.fillText(line, left, top + i*textSize.lineHeight)
|
62
|
+
|
63
|
+
createGradient: (ctx, color, y, height) ->
|
64
|
+
gradient = ctx.createLinearGradient(0, y, 0, y+height+40)
|
65
|
+
gradient.addColorStop(0, color)
|
66
|
+
gradient.addColorStop(1, "white")
|
67
|
+
gradient
|
68
|
+
|
@@ -0,0 +1,16 @@
|
|
1
|
+
$ = jQuery
|
2
|
+
|
3
|
+
class EventBroker
|
4
|
+
|
5
|
+
publish: (eventName) ->
|
6
|
+
$("body").trigger(eventName)
|
7
|
+
console.log 'published ' + eventName
|
8
|
+
|
9
|
+
subscribe: (eventName, func) ->
|
10
|
+
$("body").bind(eventName, () ->
|
11
|
+
func()
|
12
|
+
)
|
13
|
+
|
14
|
+
$ ->
|
15
|
+
root = exports ? this
|
16
|
+
root.eventBroker = new EventBroker
|
@@ -0,0 +1,113 @@
|
|
1
|
+
$ = jQuery
|
2
|
+
|
3
|
+
initFormListeners = (appContext, eventBroker) ->
|
4
|
+
$('#node-count').change ->
|
5
|
+
appContext.setNodeCount($(this).val())
|
6
|
+
eventBroker.publish('refresh')
|
7
|
+
|
8
|
+
$('#node-filter').change ->
|
9
|
+
appContext.setNodeFilter($(this).val())
|
10
|
+
eventBroker.publish('refresh')
|
11
|
+
|
12
|
+
$('#key-filter').change ->
|
13
|
+
appContext.setKeyFilter($(this).val())
|
14
|
+
eventBroker.publish('refresh')
|
15
|
+
|
16
|
+
initSubscribers = (appContext, eventBroker) ->
|
17
|
+
eventBroker.subscribe('nodeDataChanged', ->
|
18
|
+
refreshRelationFilters(appContext)
|
19
|
+
)
|
20
|
+
|
21
|
+
refreshRelationFilters = (appContext)->
|
22
|
+
activatedNodeId = appContext.getActivatedNodeId()
|
23
|
+
return if (activatedNodeId == null)
|
24
|
+
|
25
|
+
graph = appContext.getGraph()
|
26
|
+
activatedNode = graph.load(activatedNodeId)
|
27
|
+
# Event timing issue: when reloading data we have not
|
28
|
+
# set the new activatedNodeId yet so we might try to fetch non-existent node
|
29
|
+
# here.
|
30
|
+
return if (activatedNode == null)
|
31
|
+
|
32
|
+
incomingTypes = (rel.type for rel in activatedNode.incoming()).unique()
|
33
|
+
outgoingTypes = (rel.type for rel in activatedNode.outgoing()).unique()
|
34
|
+
allRelTypes = incomingTypes.union(outgoingTypes).sort()
|
35
|
+
|
36
|
+
$('#relationsFilterTable').empty()
|
37
|
+
|
38
|
+
for relType in allRelTypes
|
39
|
+
hasIncoming = incomingTypes.contains(relType)
|
40
|
+
hasOutgoing = outgoingTypes.contains(relType)
|
41
|
+
inCheckboxHtml = buildCheckboxHtml relType, "in", hasIncoming
|
42
|
+
outCheckboxHtml = buildCheckboxHtml relType, "out", hasOutgoing
|
43
|
+
|
44
|
+
$('#relationsFilterTable').append("<tr><td>#{relType} #{inCheckboxHtml}</td><td>#{outCheckboxHtml}</td></tr>")
|
45
|
+
|
46
|
+
$("#relationsFilterTable input").change ->
|
47
|
+
updateHiddenNodeData(appContext, graph, activatedNode)
|
48
|
+
|
49
|
+
updateHiddenNodeData = (appContext, graph, activatedNode) ->
|
50
|
+
relsToHide = ({ type:"#{checkbox.name}", direction:"#{checkbox.value}"} for checkbox in $("#relationsFilterTable input") when (!checkbox.disabled && !checkbox.checked))
|
51
|
+
|
52
|
+
incomingTypesToHide = (rel.type for rel in relsToHide when rel.direction == "in")
|
53
|
+
outgoingTypesToHide = (rel.type for rel in relsToHide when rel.direction == "out")
|
54
|
+
|
55
|
+
relsHiddenByUser = activatedNode.incoming(incomingTypesToHide)
|
56
|
+
relsHiddenByUser = relsHiddenByUser.concat(activatedNode.outgoing(outgoingTypesToHide))
|
57
|
+
|
58
|
+
hiddenNodeData = buildHiddenNodeData graph, activatedNode, relsHiddenByUser
|
59
|
+
|
60
|
+
appContext.setHiddenNodeData(hiddenNodeData)
|
61
|
+
|
62
|
+
buildHiddenNodeData = (graph, activatedNode, relsHiddenByUser) ->
|
63
|
+
|
64
|
+
hiddenNodeData = nodeIds:[], relIds:(rel.id for rel in relsHiddenByUser)
|
65
|
+
|
66
|
+
allRels = graph.relationships
|
67
|
+
activeRels = allRels.diff(relsHiddenByUser)
|
68
|
+
for rel in activatedNode.both()
|
69
|
+
if relsHiddenByUser.contains(rel)
|
70
|
+
otherNode = rel.other(activatedNode)
|
71
|
+
|
72
|
+
if (!graph.areConnected(activatedNode, otherNode, activeRels))
|
73
|
+
#console.log "node " + activatedNode.id + " and " + otherNode.id + " are not connected"
|
74
|
+
# No connections to otherNode exists, so hide otherNode and its subgraph
|
75
|
+
appendHiddenNodeDataForSubGraph(otherNode, activeRels, hiddenNodeData)
|
76
|
+
|
77
|
+
hiddenNodeData
|
78
|
+
|
79
|
+
appendHiddenNodeDataForSubGraph = (node, mutableActiveRels, hiddenNodeData) -> #={nodeIds: [], relIds: []}) ->
|
80
|
+
|
81
|
+
hiddenNodeData.nodeIds.push(node.id)
|
82
|
+
for rel in node.both()
|
83
|
+
if mutableActiveRels.contains(rel)
|
84
|
+
hiddenNodeData.relIds.push(rel.id)
|
85
|
+
# Remove the relationship already traversed so that
|
86
|
+
# next iteration does not traverse "backwards" again
|
87
|
+
mutableActiveRels.remove(mutableActiveRels.indexOf(rel))
|
88
|
+
other = rel.other(node)
|
89
|
+
# Have we already hidden the other node?
|
90
|
+
if (!hiddenNodeData.nodeIds.contains(other.id))
|
91
|
+
# No, go ahead and hide its subgraph.
|
92
|
+
appendHiddenNodeDataForSubGraph(other, mutableActiveRels, hiddenNodeData)
|
93
|
+
|
94
|
+
|
95
|
+
buildCheckboxHtml = (relType, value, enabled) ->
|
96
|
+
html = "<input type='checkbox' name=\"#{relType}\" value='#{value}'"
|
97
|
+
html += " checked='true'" if enabled
|
98
|
+
html += " disabled='disabled'" if !enabled
|
99
|
+
html += " />"
|
100
|
+
html += "<del>" if !enabled
|
101
|
+
html += value
|
102
|
+
html += "</del>" if !enabled
|
103
|
+
html
|
104
|
+
|
105
|
+
|
106
|
+
root = exports ? this
|
107
|
+
root.test_buildHiddenNodeData = buildHiddenNodeData # global for unit testing
|
108
|
+
|
109
|
+
|
110
|
+
$ ->
|
111
|
+
|
112
|
+
initSubscribers(@appContext, @eventBroker)
|
113
|
+
initFormListeners(@appContext, @eventBroker)
|
@@ -0,0 +1,132 @@
|
|
1
|
+
//= require 'renderer.coffee'
|
2
|
+
//= require 'space.coffee'
|
3
|
+
|
4
|
+
$ = jQuery
|
5
|
+
|
6
|
+
initFormListeners= (space, renderer, evalCode) ->
|
7
|
+
$('#loadForm').submit (e) ->
|
8
|
+
e.preventDefault()
|
9
|
+
console.log 'load'
|
10
|
+
evalCode()
|
11
|
+
|
12
|
+
showNodeDetails = (space, id=0) =>
|
13
|
+
node = space.node(id)
|
14
|
+
return unless node
|
15
|
+
showDetails(node.data)
|
16
|
+
|
17
|
+
showDetails = (data) =>
|
18
|
+
html = for key, value of data
|
19
|
+
if key is 'first' then '' else "<tr><td>#{key}</td><td>#{value}</td></tr>"
|
20
|
+
$('#details').empty().append(html.join('\n'))
|
21
|
+
|
22
|
+
showEdgeDetails = (space, id=0) =>
|
23
|
+
edge = space.rel(id)
|
24
|
+
return unless edge
|
25
|
+
showDetails(edge.data)
|
26
|
+
|
27
|
+
|
28
|
+
initEventSubscribers = (eventBroker, appContext, space, renderer, getData) ->
|
29
|
+
eventBroker.subscribe('nodeCountChanged', ->
|
30
|
+
space.setNodeCount appContext.getNodeCount()
|
31
|
+
)
|
32
|
+
|
33
|
+
eventBroker.subscribe('nodeFilterChanged', ->
|
34
|
+
space.setFilter appContext.getNodeFilter()
|
35
|
+
)
|
36
|
+
|
37
|
+
eventBroker.subscribe('keyFilterChanged', ->
|
38
|
+
renderer.setKeyFilter appContext.getKeyFilter()
|
39
|
+
)
|
40
|
+
|
41
|
+
eventBroker.subscribe('nodeDataChanged', ->
|
42
|
+
appContext.clearHiddenNodeData()
|
43
|
+
nodeData = appContext.getNodeData()
|
44
|
+
space.addData nodeData
|
45
|
+
if nodeData.nodes.length > 0
|
46
|
+
firstNode = nodeData.nodes[0]
|
47
|
+
appContext.setActivatedNodeId(firstNode.id)
|
48
|
+
appContext.setSelectedObject(firstNode.id, "node")
|
49
|
+
)
|
50
|
+
|
51
|
+
eventBroker.subscribe('hiddenNodeDataChanged', ->
|
52
|
+
space.setHiddenData appContext.getHiddenNodeData()
|
53
|
+
)
|
54
|
+
|
55
|
+
eventBroker.subscribe('activatedNodeIdChanged', ->
|
56
|
+
getData appContext.getActivatedNodeId()
|
57
|
+
)
|
58
|
+
|
59
|
+
eventBroker.subscribe('selectedObjectChanged', ->
|
60
|
+
object = appContext.getSelectedObject()
|
61
|
+
if (object.kind == "node")
|
62
|
+
showNodeDetails(space, object.id)
|
63
|
+
else
|
64
|
+
showEdgeDetails(space, object.id)
|
65
|
+
|
66
|
+
)
|
67
|
+
|
68
|
+
eventBroker.subscribe('refresh', ->
|
69
|
+
space.refresh()
|
70
|
+
)
|
71
|
+
|
72
|
+
$ ->
|
73
|
+
|
74
|
+
$('#consoleOutput').hide()
|
75
|
+
|
76
|
+
sys = arbor.ParticleSystem(1000, 600, 0.5) # create the system with sensible repulsion/stiffness/friction
|
77
|
+
sys.parameters({gravity:true}) # use center-gravity to make the graph settle nicely (ymmv)
|
78
|
+
|
79
|
+
space = new Space(sys, @appContext.getNodeCount())
|
80
|
+
|
81
|
+
appendToConsole = (text) ->
|
82
|
+
$('#console').val($('#console').val()+ '\n#' + text)
|
83
|
+
|
84
|
+
setError = (text) ->
|
85
|
+
$('#consoleOutputArea').val(text)
|
86
|
+
|
87
|
+
getData = (id=0) =>
|
88
|
+
depth = $('#depth').val()
|
89
|
+
code = if id is 0 then "node = Neo4j.ref_node" else "node = Node._load(#{id})"
|
90
|
+
code += "; viz node"
|
91
|
+
innerEvalCode(code, depth)
|
92
|
+
|
93
|
+
evalCode = =>
|
94
|
+
code = $('#console').val()
|
95
|
+
depth = $('#depth').val()
|
96
|
+
innerEvalCode(code, depth)
|
97
|
+
|
98
|
+
innerEvalCode = (code, depth) =>
|
99
|
+
appContext = @appContext
|
100
|
+
console.log code
|
101
|
+
$('#eval').attr('disabled', 'true')
|
102
|
+
$('#ajax-loader').show()
|
103
|
+
$.getJSON "<%= root_url() %>/eval", {code: code, depth: depth}, (data) ->
|
104
|
+
$('#ajax-loader').hide()
|
105
|
+
$('#eval').removeAttr('disabled')
|
106
|
+
if data.result
|
107
|
+
$('#consoleOutput').show()
|
108
|
+
setError data.result
|
109
|
+
else
|
110
|
+
setError ""
|
111
|
+
$('#consoleOutput').hide()
|
112
|
+
appContext.setNodeData data
|
113
|
+
|
114
|
+
activateNode = (id=0) =>
|
115
|
+
@appContext.setActivatedNodeId(id)
|
116
|
+
|
117
|
+
selectNode = (id=0) =>
|
118
|
+
@appContext.setSelectedObject(id, "node")
|
119
|
+
|
120
|
+
selectEdge = (id=0) =>
|
121
|
+
@appContext.setSelectedObject(id, "edge")
|
122
|
+
|
123
|
+
objectHandler =
|
124
|
+
activated: activateNode
|
125
|
+
selectedNode: selectNode
|
126
|
+
selectedEdge: selectEdge
|
127
|
+
|
128
|
+
sys.renderer = Renderer("#viewport", objectHandler)
|
129
|
+
|
130
|
+
initFormListeners(space, sys.renderer, evalCode)
|
131
|
+
initEventSubscribers(@eventBroker, @appContext, space, sys.renderer, getData)
|
132
|
+
activateNode(0)
|