maglev-webtools 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (125) hide show
  1. data/LICENSE.txt +25 -0
  2. data/README.rdoc +121 -0
  3. data/bin/webtools +15 -0
  4. data/lib/web_tools/#debugger.rb# +212 -0
  5. data/lib/web_tools/browser.rb +45 -0
  6. data/lib/web_tools/debugger.rb +219 -0
  7. data/lib/web_tools/info.rb +29 -0
  8. data/lib/web_tools/middleware/debugger.rb +118 -0
  9. data/lib/web_tools/support/app_model.rb +117 -0
  10. data/lib/web_tools/support/code_browser.rb +109 -0
  11. data/lib/web_tools/support/ruby.rb +132 -0
  12. data/lib/web_tools/support/service_helper.rb +22 -0
  13. data/lib/web_tools/support/smalltalk_extensions.rb +65 -0
  14. data/lib/web_tools/support/smalltalk_tools.rb +16 -0
  15. data/lib/web_tools/ui.rb +67 -0
  16. data/lib/web_tools.rb +10 -0
  17. data/public/images/favicon.ico +0 -0
  18. data/public/javascript/CodeMirror/LICENSE +23 -0
  19. data/public/javascript/CodeMirror/css/Smalltalk.css +34 -0
  20. data/public/javascript/CodeMirror/js/codemirror.js +582 -0
  21. data/public/javascript/CodeMirror/js/editor.js +1671 -0
  22. data/public/javascript/CodeMirror/js/highlight.js +68 -0
  23. data/public/javascript/CodeMirror/js/parseSmalltalk.js +126 -0
  24. data/public/javascript/CodeMirror/js/parsedummy.js +32 -0
  25. data/public/javascript/CodeMirror/js/select.js +699 -0
  26. data/public/javascript/CodeMirror/js/stringstream.js +159 -0
  27. data/public/javascript/CodeMirror/js/tokenize.js +57 -0
  28. data/public/javascript/CodeMirror/js/undo.js +413 -0
  29. data/public/javascript/CodeMirror/js/util.js +133 -0
  30. data/public/javascript/CodeMirror/testSmalltalkParser.html +116 -0
  31. data/public/javascript/ace/ace-uncompressed.js +17299 -0
  32. data/public/javascript/ace/ace.js +1 -0
  33. data/public/javascript/ace/keybinding-emacs.js +1 -0
  34. data/public/javascript/ace/keybinding-vim.js +1 -0
  35. data/public/javascript/ace/mode-c_cpp.js +1 -0
  36. data/public/javascript/ace/mode-clojure.js +1 -0
  37. data/public/javascript/ace/mode-coffee.js +1 -0
  38. data/public/javascript/ace/mode-csharp.js +1 -0
  39. data/public/javascript/ace/mode-css.js +1 -0
  40. data/public/javascript/ace/mode-groovy.js +1 -0
  41. data/public/javascript/ace/mode-html.js +1 -0
  42. data/public/javascript/ace/mode-java.js +1 -0
  43. data/public/javascript/ace/mode-javascript.js +1 -0
  44. data/public/javascript/ace/mode-json.js +1 -0
  45. data/public/javascript/ace/mode-lua.js +1 -0
  46. data/public/javascript/ace/mode-markdown.js +1 -0
  47. data/public/javascript/ace/mode-ocaml.js +1 -0
  48. data/public/javascript/ace/mode-perl.js +1 -0
  49. data/public/javascript/ace/mode-php.js +1 -0
  50. data/public/javascript/ace/mode-python.js +1 -0
  51. data/public/javascript/ace/mode-ruby.js +1 -0
  52. data/public/javascript/ace/mode-scad.js +1 -0
  53. data/public/javascript/ace/mode-scala.js +1 -0
  54. data/public/javascript/ace/mode-scss.js +1 -0
  55. data/public/javascript/ace/mode-svg.js +1 -0
  56. data/public/javascript/ace/mode-textile.js +1 -0
  57. data/public/javascript/ace/mode-xml.js +1 -0
  58. data/public/javascript/ace/theme-clouds.js +1 -0
  59. data/public/javascript/ace/theme-clouds_midnight.js +1 -0
  60. data/public/javascript/ace/theme-cobalt.js +1 -0
  61. data/public/javascript/ace/theme-crimson_editor.js +1 -0
  62. data/public/javascript/ace/theme-dawn.js +1 -0
  63. data/public/javascript/ace/theme-eclipse.js +1 -0
  64. data/public/javascript/ace/theme-idle_fingers.js +1 -0
  65. data/public/javascript/ace/theme-kr_theme.js +1 -0
  66. data/public/javascript/ace/theme-merbivore.js +1 -0
  67. data/public/javascript/ace/theme-merbivore_soft.js +1 -0
  68. data/public/javascript/ace/theme-mono_industrial.js +1 -0
  69. data/public/javascript/ace/theme-monokai.js +1 -0
  70. data/public/javascript/ace/theme-pastel_on_dark.js +1 -0
  71. data/public/javascript/ace/theme-solarized_dark.js +1 -0
  72. data/public/javascript/ace/theme-solarized_light.js +1 -0
  73. data/public/javascript/ace/theme-textmate.js +1 -0
  74. data/public/javascript/ace/theme-twilight.js +1 -0
  75. data/public/javascript/ace/theme-vibrant_ink.js +1 -0
  76. data/public/javascript/ace/worker-coffee.js +1 -0
  77. data/public/javascript/ace/worker-css.js +1 -0
  78. data/public/javascript/ace/worker-javascript.js +1 -0
  79. data/public/javascript/webtools/#debugger.coffee# +253 -0
  80. data/public/javascript/webtools/browser.js +260 -0
  81. data/public/javascript/webtools/debugger.coffee +286 -0
  82. data/public/javascript/webtools/debugger.js +366 -0
  83. data/public/javascript/webtools/sessions.coffee +17 -0
  84. data/public/javascript/webtools/sessions.js +27 -0
  85. data/public/javascript/webtools/version.coffee +14 -0
  86. data/public/javascript/webtools/version.js +20 -0
  87. data/public/stylesheets/base/images/ui-anim_basic_16x16.gif +0 -0
  88. data/public/stylesheets/base/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  89. data/public/stylesheets/base/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  90. data/public/stylesheets/base/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  91. data/public/stylesheets/base/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  92. data/public/stylesheets/base/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  93. data/public/stylesheets/base/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  94. data/public/stylesheets/base/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  95. data/public/stylesheets/base/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  96. data/public/stylesheets/base/images/ui-icons_222222_256x240.png +0 -0
  97. data/public/stylesheets/base/images/ui-icons_2e83ff_256x240.png +0 -0
  98. data/public/stylesheets/base/images/ui-icons_454545_256x240.png +0 -0
  99. data/public/stylesheets/base/images/ui-icons_888888_256x240.png +0 -0
  100. data/public/stylesheets/base/images/ui-icons_cd0a0a_256x240.png +0 -0
  101. data/public/stylesheets/base/jquery.ui.accordion.css +12 -0
  102. data/public/stylesheets/base/jquery.ui.all.css +2 -0
  103. data/public/stylesheets/base/jquery.ui.autocomplete.css +39 -0
  104. data/public/stylesheets/base/jquery.ui.base.css +11 -0
  105. data/public/stylesheets/base/jquery.ui.button.css +35 -0
  106. data/public/stylesheets/base/jquery.ui.core.css +37 -0
  107. data/public/stylesheets/base/jquery.ui.datepicker.css +61 -0
  108. data/public/stylesheets/base/jquery.ui.dialog.css +13 -0
  109. data/public/stylesheets/base/jquery.ui.progressbar.css +4 -0
  110. data/public/stylesheets/base/jquery.ui.resizable.css +13 -0
  111. data/public/stylesheets/base/jquery.ui.selectable.css +3 -0
  112. data/public/stylesheets/base/jquery.ui.slider.css +17 -0
  113. data/public/stylesheets/base/jquery.ui.tabs.css +11 -0
  114. data/public/stylesheets/base/jquery.ui.theme.css +247 -0
  115. data/public/stylesheets/jquery.contextMenu.css +62 -0
  116. data/public/stylesheets/reset.css +18 -0
  117. data/public/stylesheets/webtools.css +53 -0
  118. data/public/test.html +47 -0
  119. data/views/browser.rhtml +63 -0
  120. data/views/debugger.rhtml +59 -0
  121. data/views/index.rhtml +8 -0
  122. data/views/layout.rhtml +24 -0
  123. data/views/sessions.rhtml +12 -0
  124. data/views/version.rhtml +10 -0
  125. metadata +316 -0
