liquid_cms 0.3.0.1 → 0.3.0.2

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 (49) hide show
  1. data/CHANGELOG.rdoc +5 -1
  2. data/Gemfile.lock +1 -1
  3. data/README.rdoc +5 -1
  4. data/app/helpers/cms/common_helper.rb +1 -0
  5. data/app/views/cms/pages/_page.html.erb +2 -1
  6. data/app/views/layouts/cms.html.erb +2 -1
  7. data/lib/generators/liquid_cms/templates/public/cms/codemirror/LICENSE +2 -2
  8. data/lib/generators/liquid_cms/templates/public/cms/codemirror/css/csscolors.css +12 -8
  9. data/lib/generators/liquid_cms/templates/public/cms/codemirror/css/docs.css +123 -29
  10. data/lib/generators/liquid_cms/templates/public/cms/codemirror/csstest.html +1 -1
  11. data/lib/generators/liquid_cms/templates/public/cms/codemirror/htmltest.html +1 -1
  12. data/lib/generators/liquid_cms/templates/public/cms/codemirror/index.html +232 -179
  13. data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/codemirror.js +211 -65
  14. data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/editor.js +360 -194
  15. data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/mirrorframe.js +1 -1
  16. data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/parsecss.js +11 -7
  17. data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/parsejavascript.js +14 -5
  18. data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/parsesparql.js +1 -1
  19. data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/select.js +140 -87
  20. data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/stringstream.js +5 -0
  21. data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/tokenizejavascript.js +1 -1
  22. data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/undo.js +7 -7
  23. data/lib/generators/liquid_cms/templates/public/cms/codemirror/manual.html +148 -52
  24. data/lib/generators/liquid_cms/templates/public/cms/codemirror/story.html +631 -614
  25. data/lib/generators/liquid_cms/templates/public/cms/stylesheets/styles.css +7 -7
  26. data/lib/liquid_cms/version.rb +1 -1
  27. metadata +4 -26
  28. data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/lua/LICENSE +0 -32
  29. data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/lua/css/luacolors.css +0 -63
  30. data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/lua/index.html +0 -68
  31. data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/lua/js/parselua.js +0 -253
  32. data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/php/LICENSE +0 -37
  33. data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/php/css/phpcolors.css +0 -114
  34. data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/php/index.html +0 -292
  35. data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/php/js/parsephp.js +0 -371
  36. data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/php/js/parsephphtmlmixed.js +0 -90
  37. data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/php/js/tokenizephp.js +0 -1006
  38. data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/plsql/LICENSE +0 -22
  39. data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/plsql/css/plsqlcolors.css +0 -57
  40. data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/plsql/index.html +0 -67
  41. data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/plsql/js/parseplsql.js +0 -233
  42. data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/python/LICENSE +0 -32
  43. data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/python/css/pythoncolors.css +0 -58
  44. data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/python/index.html +0 -141
  45. data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/python/js/parsepython.js +0 -542
  46. data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/sql/LICENSE +0 -22
  47. data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/sql/css/sqlcolors.css +0 -57
  48. data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/sql/index.html +0 -56
  49. data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/sql/js/parsesql.js +0 -211
