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,34 @@
1
+ html {
2
+ cursor: text;
3
+ }
4
+
5
+ .editbox {
6
+ margin: .4em;
7
+ padding: 0;
8
+ font-family: monospace;
9
+ font-size: 10pt;
10
+ color: black;
11
+ }
12
+
13
+ .editbox p {
14
+ margin: 0;
15
+ }
16
+
17
+ span.st-character { color: rgb(128,0,128); }
18
+ span.st-comment { color: rgb(0,200,0); font-style: italic; }
19
+ span.st-string { color: rgb(128,0,128); }
20
+ span.st-symbol { color: rgb(128,0,128); }
21
+ span.st-boolean { color: rgb(0,0,128); }
22
+ span.st-self { color: rgb(0,0,128); }
23
+ span.st-super { color: rgb(0,0,128); }
24
+ span.st-nil { color: rgb(0,0,128); }
25
+ span.st-return { color: rgb(160,0,0); }
26
+ span.st-keyword { color: rgb(0,0,255); }
27
+ span.st-global { font-weight: bold; }
28
+
29
+ /*
30
+ number: 0 127 127
31
+ special selector: 0 0 127
32
+ brace highlight: 255 128 0
33
+ brace mismatch: 255 0 0
34
+ */
@@ -0,0 +1,582 @@
1
+ /* CodeMirror main module (http://codemirror.net/)
2
+ *
3
+ * Implements the CodeMirror constructor and prototype, which take care
4
+ * of initializing the editor frame, and providing the outside interface.
5
+ */
6
+
7
+ // The CodeMirrorConfig object is used to specify a default
8
+ // configuration. If you specify such an object before loading this
9
+ // file, the values you put into it will override the defaults given
10
+ // below. You can also assign to it after loading.
11
+ var CodeMirrorConfig = window.CodeMirrorConfig || {};
12
+
13
+ var CodeMirror = (function(){
14
+ function setDefaults(object, defaults) {
15
+ for (var option in defaults) {
16
+ if (!object.hasOwnProperty(option))
17
+ object[option] = defaults[option];
18
+ }
19
+ }
20
+ function forEach(array, action) {
21
+ for (var i = 0; i < array.length; i++)
22
+ action(array[i]);
23
+ }
24
+ function createHTMLElement(el) {
25
+ if (document.createElementNS && document.documentElement.namespaceURI !== null)
26
+ return document.createElementNS("http://www.w3.org/1999/xhtml", el)
27
+ else
28
+ return document.createElement(el)
29
+ }
30
+
31
+ // These default options can be overridden by passing a set of
32
+ // options to a specific CodeMirror constructor. See manual.html for
33
+ // their meaning.
34
+ setDefaults(CodeMirrorConfig, {
35
+ stylesheet: [],
36
+ path: "",
37
+ parserfile: [],
38
+ basefiles: ["util.js", "stringstream.js", "select.js", "undo.js", "editor.js", "tokenize.js"],
39
+ iframeClass: null,
40
+ passDelay: 200,
41
+ passTime: 50,
42
+ lineNumberDelay: 200,
43
+ lineNumberTime: 50,
44
+ continuousScanning: false,
45
+ saveFunction: null,
46
+ onLoad: null,
47
+ onChange: null,
48
+ undoDepth: 50,
49
+ undoDelay: 800,
50
+ disableSpellcheck: true,
51
+ textWrapping: true,
52
+ readOnly: false,
53
+ width: "",
54
+ height: "300px",
55
+ minHeight: 100,
56
+ autoMatchParens: false,
57
+ markParen: null,
58
+ unmarkParen: null,
59
+ parserConfig: null,
60
+ tabMode: "indent", // or "spaces", "default", "shift"
61
+ enterMode: "indent", // or "keep", "flat"
62
+ electricChars: true,
63
+ reindentOnLoad: false,
64
+ activeTokens: null,
65
+ onCursorActivity: null,
66
+ lineNumbers: false,
67
+ firstLineNumber: 1,
68
+ onLineNumberClick: null,
69
+ indentUnit: 2,
70
+ domain: null,
71
+ noScriptCaching: false,
72
+ incrementalLoading: false
73
+ });
74
+
75
+ function addLineNumberDiv(container, firstNum) {
76
+ var nums = createHTMLElement("div"),
77
+ scroller = createHTMLElement("div");
78
+ nums.style.position = "absolute";
79
+ nums.style.height = "100%";
80
+ if (nums.style.setExpression) {
81
+ try {nums.style.setExpression("height", "this.previousSibling.offsetHeight + 'px'");}
82
+ catch(e) {} // Seems to throw 'Not Implemented' on some IE8 versions
83
+ }
84
+ nums.style.top = "0px";
85
+ nums.style.left = "0px";
86
+ nums.style.overflow = "hidden";
87
+ container.appendChild(nums);
88
+ scroller.className = "CodeMirror-line-numbers";
89
+ nums.appendChild(scroller);
90
+ scroller.innerHTML = "<div>" + firstNum + "</div>";
91
+ return nums;
92
+ }
93
+
94
+ function frameHTML(options) {
95
+ if (typeof options.parserfile == "string")
96
+ options.parserfile = [options.parserfile];
97
+ if (typeof options.basefiles == "string")
98
+ options.basefiles = [options.basefiles];
99
+ if (typeof options.stylesheet == "string")
100
+ options.stylesheet = [options.stylesheet];
101
+
102
+ var sp = " spellcheck=\"" + (options.disableSpellcheck ? "false" : "true") + "\"";
103
+ var html = ["<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\"><html" + sp + "><head>"];
104
+ // Hack to work around a bunch of IE8-specific problems.
105
+ html.push("<meta http-equiv=\"X-UA-Compatible\" content=\"IE=EmulateIE7\"/>");
106
+ var queryStr = options.noScriptCaching ? "?nocache=" + new Date().getTime().toString(16) : "";
107
+ forEach(options.stylesheet, function(file) {
108
+ html.push("<link rel=\"stylesheet\" type=\"text/css\" href=\"" + file + queryStr + "\"/>");
109
+ });
110
+ forEach(options.basefiles.concat(options.parserfile), function(file) {
111
+ if (!/^https?:/.test(file)) file = options.path + file;
112
+ html.push("<script type=\"text/javascript\" src=\"" + file + queryStr + "\"><" + "/script>");
113
+ });
114
+ html.push("</head><body style=\"border-width: 0;\" class=\"editbox\"" + sp + "></body></html>");
115
+ return html.join("");
116
+ }
117
+
118
+ var internetExplorer = document.selection && window.ActiveXObject && /MSIE/.test(navigator.userAgent);
119
+
120
+ function CodeMirror(place, options) {
121
+ // Use passed options, if any, to override defaults.
122
+ this.options = options = options || {};
123
+ setDefaults(options, CodeMirrorConfig);
124
+
125
+ // Backward compatibility for deprecated options.
126
+ if (options.dumbTabs) options.tabMode = "spaces";
127
+ else if (options.normalTab) options.tabMode = "default";
128
+ if (options.cursorActivity) options.onCursorActivity = options.cursorActivity;
129
+
130
+ var frame = this.frame = createHTMLElement("iframe");
131
+ if (options.iframeClass) frame.className = options.iframeClass;
132
+ frame.frameBorder = 0;
133
+ frame.style.border = "0";
134
+ frame.style.width = '100%';
135
+ frame.style.height = '100%';
136
+ // display: block occasionally suppresses some Firefox bugs, so we
137
+ // always add it, redundant as it sounds.
138
+ frame.style.display = "block";
139
+
140
+ var div = this.wrapping = createHTMLElement("div");
141
+ div.style.position = "relative";
142
+ div.className = "CodeMirror-wrapping";
143
+ div.style.width = options.width;
144
+ div.style.height = (options.height == "dynamic") ? options.minHeight + "px" : options.height;
145
+ // This is used by Editor.reroutePasteEvent
146
+ var teHack = this.textareaHack = createHTMLElement("textarea");
147
+ div.appendChild(teHack);
148
+ teHack.style.position = "absolute";
149
+ teHack.style.left = "-10000px";
150
+ teHack.style.width = "10px";
151
+ teHack.tabIndex = 100000;
152
+
153
+ // Link back to this object, so that the editor can fetch options
154
+ // and add a reference to itself.
155
+ frame.CodeMirror = this;
156
+ if (options.domain && internetExplorer) {
157
+ this.html = frameHTML(options);
158
+ frame.src = "javascript:(function(){document.open();" +
159
+ (options.domain ? "document.domain=\"" + options.domain + "\";" : "") +
160
+ "document.write(window.frameElement.CodeMirror.html);document.close();})()";
161
+ }
162
+ else {
163
+ frame.src = "javascript:;";
164
+ }
165
+
166
+ if (place.appendChild) place.appendChild(div);
167
+ else place(div);
168
+ div.appendChild(frame);
169
+ if (options.lineNumbers) this.lineNumbers = addLineNumberDiv(div, options.firstLineNumber);
170
+
171
+ this.win = frame.contentWindow;
172
+ if (!options.domain || !internetExplorer) {
173
+ this.win.document.open();
174
+ this.win.document.write(frameHTML(options));
175
+ this.win.document.close();
176
+ }
177
+ }
178
+
179
+ CodeMirror.prototype = {
180
+ init: function() {
181
+ // Deprecated, but still supported.
182
+ if (this.options.initCallback) this.options.initCallback(this);
183
+ if (this.options.onLoad) this.options.onLoad(this);
184
+ if (this.options.lineNumbers) this.activateLineNumbers();
185
+ if (this.options.reindentOnLoad) this.reindent();
186
+ if (this.options.height == "dynamic") this.setDynamicHeight();
187
+ },
188
+
189
+ getCode: function() {return this.editor.getCode();},
190
+ setCode: function(code) {this.editor.importCode(code);},
191
+ selection: function() {this.focusIfIE(); return this.editor.selectedText();},
192
+ reindent: function() {this.editor.reindent();},
193
+ reindentSelection: function() {this.focusIfIE(); this.editor.reindentSelection(null);},
194
+
195
+ focusIfIE: function() {
196
+ // in IE, a lot of selection-related functionality only works when the frame is focused
197
+ if (this.win.select.ie_selection && document.activeElement != this.frame)
198
+ this.focus();
199
+ },
200
+ focus: function() {
201
+ this.win.focus();
202
+ if (this.editor.selectionSnapshot) // IE hack
203
+ this.win.select.setBookmark(this.win.document.body, this.editor.selectionSnapshot);
204
+ },
205
+ replaceSelection: function(text) {
206
+ this.focus();
207
+ this.editor.replaceSelection(text);
208
+ return true;
209
+ },
210
+ replaceChars: function(text, start, end) {
211
+ this.editor.replaceChars(text, start, end);
212
+ },
213
+ getSearchCursor: function(string, fromCursor, caseFold) {
214
+ return this.editor.getSearchCursor(string, fromCursor, caseFold);
215
+ },
216
+
217
+ undo: function() {this.editor.history.undo();},
218
+ redo: function() {this.editor.history.redo();},
219
+ historySize: function() {return this.editor.history.historySize();},
220
+ clearHistory: function() {this.editor.history.clear();},
221
+
222
+ grabKeys: function(callback, filter) {this.editor.grabKeys(callback, filter);},
223
+ ungrabKeys: function() {this.editor.ungrabKeys();},
224
+
225
+ setParser: function(name, parserConfig) {this.editor.setParser(name, parserConfig);},
226
+ setSpellcheck: function(on) {this.win.document.body.spellcheck = on;},
227
+ setStylesheet: function(names) {
228
+ if (typeof names === "string") names = [names];
229
+ var activeStylesheets = {};
230
+ var matchedNames = {};
231
+ var links = this.win.document.getElementsByTagName("link");
232
+ // Create hashes of active stylesheets and matched names.
233
+ // This is O(n^2) but n is expected to be very small.
234
+ for (var x = 0, link; link = links[x]; x++) {
235
+ if (link.rel.indexOf("stylesheet") !== -1) {
236
+ for (var y = 0; y < names.length; y++) {
237
+ var name = names[y];
238
+ if (link.href.substring(link.href.length - name.length) === name) {
239
+ activeStylesheets[link.href] = true;
240
+ matchedNames[name] = true;
241
+ }
242
+ }
243
+ }
244
+ }
245
+ // Activate the selected stylesheets and disable the rest.
246
+ for (var x = 0, link; link = links[x]; x++) {
247
+ if (link.rel.indexOf("stylesheet") !== -1) {
248
+ link.disabled = !(link.href in activeStylesheets);
249
+ }
250
+ }
251
+ // Create any new stylesheets.
252
+ for (var y = 0; y < names.length; y++) {
253
+ var name = names[y];
254
+ if (!(name in matchedNames)) {
255
+ var link = this.win.document.createElement("link");
256
+ link.rel = "stylesheet";
257
+ link.type = "text/css";
258
+ link.href = name;
259
+ this.win.document.getElementsByTagName('head')[0].appendChild(link);
260
+ }
261
+ }
262
+ },
263
+ setTextWrapping: function(on) {
264
+ if (on == this.options.textWrapping) return;
265
+ this.win.document.body.style.whiteSpace = on ? "" : "nowrap";
266
+ this.options.textWrapping = on;
267
+ if (this.lineNumbers) {
268
+ this.setLineNumbers(false);
269
+ this.setLineNumbers(true);
270
+ }
271
+ },
272
+ setIndentUnit: function(unit) {this.win.indentUnit = unit;},
273
+ setUndoDepth: function(depth) {this.editor.history.maxDepth = depth;},
274
+ setTabMode: function(mode) {this.options.tabMode = mode;},
275
+ setEnterMode: function(mode) {this.options.enterMode = mode;},
276
+ setLineNumbers: function(on) {
277
+ if (on && !this.lineNumbers) {
278
+ this.lineNumbers = addLineNumberDiv(this.wrapping,this.options.firstLineNumber);
279
+ this.activateLineNumbers();
280
+ }
281
+ else if (!on && this.lineNumbers) {
282
+ this.wrapping.removeChild(this.lineNumbers);
283
+ this.wrapping.style.paddingLeft = "";
284
+ this.lineNumbers = null;
285
+ }
286
+ },
287
+
288
+ cursorPosition: function(start) {this.focusIfIE(); return this.editor.cursorPosition(start);},
289
+ firstLine: function() {return this.editor.firstLine();},
290
+ lastLine: function() {return this.editor.lastLine();},
291
+ nextLine: function(line) {return this.editor.nextLine(line);},
292
+ prevLine: function(line) {return this.editor.prevLine(line);},
293
+ lineContent: function(line) {return this.editor.lineContent(line);},
294
+ setLineContent: function(line, content) {this.editor.setLineContent(line, content);},
295
+ removeLine: function(line){this.editor.removeLine(line);},
296
+ insertIntoLine: function(line, position, content) {this.editor.insertIntoLine(line, position, content);},
297
+ selectLines: function(startLine, startOffset, endLine, endOffset) {
298
+ this.win.focus();
299
+ this.editor.selectLines(startLine, startOffset, endLine, endOffset);
300
+ },
301
+ nthLine: function(n) {
302
+ var line = this.firstLine();
303
+ for (; n > 1 && line !== false; n--)
304
+ line = this.nextLine(line);
305
+ return line;
306
+ },
307
+ lineNumber: function(line) {
308
+ var num = 0;
309
+ while (line !== false) {
310
+ num++;
311
+ line = this.prevLine(line);
312
+ }
313
+ return num;
314
+ },
315
+ jumpToLine: function(line) {
316
+ if (typeof line == "number") line = this.nthLine(line);
317
+ this.selectLines(line, 0);
318
+ this.win.focus();
319
+ },
320
+ currentLine: function() { // Deprecated, but still there for backward compatibility
321
+ return this.lineNumber(this.cursorLine());
322
+ },
323
+ cursorLine: function() {
324
+ return this.cursorPosition().line;
325
+ },
326
+ cursorCoords: function(start) {return this.editor.cursorCoords(start);},
327
+
328
+ activateLineNumbers: function() {
329
+ var frame = this.frame, win = frame.contentWindow, doc = win.document, body = doc.body,
330
+ nums = this.lineNumbers, scroller = nums.firstChild, self = this;
331
+ var barWidth = null;
332
+
333
+ nums.onclick = function(e) {
334
+ var handler = self.options.onLineNumberClick;
335
+ if (handler) {
336
+ var div = (e || window.event).target || (e || window.event).srcElement;
337
+ var num = div == nums ? NaN : Number(div.innerHTML);
338
+ if (!isNaN(num)) handler(num, div);
339
+ }
340
+ };
341
+
342
+ function sizeBar() {
343
+ if (frame.offsetWidth == 0) return;
344
+ for (var root = frame; root.parentNode; root = root.parentNode){}
345
+ if (!nums.parentNode || root != document || !win.Editor) {
346
+ // Clear event handlers (their nodes might already be collected, so try/catch)
347
+ try{clear();}catch(e){}
348
+ clearInterval(sizeInterval);
349
+ return;
350
+ }
351
+
352
+ if (nums.offsetWidth != barWidth) {
353
+ barWidth = nums.offsetWidth;
354
+ frame.parentNode.style.paddingLeft = barWidth + "px";
355
+ }
356
+ }
357
+ function doScroll() {
358
+ nums.scrollTop = body.scrollTop || doc.documentElement.scrollTop || 0;
359
+ }
360
+ // Cleanup function, registered by nonWrapping and wrapping.
361
+ var clear = function(){};
362
+ sizeBar();
363
+ var sizeInterval = setInterval(sizeBar, 500);
364
+
365
+ function ensureEnoughLineNumbers(fill) {
366
+ var lineHeight = scroller.firstChild.offsetHeight;
367
+ if (lineHeight == 0) return;
368
+ var targetHeight = 50 + Math.max(body.offsetHeight, Math.max(frame.offsetHeight, body.scrollHeight || 0)),
369
+ lastNumber = Math.ceil(targetHeight / lineHeight);
370
+ for (var i = scroller.childNodes.length; i <= lastNumber; i++) {
371
+ var div = createHTMLElement("div");
372
+ div.appendChild(document.createTextNode(fill ? String(i + self.options.firstLineNumber) : "\u00a0"));
373
+ scroller.appendChild(div);
374
+ }
375
+ }
376
+
377
+ function nonWrapping() {
378
+ function update() {
379
+ ensureEnoughLineNumbers(true);
380
+ doScroll();
381
+ }
382
+ self.updateNumbers = update;
383
+ var onScroll = win.addEventHandler(win, "scroll", doScroll, true),
384
+ onResize = win.addEventHandler(win, "resize", update, true);
385
+ clear = function(){
386
+ onScroll(); onResize();
387
+ if (self.updateNumbers == update) self.updateNumbers = null;
388
+ };
389
+ update();
390
+ }
391
+
392
+ function wrapping() {
393
+ var node, lineNum, next, pos, changes = [], styleNums = self.options.styleNumbers;
394
+
395
+ function setNum(n, node) {
396
+ // Does not typically happen (but can, if you mess with the
397
+ // document during the numbering)
398
+ if (!lineNum) lineNum = scroller.appendChild(createHTMLElement("div"));
399
+ if (styleNums) styleNums(lineNum, node, n);
400
+ // Changes are accumulated, so that the document layout
401
+ // doesn't have to be recomputed during the pass
402
+ changes.push(lineNum); changes.push(n);
403
+ pos = lineNum.offsetHeight + lineNum.offsetTop;
404
+ lineNum = lineNum.nextSibling;
405
+ }
406
+ function commitChanges() {
407
+ for (var i = 0; i < changes.length; i += 2)
408
+ changes[i].innerHTML = changes[i + 1];
409
+ changes = [];
410
+ }
411
+ function work() {
412
+ if (!scroller.parentNode || scroller.parentNode != self.lineNumbers) return;
413
+
414
+ var endTime = new Date().getTime() + self.options.lineNumberTime;
415
+ while (node) {
416
+ setNum(next++, node.previousSibling);
417
+ for (; node && !win.isBR(node); node = node.nextSibling) {
418
+ var bott = node.offsetTop + node.offsetHeight;
419
+ while (scroller.offsetHeight && bott - 3 > pos) {
420
+ var oldPos = pos;
421
+ setNum("&nbsp;");
422
+ if (pos <= oldPos) break;
423
+ }
424
+ }
425
+ if (node) node = node.nextSibling;
426
+ if (new Date().getTime() > endTime) {
427
+ commitChanges();
428
+ pending = setTimeout(work, self.options.lineNumberDelay);
429
+ return;
430
+ }
431
+ }
432
+ while (lineNum) setNum(next++);
433
+ commitChanges();
434
+ doScroll();
435
+ }
436
+ function start(firstTime) {
437
+ doScroll();
438
+ ensureEnoughLineNumbers(firstTime);
439
+ node = body.firstChild;
440
+ lineNum = scroller.firstChild;
441
+ pos = 0;
442
+ next = self.options.firstLineNumber;
443
+ work();
444
+ }
445
+
446
+ start(true);
447
+ var pending = null;
448
+ function update() {
449
+ if (pending) clearTimeout(pending);
450
+ if (self.editor.allClean()) start();
451
+ else pending = setTimeout(update, 200);
452
+ }
453
+ self.updateNumbers = update;
454
+ var onScroll = win.addEventHandler(win, "scroll", doScroll, true),
455
+ onResize = win.addEventHandler(win, "resize", update, true);
456
+ clear = function(){
457
+ if (pending) clearTimeout(pending);
458
+ if (self.updateNumbers == update) self.updateNumbers = null;
459
+ onScroll();
460
+ onResize();
461
+ };
462
+ }
463
+ (this.options.textWrapping || this.options.styleNumbers ? wrapping : nonWrapping)();
464
+ },
465
+
466
+ setDynamicHeight: function() {
467
+ var self = this, activity = self.options.onCursorActivity, win = self.win, body = win.document.body,
468
+ lineHeight = null, timeout = null, vmargin = 2 * self.frame.offsetTop;
469
+ body.style.overflowY = "hidden";
470
+ win.document.documentElement.style.overflowY = "hidden";
471
+ this.frame.scrolling = "no";
472
+
473
+ function updateHeight() {
474
+ var trailingLines = 0, node = body.lastChild, computedHeight;
475
+ while (node && win.isBR(node)) {
476
+ if (!node.hackBR) trailingLines++;
477
+ node = node.previousSibling;
478
+ }
479
+ if (node) {
480
+ lineHeight = node.offsetHeight;
481
+ computedHeight = node.offsetTop + (1 + trailingLines) * lineHeight;
482
+ }
483
+ else if (lineHeight) {
484
+ computedHeight = trailingLines * lineHeight;
485
+ }
486
+ if (computedHeight)
487
+ self.wrapping.style.height = Math.max(vmargin + computedHeight, self.options.minHeight) + "px";
488
+ }
489
+ setTimeout(updateHeight, 300);
490
+ self.options.onCursorActivity = function(x) {
491
+ if (activity) activity(x);
492
+ clearTimeout(timeout);
493
+ timeout = setTimeout(updateHeight, 100);
494
+ };
495
+ }
496
+ };
497
+
498
+ CodeMirror.InvalidLineHandle = {toString: function(){return "CodeMirror.InvalidLineHandle";}};
499
+
500
+ CodeMirror.replace = function(element) {
501
+ if (typeof element == "string")
502
+ element = document.getElementById(element);
503
+ return function(newElement) {
504
+ element.parentNode.replaceChild(newElement, element);
505
+ };
506
+ };
507
+
508
+ CodeMirror.fromTextArea = function(area, options) {
509
+ if (typeof area == "string")
510
+ area = document.getElementById(area);
511
+
512
+ options = options || {};
513
+ if (area.style.width && options.width == null)
514
+ options.width = area.style.width;
515
+ if (area.style.height && options.height == null)
516
+ options.height = area.style.height;
517
+ if (options.content == null) options.content = area.value;
518
+
519
+ function updateField() {
520
+ area.value = mirror.getCode();
521
+ }
522
+ if (area.form) {
523
+ if (typeof area.form.addEventListener == "function")
524
+ area.form.addEventListener("submit", updateField, false);
525
+ else
526
+ area.form.attachEvent("onsubmit", updateField);
527
+ var realSubmit = area.form.submit;
528
+ function wrapSubmit() {
529
+ updateField();
530
+ // Can't use realSubmit.apply because IE6 is too stupid
531
+ area.form.submit = realSubmit;
532
+ area.form.submit();
533
+ area.form.submit = wrapSubmit;
534
+ }
535
+ try {area.form.submit = wrapSubmit;} catch(e){}
536
+ }
537
+
538
+ function insert(frame) {
539
+ if (area.nextSibling)
540
+ area.parentNode.insertBefore(frame, area.nextSibling);
541
+ else
542
+ area.parentNode.appendChild(frame);
543
+ }
544
+
545
+ area.style.display = "none";
546
+ var mirror = new CodeMirror(insert, options);
547
+ mirror.save = updateField;
548
+ mirror.toTextArea = function() {
549
+ updateField();
550
+ area.parentNode.removeChild(mirror.wrapping);
551
+ area.style.display = "";
552
+ if (area.form) {
553
+ try {area.form.submit = realSubmit;} catch(e) {}
554
+ if (typeof area.form.removeEventListener == "function")
555
+ area.form.removeEventListener("submit", updateField, false);
556
+ else
557
+ area.form.detachEvent("onsubmit", updateField);
558
+ }
559
+ };
560
+
561
+ return mirror;
562
+ };
563
+
564
+ CodeMirror.isProbablySupported = function() {
565
+ // This is rather awful, but can be useful.
566
+ var match;
567
+ if (window.opera)
568
+ return Number(window.opera.version()) >= 9.52;
569
+ else if (/Apple Computer, Inc/.test(navigator.vendor) && (match = navigator.userAgent.match(/Version\/(\d+(?:\.\d+)?)\./)))
570
+ return Number(match[1]) >= 3;
571
+ else if (document.selection && window.ActiveXObject && (match = navigator.userAgent.match(/MSIE (\d+(?:\.\d*)?)\b/)))
572
+ return Number(match[1]) >= 6;
573
+ else if (match = navigator.userAgent.match(/gecko\/(\d{8})/i))
574
+ return Number(match[1]) >= 20050901;
575
+ else if (match = navigator.userAgent.match(/AppleWebKit\/(\d+)/))
576
+ return Number(match[1]) >= 525;
577
+ else
578
+ return null;
579
+ };
580
+
581
+ return CodeMirror;
582
+ })();