maglev-webtools 0.2.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.
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
+ })();