@@ -1,4 +1,4 @@
1
- /* CodeMirror main module
1
+ /* CodeMirror main module (http://codemirror.net/)
2
2
  *
3
3
  * Implements the CodeMirror constructor and prototype, which take care
4
4
  * of initializing the editor frame, and providing the outside interface.
@@ -26,7 +26,7 @@ var CodeMirror = (function(){
26
26
  // options to a specific CodeMirror constructor. See manual.html for
27
27
  // their meaning.
28
28
  setDefaults(CodeMirrorConfig, {
29
- stylesheet: "",
29
+ stylesheet: [],
30
30
  path: "",
31
31
  parserfile: [],
32
32
  basefiles: ["util.js", "stringstream.js", "select.js", "undo.js", "editor.js", "tokenize.js"],
@@ -45,17 +45,22 @@ var CodeMirror = (function(){
45
45
  readOnly: false,
46
46
  width: "",
47
47
  height: "300px",
48
+ minHeight: 100,
48
49
  autoMatchParens: false,
49
50
  parserConfig: null,
50
51
  tabMode: "indent", // or "spaces", "default", "shift"
52
+ enterMode: "indent", // or "keep", "flat"
53
+ electricChars: true,
51
54
  reindentOnLoad: false,
52
55
  activeTokens: null,
53
56
  cursorActivity: null,
54
57
  lineNumbers: false,
55
- indentUnit: 2
58
+ firstLineNumber: 1,
59
+ indentUnit: 2,
60
+ domain: null
56
61
  });
57
62
 
58
- function addLineNumberDiv(container) {
63
+ function addLineNumberDiv(container, firstNum) {
59
64
  var nums = document.createElement("DIV"),
60
65
  scroller = document.createElement("DIV");
61
66
  nums.style.position = "absolute";
@@ -65,26 +70,52 @@ var CodeMirror = (function(){
65
70
  catch(e) {} // Seems to throw 'Not Implemented' on some IE8 versions
66
71
  }
67
72
  nums.style.top = "0px";
73
+ nums.style.left = "0px";
68
74
  nums.style.overflow = "hidden";
69
75
  container.appendChild(nums);
70
76
  scroller.className = "CodeMirror-line-numbers";
71
77
  nums.appendChild(scroller);
78
+ scroller.innerHTML = "<div>" + firstNum + "</div>";
72
79
  return nums;
73
80
  }
74
81
 
75
- function CodeMirror(place, options) {
76
- // Backward compatibility for deprecated options.
77
- if (options.dumbTabs) options.tabMode = "spaces";
78
- else if (options.normalTab) options.tabMode = "default";
82
+ function frameHTML(options) {
83
+ if (typeof options.parserfile == "string")
84
+ options.parserfile = [options.parserfile];
85
+ if (typeof options.basefiles == "string")
86
+ options.basefiles = [options.basefiles];
87
+ if (typeof options.stylesheet == "string")
88
+ options.stylesheet = [options.stylesheet];
89
+
90
+ var html = ["<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\"><html><head>"];
91
+ // Hack to work around a bunch of IE8-specific problems.
92
+ html.push("<meta http-equiv=\"X-UA-Compatible\" content=\"IE=EmulateIE7\"/>");
93
+ forEach(options.stylesheet, function(file) {
94
+ html.push("<link rel=\"stylesheet\" type=\"text/css\" href=\"" + file + "\"/>");
95
+ });
96
+ forEach(options.basefiles.concat(options.parserfile), function(file) {
97
+ if (!/^https?:/.test(file)) file = options.path + file;
98
+ html.push("<script type=\"text/javascript\" src=\"" + file + "\"><" + "/script>");
99
+ });
100
+ html.push("</head><body style=\"border-width: 0;\" class=\"editbox\" spellcheck=\"" +
101
+ (options.disableSpellcheck ? "false" : "true") + "\"></body></html>");
102
+ return html.join("");
103
+ }
79
104
 
105
+ var internetExplorer = document.selection && window.ActiveXObject && /MSIE/.test(navigator.userAgent);
106
+
107
+ function CodeMirror(place, options) {
80
108
  // Use passed options, if any, to override defaults.
81
109
  this.options = options = options || {};
82
110
  setDefaults(options, CodeMirrorConfig);
83
111
 
112
+ // Backward compatibility for deprecated options.
113
+ if (options.dumbTabs) options.tabMode = "spaces";
114
+ else if (options.normalTab) options.tabMode = "default";
115
+
84
116
  var frame = this.frame = document.createElement("IFRAME");
85
117
  if (options.iframeClass) frame.className = options.iframeClass;
86
118
  frame.frameBorder = 0;
87
- frame.src = "javascript:false;";
88
119
  frame.style.border = "0";
89
120
  frame.style.width = '100%';
90
121
  frame.style.height = '100%';
@@ -96,39 +127,38 @@ var CodeMirror = (function(){
96
127
  div.style.position = "relative";
97
128
  div.className = "CodeMirror-wrapping";
98
129
  div.style.width = options.width;
99
- div.style.height = options.height;
100
-
101
- if (place.appendChild) place.appendChild(div);
102
- else place(div);
103
- div.appendChild(frame);
104
- if (options.lineNumbers) this.lineNumbers = addLineNumberDiv(div);
130
+ div.style.height = (options.height == "dynamic") ? options.minHeight + "px" : options.height;
131
+ // This is used by Editor.reroutePasteEvent
132
+ var teHack = this.textareaHack = document.createElement("TEXTAREA");
133
+ div.appendChild(teHack);
134
+ teHack.style.position = "absolute";
135
+ teHack.style.left = "-10000px";
136
+ teHack.style.width = "10px";
105
137
 
106
138
  // Link back to this object, so that the editor can fetch options
107
139
  // and add a reference to itself.
108
140
  frame.CodeMirror = this;
109
- this.win = frame.contentWindow;
110
-
111
- if (typeof options.parserfile == "string")
112
- options.parserfile = [options.parserfile];
113
- if (typeof options.stylesheet == "string")
114
- options.stylesheet = [options.stylesheet];
141
+ if (options.domain && internetExplorer) {
142
+ this.html = frameHTML(options);
143
+ frame.src = "javascript:(function(){document.open();" +
144
+ (options.domain ? "document.domain=\"" + options.domain + "\";" : "") +
145
+ "document.write(window.frameElement.CodeMirror.html);document.close();})()";
146
+ }
147
+ else {
148
+ frame.src = "javascript:;";
149
+ }
115
150
 
116
- var html = ["<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\"><html><head>"];
117
- // Hack to work around a bunch of IE8-specific problems.
118
- html.push("<meta http-equiv=\"X-UA-Compatible\" content=\"IE=EmulateIE7\"/>");
119
- forEach(options.stylesheet, function(file) {
120
- html.push("<link rel=\"stylesheet\" type=\"text/css\" href=\"" + file + "\"/>");
121
- });
122
- forEach(options.basefiles.concat(options.parserfile), function(file) {
123
- html.push("<script type=\"text/javascript\" src=\"" + options.path + file + "\"><" + "/script>");
124
- });
125
- html.push("</head><body style=\"border-width: 0;\" class=\"editbox\" spellcheck=\"" +
126
- (options.disableSpellcheck ? "false" : "true") + "\"></body></html>");
151
+ if (place.appendChild) place.appendChild(div);
152
+ else place(div);
153
+ div.appendChild(frame);
154
+ if (options.lineNumbers) this.lineNumbers = addLineNumberDiv(div, options.firstLineNumber);
127
155
 
128
- var doc = this.win.document;
129
- doc.open();
130
- doc.write(html.join(""));
131
- doc.close();
156
+ this.win = frame.contentWindow;
157
+ if (!options.domain || !internetExplorer) {
158
+ this.win.document.open();
159
+ this.win.document.write(frameHTML(options));
160
+ this.win.document.close();
161
+ }
132
162
  }
133
163
 
134
164
  CodeMirror.prototype = {
@@ -136,6 +166,7 @@ var CodeMirror = (function(){
136
166
  if (this.options.initCallback) this.options.initCallback(this);
137
167
  if (this.options.lineNumbers) this.activateLineNumbers();
138
168
  if (this.options.reindentOnLoad) this.reindent();
169
+ if (this.options.height == "dynamic") this.setDynamicHeight();
139
170
  },
140
171
 
141
172
  getCode: function() {return this.editor.getCode();},
@@ -173,8 +204,44 @@ var CodeMirror = (function(){
173
204
  grabKeys: function(callback, filter) {this.editor.grabKeys(callback, filter);},
174
205
  ungrabKeys: function() {this.editor.ungrabKeys();},
175
206
 
176
- setParser: function(name) {this.editor.setParser(name);},
207
+ setParser: function(name, parserConfig) {this.editor.setParser(name, parserConfig);},
177
208
  setSpellcheck: function(on) {this.win.document.body.spellcheck = on;},
209
+ setStylesheet: function(names) {
210
+ if (typeof names === "string") names = [names];
211
+ var activeStylesheets = {};
212
+ var matchedNames = {};
213
+ var links = this.win.document.getElementsByTagName("link");
214
+ // Create hashes of active stylesheets and matched names.
215
+ // This is O(n^2) but n is expected to be very small.
216
+ for (var x = 0, link; link = links[x]; x++) {
217
+ if (link.rel.indexOf("stylesheet") !== -1) {
218
+ for (var y = 0; y < names.length; y++) {
219
+ var name = names[y];
220
+ if (link.href.substring(link.href.length - name.length) === name) {
221
+ activeStylesheets[link.href] = true;
222
+ matchedNames[name] = true;
223
+ }
224
+ }
225
+ }
226
+ }
227
+ // Activate the selected stylesheets and disable the rest.
228
+ for (var x = 0, link; link = links[x]; x++) {
229
+ if (link.rel.indexOf("stylesheet") !== -1) {
230
+ link.disabled = !(link.href in activeStylesheets);
231
+ }
232
+ }
233
+ // Create any new stylesheets.
234
+ for (var y = 0; y < names.length; y++) {
235
+ var name = names[y];
236
+ if (!(name in matchedNames)) {
237
+ var link = this.win.document.createElement("link");
238
+ link.rel = "stylesheet";
239
+ link.type = "text/css";
240
+ link.href = name;
241
+ this.win.document.getElementsByTagName('head')[0].appendChild(link);
242
+ }
243
+ }
244
+ },
178
245
  setTextWrapping: function(on) {
179
246
  if (on == this.options.textWrapping) return;
180
247
  this.win.document.body.style.whiteSpace = on ? "" : "nowrap";
@@ -187,6 +254,7 @@ var CodeMirror = (function(){
187
254
  setIndentUnit: function(unit) {this.win.indentUnit = unit;},
188
255
  setUndoDepth: function(depth) {this.editor.history.maxDepth = depth;},
189
256
  setTabMode: function(mode) {this.options.tabMode = mode;},
257
+ setEnterMode: function(mode) {this.options.enterMode = mode;},
190
258
  setLineNumbers: function(on) {
191
259
  if (on && !this.lineNumbers) {
192
260
  this.lineNumbers = addLineNumberDiv(this.wrapping);
@@ -226,15 +294,18 @@ var CodeMirror = (function(){
226
294
  }
227
295
  return num;
228
296
  },
229
-
230
- // Old number-based line interface
231
- jumpToLine: function(n) {
232
- this.selectLines(this.nthLine(n), 0);
297
+ jumpToLine: function(line) {
298
+ if (typeof line == "number") line = this.nthLine(line);
299
+ this.selectLines(line, 0);
233
300
  this.win.focus();
234
301
  },
235
- currentLine: function() {
236
- return this.lineNumber(this.cursorPosition().line);
302
+ currentLine: function() { // Deprecated, but still there for backward compatibility
303
+ return this.lineNumber(this.cursorLine());
304
+ },
305
+ cursorLine: function() {
306
+ return this.cursorPosition().line;
237
307
  },
308
+ cursorCoords: function(start) {return this.editor.cursorCoords(start);},
238
309
 
239
310
  activateLineNumbers: function() {
240
311
  var frame = this.frame, win = frame.contentWindow, doc = win.document, body = doc.body,
@@ -243,7 +314,7 @@ var CodeMirror = (function(){
243
314
 
244
315
  function sizeBar() {
245
316
  if (frame.offsetWidth == 0) return;
246
- for (var root = frame; root.parentNode; root = root.parentNode);
317
+ for (var root = frame; root.parentNode; root = root.parentNode){}
247
318
  if (!nums.parentNode || root != document || !win.Editor) {
248
319
  // Clear event handlers (their nodes might already be collected, so try/catch)
249
320
  try{clear();}catch(e){}
@@ -253,7 +324,7 @@ var CodeMirror = (function(){
253
324
 
254
325
  if (nums.offsetWidth != barWidth) {
255
326
  barWidth = nums.offsetWidth;
256
- nums.style.left = "-" + (frame.parentNode.style.marginLeft = barWidth + "px");
327
+ frame.parentNode.style.paddingLeft = barWidth + "px";
257
328
  }
258
329
  }
259
330
  function doScroll() {
@@ -264,61 +335,84 @@ var CodeMirror = (function(){
264
335
  sizeBar();
265
336
  var sizeInterval = setInterval(sizeBar, 500);
266
337
 
338
+ function ensureEnoughLineNumbers(fill) {
339
+ var lineHeight = scroller.firstChild.offsetHeight;
340
+ if (lineHeight == 0) return;
341
+ var targetHeight = 50 + Math.max(body.offsetHeight, Math.max(frame.offsetHeight, body.scrollHeight || 0)),
342
+ lastNumber = Math.ceil(targetHeight / lineHeight);
343
+ for (var i = scroller.childNodes.length; i <= lastNumber; i++) {
344
+ var div = document.createElement("DIV");
345
+ div.appendChild(document.createTextNode(fill ? String(i + self.options.firstLineNumber) : "\u00a0"));
346
+ scroller.appendChild(div);
347
+ }
348
+ }
349
+
267
350
  function nonWrapping() {
268
- var nextNum = 1;
269
351
  function update() {
270
- var target = 50 + Math.max(body.offsetHeight, frame.offsetHeight);
271
- while (scroller.offsetHeight < target) {
272
- scroller.appendChild(document.createElement("DIV"));
273
- scroller.lastChild.innerHTML = nextNum++;
274
- }
352
+ ensureEnoughLineNumbers(true);
275
353
  doScroll();
276
354
  }
277
- var onScroll = win.addEventHandler(win, "scroll", update, true),
355
+ self.updateNumbers = update;
356
+ var onScroll = win.addEventHandler(win, "scroll", doScroll, true),
278
357
  onResize = win.addEventHandler(win, "resize", update, true);
279
- clear = function(){onScroll(); onResize();};
358
+ clear = function(){
359
+ onScroll(); onResize();
360
+ if (self.updateNumbers == update) self.updateNumbers = null;
361
+ };
280
362
  update();
281
363
  }
364
+
282
365
  function wrapping() {
283
- var node, lineNum, next, pos;
366
+ var node, lineNum, next, pos, changes = [], styleNums = self.options.styleNumbers;
284
367
 
285
- function addNum(n) {
368
+ function setNum(n, node) {
369
+ // Does not typically happen (but can, if you mess with the
370
+ // document during the numbering)
286
371
  if (!lineNum) lineNum = scroller.appendChild(document.createElement("DIV"));
287
- lineNum.innerHTML = n;
372
+ if (styleNums) styleNums(lineNum, node, n);
373
+ // Changes are accumulated, so that the document layout
374
+ // doesn't have to be recomputed during the pass
375
+ changes.push(lineNum); changes.push(n);
288
376
  pos = lineNum.offsetHeight + lineNum.offsetTop;
289
377
  lineNum = lineNum.nextSibling;
290
378
  }
379
+ function commitChanges() {
380
+ for (var i = 0; i < changes.length; i += 2)
381
+ changes[i].innerHTML = changes[i + 1];
382
+ changes = [];
383
+ }
291
384
  function work() {
292
385
  if (!scroller.parentNode || scroller.parentNode != self.lineNumbers) return;
293
386
 
294
387
  var endTime = new Date().getTime() + self.options.lineNumberTime;
295
388
  while (node) {
296
- addNum(next++);
389
+ setNum(next++, node.previousSibling);
297
390
  for (; node && !win.isBR(node); node = node.nextSibling) {
298
391
  var bott = node.offsetTop + node.offsetHeight;
299
- while (bott - 3 > pos) addNum("&nbsp;");
392
+ while (scroller.offsetHeight && bott - 3 > pos) setNum("&nbsp;");
300
393
  }
301
394
  if (node) node = node.nextSibling;
302
395
  if (new Date().getTime() > endTime) {
396
+ commitChanges();
303
397
  pending = setTimeout(work, self.options.lineNumberDelay);
304
398
  return;
305
399
  }
306
400
  }
307
- // While there are un-processed number DIVs, or the scroller is smaller than the frame...
308
- var target = 50 + Math.max(body.offsetHeight, frame.offsetHeight);
309
- while (lineNum || scroller.offsetHeight < target) addNum(next++);
401
+ while (lineNum) setNum(next++);
402
+ commitChanges();
310
403
  doScroll();
311
404
  }
312
- function start() {
405
+ function start(firstTime) {
313
406
  doScroll();
407
+ ensureEnoughLineNumbers(firstTime);
314
408
  node = body.firstChild;
315
409
  lineNum = scroller.firstChild;
316
410
  pos = 0;
317
- next = 1;
411
+ next = self.options.firstLineNumber;
318
412
  work();
319
413
  }
320
414
 
321
- start();
415
+ start(true);
322
416
  var pending = null;
323
417
  function update() {
324
418
  if (pending) clearTimeout(pending);
@@ -335,7 +429,38 @@ var CodeMirror = (function(){
335
429
  onResize();
336
430
  };
337
431
  }
338
- (this.options.textWrapping ? wrapping : nonWrapping)();
432
+ (this.options.textWrapping || this.options.styleNumbers ? wrapping : nonWrapping)();
433
+ },
434
+
435
+ setDynamicHeight: function() {
436
+ var self = this, activity = self.options.cursorActivity, win = self.win, body = win.document.body,
437
+ lineHeight = null, timeout = null, vmargin = 2 * self.frame.offsetTop;
438
+ body.style.overflowY = "hidden";
439
+ win.document.documentElement.style.overflowY = "hidden";
440
+ this.frame.scrolling = "no";
441
+
442
+ function updateHeight() {
443
+ var trailingLines = 0, node = body.lastChild, computedHeight;
444
+ while (node && win.isBR(node)) {
445
+ if (!node.hackBR) trailingLines++;
446
+ node = node.previousSibling;
447
+ }
448
+ if (node) {
449
+ lineHeight = node.offsetHeight;
450
+ computedHeight = node.offsetTop + (1 + trailingLines) * lineHeight;
451
+ }
452
+ else if (lineHeight) {
453
+ computedHeight = trailingLines * lineHeight;
454
+ }
455
+ if (computedHeight)
456
+ self.wrapping.style.height = Math.max(vmargin + computedHeight, self.options.minHeight) + "px";
457
+ }
458
+ setTimeout(updateHeight, 300);
459
+ self.options.cursorActivity = function(x) {
460
+ if (activity) activity(x);
461
+ clearTimeout(timeout);
462
+ timeout = setTimeout(updateHeight, 100);
463
+ };
339
464
  }
340
465
  };
341
466
 
@@ -368,6 +493,15 @@ var CodeMirror = (function(){
368
493
  area.form.addEventListener("submit", updateField, false);
369
494
  else
370
495
  area.form.attachEvent("onsubmit", updateField);
496
+ var realSubmit = area.form.submit;
497
+ function wrapSubmit() {
498
+ updateField();
499
+ // Can't use realSubmit.apply because IE6 is too stupid
500
+ area.form.submit = realSubmit;
501
+ area.form.submit();
502
+ area.form.submit = wrapSubmit;
503
+ }
504
+ area.form.submit = wrapSubmit;
371
505
  }
372
506
 
373
507
  function insert(frame) {
@@ -379,6 +513,18 @@ var CodeMirror = (function(){
379
513
 
380
514
  area.style.display = "none";
381
515
  var mirror = new CodeMirror(insert, options);
516
+ mirror.toTextArea = function() {
517
+ area.parentNode.removeChild(mirror.wrapping);
518
+ area.style.display = "";
519
+ if (area.form) {
520
+ area.form.submit = realSubmit;
521
+ if (typeof area.form.removeEventListener == "function")
522
+ area.form.removeEventListener("submit", updateField, false);
523
+ else
524
+ area.form.detachEvent("onsubmit", updateField);
525
+ }
526
+ };
527
+
382
528
  return mirror;
383
529
  };
384
530