@@ -0,0 +1,253 @@
1
+ window.escapeHTML = (str) ->
2
+ str = "" unless str?
3
+ str += str unless typeof str == "string"
4
+ $("<i></i>").text(str).html()
5
+
6
+ class Frame
7
+ constructor: (@server, @pid, @frame_idx, @container) ->
8
+
9
+ update_detail_view: (objectInfo) ->
10
+ @inspector.hide()
11
+ @inspector.children('.objInfoClass').text(objectInfo['(__class__)'])
12
+ @inspector.children('.objInfoValue').text(objectInfo['(__inspect__)'])
13
+ this.renderTableData @inspector.children('.objInstVars'), objectInfo, (idx, data) ->
14
+ $("<tr><td>#{idx}</td><td>#{data}</td></tr>")
15
+ @inspector.show()
16
+
17
+ renderTableData: (instVarsTable, object, formatFn) ->
18
+ ui = instVarsTable.children('tbody')
19
+ ui.empty()
20
+ $.each object, (key, value) ->
21
+ if key.indexOf("@") == 0
22
+ ui.append(formatFn(key, value))
23
+
24
+ create_detail_view: ->
25
+ @inspector = $('#objectInspector').clone()
26
+ @inspector.removeAttr('id')
27
+ @inspector.removeClass('hidden')
28
+ @container.append(@inspector)
29
+
30
+ create_source_code_holder: () ->
31
+ @container.prepend($('#editor'))
32
+ $('#editor').show()
33
+
34
+ create_inspector: (object, index, path) ->
35
+ index = 0 unless index?
36
+ path = "#{@server}/process/#{@pid}/frames/#{@frame_idx}" unless path?
37
+ options = $([])
38
+ $.each object, (key, value) ->
39
+ if "#{key}".indexOf("@") == 0 || key == "(__self__)" || key == "(__class__)"
40
+ options.push("#{key}")
41
+ if not @inspector_div?
42
+ @inspector_div = $(document.createElement("div"))
43
+ @inspector_div.addClass("inspectors")
44
+ @container.prepend(@inspector_div)
45
+ if @inspectors[index]?
46
+ inspector = @inspectors[index]
47
+ else
48
+ @inspectors[index] = (inspector = $(document.createElement("select")))
49
+ @inspector_div.append(inspector)
50
+ inspector.attr
51
+ multiple: true
52
+ class: 'inspector'
53
+ inspector.html("")
54
+ $(options).each (idx, o) =>
55
+ inspector.append("<option value=#{idx}>#{escapeHTML(o)}</option>")
56
+ this.create_evaluator(path)
57
+ inspector.bind "change", =>
58
+ value = options[inspector.val()]
59
+ url = "#{path}/objects/#{value}"
60
+ for i in @inspectors.slice(index + 1)
61
+ i.html("")
62
+ $.get "#{url}/objects", (object) =>
63
+ this.create_inspector(object, index + 1, url)
64
+ this.update_detail_view(object)
65
+ , 'json'
66
+
67
+ create_evaluator: (path) ->
68
+ unless @evaluator?
69
+ @evaluator = $(document.createElement("input"))
70
+ @evaluator.attr
71
+ type: "text"
72
+ name: "#{@frame_idx}_evaluator"
73
+ id: "#{@frame_idx}_evaluator"
74
+ class: "ui-widget-content ui-corner-all"
75
+ @container.prepend(@evaluator)
76
+ @evaluator.unbind("keypress")
77
+ @evaluator.bind "keypress", (e) =>
78
+ code = e.keyCode if e.keyCode?
79
+ code = e.which unless code
80
+ if code == 13 # RETURN
81
+ $.ajax
82
+ url: path
83
+ data:
84
+ "do-it": @evaluator.val()
85
+ success: (data) =>
86
+ result = data["do-it-result"]
87
+ @evaluator.val("#{@evaluator.val()} => #{result['(__inspect__)']}")
88
+ this.update_detail_view(result)
89
+ @evaluator.select()
90
+ dataType: 'json'
91
+ type: 'PUT'
92
+
93
+ render: ->
94
+ @container.html("")
95
+ @inspectors = []
96
+ this.create_source_code_holder()
97
+ $.get "#{@server}/process/#{@pid}/frames/#{@frame_idx}", (frame) =>
98
+ editor.getSession().setValue(frame.debug_info.source)
99
+ editor.frame_url = "#{@server}/process/#{@pid}/frames/#{@frame_idx}"
100
+ this.create_inspector(frame.debug_info.context)
101
+ this.create_detail_view()
102
+ , 'json'
103
+
104
+ class Process
105
+ constructor: (@server, @pid, @tab) ->
106
+ @info_div = $("##{@tab} .info-bar")
107
+ @stack_div = $("##{@tab} .frame-list")
108
+
109
+ render: ->
110
+ this.render_info()
111
+ this.render_stack()
112
+
113
+ render_info: ->
114
+ request = $.get "#{@server}/process/#{@pid}", (data) =>
115
+ @info_div.text("#{data.label} (#{data.timestamp})")
116
+ , 'json'
117
+
118
+ render_stack: ->
119
+ @stack_div.html("")
120
+ request = $.get "#{@server}/process/#{@pid}/frames", (framelist) =>
121
+ $(framelist).each (idx, f) =>
122
+ header = $(document.createElement("h3"))
123
+ link = $(document.createElement("a"))
124
+ link.attr
125
+ href: '#'
126
+ data_idx: idx
127
+ link.text("#{f.class}##{f.method_name}")
128
+ link.append("<small>#{escapeHTML(f.source_location)}</small>")
129
+ header.append(link)
130
+ restartLink = $('<a href="#">Restart frame</a>')
131
+ restartLink.bind "click", (e) =>
132
+ $.ajax
133
+ url: "#{@server}/process/#{@pid}/frames/#{idx}",
134
+ type: 'DELETE'
135
+ success: =>
136
+
137
+ e.preventDefault()
138
+ header.append(restartLink)
139
+ div = document.createElement("div")
140
+ $(div).text("Waiting for data...")
141
+ @stack_div.append(header)
142
+ @stack_div.append(div)
143
+ if idx == 0
144
+ @selected_frame = new Frame(@server, @pid, 0, $(div))
145
+ @selected_frame.render()
146
+ @stack_div.accordion
147
+ clearStyle: true
148
+ collapsible: true
149
+ changestart: (event, ui) =>
150
+ frame_idx = ui.newHeader.children("a").attr("data_idx")
151
+ if frame_idx?
152
+ @selected_frame = new Frame(@server, @pid, frame_idx, ui.newContent)
153
+ @selected_frame.render()
154
+ , 'json'
155
+
156
+ class Debugger
157
+ constructor: (@server) ->
158
+ @tab_content_template = $("#tab_content_template")
159
+
160
+ toString: ->
161
+ "Debugger on #{server}"
162
+
163
+ server_alive: () ->
164
+ request = $.ajax
165
+ url: "#{@server}/process"
166
+ async: false
167
+ request.status == 200
168
+
169
+ clone_template: () ->
170
+ @content = @tab_content_template.clone()
171
+ @content.show()
172
+ @content.removeAttr("id")
173
+
174
+ fill_process_selector: () ->
175
+ @process_box = @content.children("select[name='process-select-box']")
176
+ $.getJSON "#{@server}/process", (errors) =>
177
+ $(errors).each (idx, e) =>
178
+ @process_box.append("<option value='#{e.process_id}'>#{e.process_id}: #{escapeHTML(e.label)}</option>")
179
+ @process_box.bind "change", =>
180
+ @process = new Process(@server, @process_box.val(), @tab)
181
+ @process.render()
182
+
183
+ content_for: (ui_panel) ->
184
+ if not @content?
185
+ @tab = $(ui_panel).attr("id")
186
+ return "<p>The URL " + url + " could not be reached</p>" unless this.server_alive()
187
+ this.clone_template()
188
+ this.fill_process_selector()
189
+ ui_panel.append(@content)
190
+ @content
191
+
192
+ DebuggerApp =
193
+ setup: ->
194
+ debuggers = []
195
+ tab_server_input = $("#tab_server")
196
+ tab_counter = 2
197
+
198
+ # actual addTab function: adds new tab using the title input
199
+ # from the form above
200
+ add_tab = ->
201
+ tab_server = tab_server_input.val()
202
+ tabs.tabs("add", "#tabs-#{tab_counter}", tab_server)
203
+ tab_counter++
204
+
205
+ # tabs init with a custom tab template and an "add" callback
206
+ # filling in the content
207
+ tabs = $("#tabs").tabs
208
+ tabTemplate: '<li><a href=\'#{href}\'>#{label}</a>' +
209
+ "<span class='ui-icon ui-icon-close'>Remove Tab</span></li>"
210
+ add: (event, ui) ->
211
+ new_debugger = new Debugger(tab_server_input.val())
212
+ debuggers.push(new_debugger)
213
+ new_debugger.content_for($(ui.panel))
214
+
215
+ # modal dialog init: custom buttons and a "close" callback
216
+ # reseting the form inside
217
+ dialog = $("#dialog").dialog
218
+ autoOpen: false
219
+ modal: true
220
+ buttons:
221
+ Add: ->
222
+ add_tab()
223
+ dialog.dialog("close")
224
+ Cancel: ->
225
+ dialog.dialog("close")
226
+ open: ->
227
+ tab_server_input.focus()
228
+ close: ->
229
+ form[0].reset()
230
+
231
+ # addTab form: calls addTab function on submit and closes the
232
+ # dialog
233
+ form = $("form", this.dialog).submit ->
234
+ add_tab()
235
+ dialog.dialog("close")
236
+ false
237
+
238
+ # addTab button: just opens the dialog
239
+ $("#add_tab").button().click ->
240
+ dialog.dialog("open");
241
+
242
+ # close icon: removing the tab on click
243
+ $("#tabs span.ui-icon-close").live "click", ->
244
+ index = $("li", tabs).index($(this).parent())
245
+ tabs.tabs("remove", index);
246
+
247
+ $(document).ready ->
248
+ DebuggerApp.setup()
249
+ window.RubyMode = require("ace/mode/ruby").Mode
250
+ window.canon = require('pilot/canon')
251
+ window.editor = ace.edit('editor')
252
+ window.editor.getSession().setUseSoftTabs(true)
253
+ window.editor.getSession().setMode(new RubyMode())
@@ -0,0 +1,260 @@
1
+ maglevInfo = (function() {
2
+ var requestCount = 0, rubyEditor = null;
3
+
4
+ $(document).ready(function() {
5
+ setupSelectables();
6
+ setupEditor();
7
+ setupToolBar();
8
+ updateCodeBrowser(); // Not sure this is the best way to kick it off...
9
+ });
10
+
11
+ function setupToolBar() {
12
+ $('#toolBar').append(
13
+ $('<div>').button({label: 'Refresh View'}
14
+ ).click(function () {
15
+ getJSON('/transaction/abort', null, function(data) {
16
+ clearRubyNav();
17
+ updateCodeBrowser();
18
+ });
19
+ }));
20
+ $('#toolBar').append($('<div>', { id: 'statusBar'}));
21
+ }
22
+
23
+ function clearRubyNav() {
24
+ $('ul.rubyList').empty();
25
+ clearDetailView();
26
+ }
27
+
28
+ function setupSelectables() {
29
+ $('#rubyModules').selectable({
30
+ selected: function(event, ui) { selectModule(ui.selected.title); }
31
+ });
32
+ $('#rubyConstants').selectable({
33
+ selected: function(event, ui) { selectConstant(ui.selected.title); }
34
+ });
35
+ $('#rubyModuleMethods').selectable({
36
+ selected: function(event, ui) { selectModuleMethod(ui.selected.title); }
37
+ });
38
+ $('#rubyInstanceMethods').selectable({
39
+ selected: function(event, ui) { selectInstanceMethod(ui.selected.title); }
40
+ });
41
+ }
42
+
43
+ function setupEditor() {
44
+ rubyEditor = CodeMirror.fromTextArea('rubyEditor',
45
+ { height: "100%",
46
+ parserfile: "parseSmalltalk.js",
47
+ stylesheet: "CodeMirror/css/Smalltalk.css",
48
+ path: "CodeMirror/js/",
49
+ lineNumbers: true});
50
+ }
51
+
52
+ function selectedModuleName() {
53
+ return $('#rubyModules .ui-selected').attr('title');
54
+ }
55
+
56
+ function selectedConstantName() {
57
+ return $('#rubyConstants .ui-selected').attr('title');
58
+ }
59
+
60
+ function selectedModuleMethodName() {
61
+ return $('#rubyModuleMethods .ui-selected').attr('title');
62
+ }
63
+
64
+ function selectedInstanceMethodName() {
65
+ return $('#rubyInstanceMethods .ui-selected').attr('title');
66
+ }
67
+
68
+ function selectModule(className) {
69
+ clearSelections(['#rubyModuleMethods', '#rubyModuleMethods',
70
+ '#rubyInstanceMethods', '#rubyAncestors']);
71
+ clearDetailView();
72
+ getJSON('/module/' + className, null, renderCodeBrowser);
73
+ }
74
+
75
+ function selectConstant(constName) {
76
+ clearSelections(['#rubyModuleMethods', '#rubyInstanceMethods']);
77
+ getJSON('/module/' + selectedModuleName() + '/constant/' + selectedConstantName(),
78
+ null,
79
+ function(data) {
80
+ clearEditArea();
81
+ renderObject(data['const_value']);
82
+ });
83
+ }
84
+
85
+ function selectModuleMethod(methodName) {
86
+ clearSelections(['#rubyConstants', '#rubyInstanceMethods']);
87
+ getJSON('/module/' + selectedModuleName() + '/method',
88
+ { 'method_name': selectedModuleMethodName(),
89
+ 'is_instance_method': false },
90
+ renderMethod);
91
+ }
92
+
93
+ function selectInstanceMethod(methodName) {
94
+ clearSelections(['#rubyConstants', '#rubyModuleMethods']);
95
+ getJSON('/module/' + selectedModuleName() + '/method',
96
+ { 'method_name': selectedInstanceMethodName(),
97
+ 'is_instance_method': true },
98
+ renderMethod);
99
+ }
100
+
101
+ function clearSelections(selections) {
102
+ console.log('clearSelections: ' + selections);
103
+ $.each(selections, function(i, el) {
104
+ $(el + ' .ui-selected').removeClass('ui-selected');
105
+ });
106
+ clearEditArea();
107
+ }
108
+
109
+ // Makes a JSON request, and decorates it with timing information.
110
+ // It then passes the bundled data object to the callback.
111
+ function getJSON(url, data, callback) {
112
+ var startTime = new Date().getTime();
113
+ var statusBar = $('#statusBar');
114
+ url = window.WebTools.location + url
115
+ $(statusBar).text('Sent request #' + (++requestCount) + ' for ' + url);
116
+ $.getJSON(url, data, success);
117
+ return;
118
+
119
+ function success(data) {
120
+ debugMsg('getJSON Success');
121
+ debugMsg(data);
122
+
123
+ var serverTime = data['_time'];
124
+ var networkTime = new Date().getTime() - startTime - serverTime;
125
+ startTime = new Date().getTime();
126
+ var error = data['_error'];
127
+ if (error) {
128
+ alert(error + ' (see console log for stack)');
129
+ debugMsg(data['_stack']);
130
+ } else {
131
+ (callback)(data);
132
+ };
133
+ var elapsed = new Date().getTime() - startTime;
134
+ $(statusBar).text(
135
+ 'Request for ' + url + ' (roundtrip #' + requestCount + ') took ' +
136
+ serverTime + ' ms on server, ' + networkTime + ' ms on the network, and '
137
+ + elapsed + ' ms on the client.'
138
+ );
139
+ }
140
+ }
141
+
142
+ function updateCodeBrowser() {
143
+ getJSON('/modulelist', null, renderCodeBrowser);
144
+ }
145
+
146
+ function renderCodeBrowser(data) {
147
+ renderList(data['modules'], $('#rubyModules'));
148
+ renderList(data['constants'], $('#rubyConstants'));
149
+ renderList(data['module_methods'], $('#rubyModuleMethods'));
150
+ renderList(data['instance_methods'], $('#rubyInstanceMethods'));
151
+ renderList(data['ancestors'], $('#rubyAncestors'));
152
+ return;
153
+
154
+ function renderList(items, ui) {
155
+ if (items) {
156
+ ui.empty();
157
+ $.each(items, function(n, item) {
158
+ $('<li>', { title: item, 'class': 'ui-widget-content' }).html(item).appendTo(ui);
159
+ });
160
+ }
161
+ }
162
+ }
163
+
164
+ function setDetailViewCode(sym) {
165
+ console.log('setDetailViewCode()');
166
+ $('#objectInspector').addClass('hidden');
167
+ $('#rubyEditArea').removeClass('hidden');
168
+ }
169
+
170
+ function setDetailViewObject(sym) {
171
+ $('#rubyEditArea').addClass('hidden');
172
+ $('#objectInspector').removeClass('hidden');
173
+ }
174
+
175
+ function clearDetailView() {
176
+ $('#rubyEditArea').addClass('hidden');
177
+ $('#objectInspector').addClass('hidden');
178
+ }
179
+
180
+ function clearEditArea() {
181
+ if (rubyEditor.editor) {
182
+ rubyEditor.setCode('');
183
+ }
184
+ $('#fileInfo').empty();
185
+ }
186
+
187
+ function renderMethod(data) {
188
+ clearEditArea();
189
+ renderSource(data['method_source']);
190
+ var file = data['method_source_file'];
191
+
192
+ if (file) {
193
+ $('#fileInfo').html(file + ':' + data['method_line_number']);
194
+ } else {
195
+ $('#fileInfo').html('No file information available');
196
+ }
197
+ }
198
+
199
+ // Make the rubyEditor visible in the detail area and render the source
200
+ // code. High level api.
201
+ function renderSource(string) {
202
+ if (rubyEditor.editor) {
203
+ rubyEditor.setCode(string);
204
+ setDetailViewCode();
205
+ }
206
+ }
207
+
208
+ // Make the objectInspector visible in the detail area and render the
209
+ // Object. High level api.
210
+ function renderObject(objectInfo) {
211
+ console.log('renderObject()');
212
+ console.log(objectInfo);
213
+ setDetailViewObject();
214
+
215
+ $('#objInfoClass').text(objectInfo['class']);
216
+ $('#objInfoId').text(objectInfo['object_id']);
217
+ $('#objInfoValue').text(objectInfo['inspect']);
218
+
219
+ renderTableData('#objInstVars',
220
+ objectInfo['instance_variables'],
221
+ // Data is an array of [name, value, objid]
222
+ function(idx, data) {
223
+ return $('<tr><td>'+ data[0] + '</td><td objectId="'
224
+ + escapeHTML(data[2]) + '">' + data[1] + '</td></tr>');
225
+ });
226
+
227
+ renderTableData('#objEnumValues',
228
+ objectInfo['enumerated'],
229
+ function(idx, data) {
230
+ return $('<tr><td>' + idx + '</td><td>' + escapeHTML(data) + '</td></tr>');
231
+ });
232
+ return;
233
+
234
+ function escapeHTML(text) {
235
+ return $('<div>').text(text).html();
236
+ }
237
+
238
+ function renderTableData(tableId, vals, formatFn) {
239
+ console.log('renderTableData: tableId: '+ tableId + ' # vals: ' + vals.length);
240
+ if (vals && vals.length > 0) {
241
+ $(tableId).removeClass('hidden');
242
+ var ui = $(tableId + ' tbody');
243
+ ui.empty();
244
+ $.each(vals, function(idx, data) { ui.append(formatFn(idx, data)) });
245
+ $(tableId).removeClass('hidden');
246
+ } else {
247
+ $(tableId).addClass('hidden');
248
+ }
249
+ }
250
+ }
251
+
252
+ // Some older browsers were complaining that console wasn't defined.
253
+ // (old firefox on solaris), so I'm wrapping console logging in this
254
+ // function.
255
+ function debugMsg(obj) {
256
+ if (console) {
257
+ console.log(obj);
258
+ }
259
+ }
260
+ })();