##// END OF EJS Templates
Adding refresh/focus/refresh back to edit to fix bug in FF.
Brian Granger -
Show More
@@ -1,288 +1,290 b''
1 //----------------------------------------------------------------------------
1 //----------------------------------------------------------------------------
2 // Copyright (C) 2008-2011 The IPython Development Team
2 // Copyright (C) 2008-2011 The IPython Development Team
3 //
3 //
4 // Distributed under the terms of the BSD License. The full license is in
4 // Distributed under the terms of the BSD License. The full license is in
5 // the file COPYING, distributed as part of this software.
5 // the file COPYING, distributed as part of this software.
6 //----------------------------------------------------------------------------
6 //----------------------------------------------------------------------------
7
7
8 //============================================================================
8 //============================================================================
9 // TextCell
9 // TextCell
10 //============================================================================
10 //============================================================================
11
11
12 var IPython = (function (IPython) {
12 var IPython = (function (IPython) {
13
13
14 // TextCell base class
14 // TextCell base class
15
15
16 var TextCell = function (notebook) {
16 var TextCell = function (notebook) {
17 this.code_mirror_mode = this.code_mirror_mode || 'htmlmixed';
17 this.code_mirror_mode = this.code_mirror_mode || 'htmlmixed';
18 IPython.Cell.apply(this, arguments);
18 IPython.Cell.apply(this, arguments);
19 this.rendered = false;
19 this.rendered = false;
20 this.cell_type = this.cell_type || 'text';
20 this.cell_type = this.cell_type || 'text';
21 };
21 };
22
22
23
23
24 TextCell.prototype = new IPython.Cell();
24 TextCell.prototype = new IPython.Cell();
25
25
26
26
27 TextCell.prototype.create_element = function () {
27 TextCell.prototype.create_element = function () {
28 var cell = $("<div>").addClass('cell text_cell border-box-sizing');
28 var cell = $("<div>").addClass('cell text_cell border-box-sizing');
29 cell.attr('tabindex','2');
29 cell.attr('tabindex','2');
30 var input_area = $('<div/>').addClass('text_cell_input border-box-sizing');
30 var input_area = $('<div/>').addClass('text_cell_input border-box-sizing');
31 this.code_mirror = CodeMirror(input_area.get(0), {
31 this.code_mirror = CodeMirror(input_area.get(0), {
32 indentUnit : 4,
32 indentUnit : 4,
33 mode: this.code_mirror_mode,
33 mode: this.code_mirror_mode,
34 theme: 'default',
34 theme: 'default',
35 value: this.placeholder,
35 value: this.placeholder,
36 readOnly: this.read_only,
36 readOnly: this.read_only,
37 onKeyEvent: $.proxy(this.handle_codemirror_keyevent,this)
37 onKeyEvent: $.proxy(this.handle_codemirror_keyevent,this)
38 });
38 });
39 // The tabindex=-1 makes this div focusable.
39 // The tabindex=-1 makes this div focusable.
40 var render_area = $('<div/>').addClass('text_cell_render border-box-sizing').
40 var render_area = $('<div/>').addClass('text_cell_render border-box-sizing').
41 addClass('rendered_html').attr('tabindex','-1');
41 addClass('rendered_html').attr('tabindex','-1');
42 cell.append(input_area).append(render_area);
42 cell.append(input_area).append(render_area);
43 this.element = cell;
43 this.element = cell;
44 };
44 };
45
45
46
46
47 TextCell.prototype.bind_events = function () {
47 TextCell.prototype.bind_events = function () {
48 IPython.Cell.prototype.bind_events.apply(this);
48 IPython.Cell.prototype.bind_events.apply(this);
49 var that = this;
49 var that = this;
50 this.element.keydown(function (event) {
50 this.element.keydown(function (event) {
51 if (event.which === 13) {
51 if (event.which === 13) {
52 if (that.rendered) {
52 if (that.rendered) {
53 that.edit();
53 that.edit();
54 return false;
54 return false;
55 };
55 };
56 };
56 };
57 });
57 });
58 this.element.dblclick(function () {
58 this.element.dblclick(function () {
59 that.edit();
59 that.edit();
60 });
60 });
61 };
61 };
62
62
63
63
64 TextCell.prototype.handle_codemirror_keyevent = function (editor, event) {
64 TextCell.prototype.handle_codemirror_keyevent = function (editor, event) {
65 // This method gets called in CodeMirror's onKeyDown/onKeyPress
65 // This method gets called in CodeMirror's onKeyDown/onKeyPress
66 // handlers and is used to provide custom key handling. Its return
66 // handlers and is used to provide custom key handling. Its return
67 // value is used to determine if CodeMirror should ignore the event:
67 // value is used to determine if CodeMirror should ignore the event:
68 // true = ignore, false = don't ignore.
68 // true = ignore, false = don't ignore.
69
69
70 if (event.keyCode === 13 && (event.shiftKey || event.ctrlKey)) {
70 if (event.keyCode === 13 && (event.shiftKey || event.ctrlKey)) {
71 // Always ignore shift-enter in CodeMirror as we handle it.
71 // Always ignore shift-enter in CodeMirror as we handle it.
72 return true;
72 return true;
73 }
73 }
74 return false;
74 return false;
75 };
75 };
76
76
77
77
78 TextCell.prototype.select = function () {
78 TextCell.prototype.select = function () {
79 IPython.Cell.prototype.select.apply(this);
79 IPython.Cell.prototype.select.apply(this);
80 var output = this.element.find("div.text_cell_render");
80 var output = this.element.find("div.text_cell_render");
81 output.trigger('focus');
81 output.trigger('focus');
82 };
82 };
83
83
84
84
85 TextCell.prototype.unselect = function() {
85 TextCell.prototype.unselect = function() {
86 // render on selection of another cell
86 // render on selection of another cell
87 this.render();
87 this.render();
88 IPython.Cell.prototype.unselect.apply(this);
88 IPython.Cell.prototype.unselect.apply(this);
89 };
89 };
90
90
91
91
92 TextCell.prototype.edit = function () {
92 TextCell.prototype.edit = function () {
93 if ( this.read_only ) return;
93 if ( this.read_only ) return;
94 if (this.rendered === true) {
94 if (this.rendered === true) {
95 var text_cell = this.element;
95 var text_cell = this.element;
96 var output = text_cell.find("div.text_cell_render");
96 var output = text_cell.find("div.text_cell_render");
97 output.hide();
97 output.hide();
98 text_cell.find('div.text_cell_input').show();
98 text_cell.find('div.text_cell_input').show();
99 // I don't know why I need to do this, but if I don't do
99 // I don't know why I need to do this, but if I don't do
100 // refresh/focus/refresh, the to_markdown method won't work.
100 // refresh/focus/refresh, the to_markdown method won't work.
101 this.code_mirror.refresh();
101 this.code_mirror.refresh();
102 this.code_mirror.focus();
102 this.code_mirror.focus();
103 // In some wierd cases we seem to need this extra refresh.
103 // This final refresh is needed on Firefox to trigger the editor
104 //this.code_mirror.refresh();
104 // to be auto-sized. This glitch only happens on cell that are
105 // loaded initially and haven't had their editor focused before.
106 this.code_mirror.refresh();
105 this.rendered = false;
107 this.rendered = false;
106 if (this.get_text() === this.placeholder) {
108 if (this.get_text() === this.placeholder) {
107 this.set_text('');
109 this.set_text('');
108 this.refresh();
110 this.refresh();
109 }
111 }
110 }
112 }
111 };
113 };
112
114
113
115
114 // Subclasses must define render.
116 // Subclasses must define render.
115 TextCell.prototype.render = function () {};
117 TextCell.prototype.render = function () {};
116
118
117
119
118 TextCell.prototype.get_text = function() {
120 TextCell.prototype.get_text = function() {
119 return this.code_mirror.getValue();
121 return this.code_mirror.getValue();
120 };
122 };
121
123
122
124
123 TextCell.prototype.set_text = function(text) {
125 TextCell.prototype.set_text = function(text) {
124 this.code_mirror.setValue(text);
126 this.code_mirror.setValue(text);
125 this.code_mirror.refresh();
127 this.code_mirror.refresh();
126 };
128 };
127
129
128
130
129 TextCell.prototype.get_rendered = function() {
131 TextCell.prototype.get_rendered = function() {
130 return this.element.find('div.text_cell_render').html();
132 return this.element.find('div.text_cell_render').html();
131 };
133 };
132
134
133
135
134 TextCell.prototype.set_rendered = function(text) {
136 TextCell.prototype.set_rendered = function(text) {
135 this.element.find('div.text_cell_render').html(text);
137 this.element.find('div.text_cell_render').html(text);
136 };
138 };
137
139
138
140
139 TextCell.prototype.at_top = function () {
141 TextCell.prototype.at_top = function () {
140 if (this.rendered) {
142 if (this.rendered) {
141 return true;
143 return true;
142 } else {
144 } else {
143 return false;
145 return false;
144 }
146 }
145 };
147 };
146
148
147
149
148 TextCell.prototype.at_bottom = function () {
150 TextCell.prototype.at_bottom = function () {
149 if (this.rendered) {
151 if (this.rendered) {
150 return true;
152 return true;
151 } else {
153 } else {
152 return false;
154 return false;
153 }
155 }
154 };
156 };
155
157
156
158
157 TextCell.prototype.fromJSON = function (data) {
159 TextCell.prototype.fromJSON = function (data) {
158 if (data.cell_type === this.cell_type) {
160 if (data.cell_type === this.cell_type) {
159 if (data.source !== undefined) {
161 if (data.source !== undefined) {
160 this.set_text(data.source);
162 this.set_text(data.source);
161 this.set_rendered(data.rendered || '');
163 this.set_rendered(data.rendered || '');
162 this.rendered = false;
164 this.rendered = false;
163 this.render();
165 this.render();
164 }
166 }
165 }
167 }
166 };
168 };
167
169
168
170
169 TextCell.prototype.toJSON = function () {
171 TextCell.prototype.toJSON = function () {
170 var data = {};
172 var data = {};
171 data.cell_type = this.cell_type;
173 data.cell_type = this.cell_type;
172 data.source = this.get_text();
174 data.source = this.get_text();
173 return data;
175 return data;
174 };
176 };
175
177
176
178
177 // HTMLCell
179 // HTMLCell
178
180
179 var HTMLCell = function (notebook) {
181 var HTMLCell = function (notebook) {
180 this.placeholder = "Type <strong>HTML</strong> and LaTeX: $\\alpha^2$";
182 this.placeholder = "Type <strong>HTML</strong> and LaTeX: $\\alpha^2$";
181 IPython.TextCell.apply(this, arguments);
183 IPython.TextCell.apply(this, arguments);
182 this.cell_type = 'html';
184 this.cell_type = 'html';
183 };
185 };
184
186
185
187
186 HTMLCell.prototype = new TextCell();
188 HTMLCell.prototype = new TextCell();
187
189
188
190
189 HTMLCell.prototype.render = function () {
191 HTMLCell.prototype.render = function () {
190 if (this.rendered === false) {
192 if (this.rendered === false) {
191 var text = this.get_text();
193 var text = this.get_text();
192 if (text === "") { text = this.placeholder; }
194 if (text === "") { text = this.placeholder; }
193 this.set_rendered(text);
195 this.set_rendered(text);
194 this.typeset();
196 this.typeset();
195 this.element.find('div.text_cell_input').hide();
197 this.element.find('div.text_cell_input').hide();
196 this.element.find("div.text_cell_render").show();
198 this.element.find("div.text_cell_render").show();
197 this.rendered = true;
199 this.rendered = true;
198 }
200 }
199 };
201 };
200
202
201
203
202 // MarkdownCell
204 // MarkdownCell
203
205
204 var MarkdownCell = function (notebook) {
206 var MarkdownCell = function (notebook) {
205 this.placeholder = "Type *Markdown* and LaTeX: $\\alpha^2$";
207 this.placeholder = "Type *Markdown* and LaTeX: $\\alpha^2$";
206 IPython.TextCell.apply(this, arguments);
208 IPython.TextCell.apply(this, arguments);
207 this.cell_type = 'markdown';
209 this.cell_type = 'markdown';
208 };
210 };
209
211
210
212
211 MarkdownCell.prototype = new TextCell();
213 MarkdownCell.prototype = new TextCell();
212
214
213
215
214 MarkdownCell.prototype.render = function () {
216 MarkdownCell.prototype.render = function () {
215 if (this.rendered === false) {
217 if (this.rendered === false) {
216 var text = this.get_text();
218 var text = this.get_text();
217 if (text === "") { text = this.placeholder; }
219 if (text === "") { text = this.placeholder; }
218 var html = IPython.markdown_converter.makeHtml(text);
220 var html = IPython.markdown_converter.makeHtml(text);
219 this.set_rendered(html);
221 this.set_rendered(html);
220 this.typeset()
222 this.typeset()
221 this.element.find('div.text_cell_input').hide();
223 this.element.find('div.text_cell_input').hide();
222 this.element.find("div.text_cell_render").show();
224 this.element.find("div.text_cell_render").show();
223 var code_snippets = this.element.find("pre > code");
225 var code_snippets = this.element.find("pre > code");
224 code_snippets.replaceWith(function () {
226 code_snippets.replaceWith(function () {
225 var code = $(this).html();
227 var code = $(this).html();
226 /* Substitute br for newlines and &nbsp; for spaces
228 /* Substitute br for newlines and &nbsp; for spaces
227 before highlighting, since prettify doesn't
229 before highlighting, since prettify doesn't
228 preserve those on all browsers */
230 preserve those on all browsers */
229 code = code.replace(/(\r\n|\n|\r)/gm, "<br/>");
231 code = code.replace(/(\r\n|\n|\r)/gm, "<br/>");
230 code = code.replace(/ /gm, '&nbsp;');
232 code = code.replace(/ /gm, '&nbsp;');
231 code = prettyPrintOne(code);
233 code = prettyPrintOne(code);
232
234
233 return '<code class="prettyprint">' + code + '</code>';
235 return '<code class="prettyprint">' + code + '</code>';
234 });
236 });
235 this.rendered = true;
237 this.rendered = true;
236 }
238 }
237 };
239 };
238
240
239
241
240 // RSTCell
242 // RSTCell
241
243
242 var RSTCell = function (notebook) {
244 var RSTCell = function (notebook) {
243 this.placeholder = "Type *ReStructured Text* and LaTeX: $\\alpha^2$";
245 this.placeholder = "Type *ReStructured Text* and LaTeX: $\\alpha^2$";
244 IPython.TextCell.apply(this, arguments);
246 IPython.TextCell.apply(this, arguments);
245 this.cell_type = 'rst';
247 this.cell_type = 'rst';
246 };
248 };
247
249
248
250
249 RSTCell.prototype = new TextCell();
251 RSTCell.prototype = new TextCell();
250
252
251
253
252 RSTCell.prototype.render = function () {
254 RSTCell.prototype.render = function () {
253 if (this.rendered === false) {
255 if (this.rendered === false) {
254 var text = this.get_text();
256 var text = this.get_text();
255 if (text === "") { text = this.placeholder; }
257 if (text === "") { text = this.placeholder; }
256 var settings = {
258 var settings = {
257 processData : false,
259 processData : false,
258 cache : false,
260 cache : false,
259 type : "POST",
261 type : "POST",
260 data : text,
262 data : text,
261 headers : {'Content-Type': 'application/x-rst'},
263 headers : {'Content-Type': 'application/x-rst'},
262 success : $.proxy(this.handle_render,this)
264 success : $.proxy(this.handle_render,this)
263 };
265 };
264 $.ajax("/rstservice/render", settings);
266 $.ajax("/rstservice/render", settings);
265 this.element.find('div.text_cell_input').hide();
267 this.element.find('div.text_cell_input').hide();
266 this.element.find("div.text_cell_render").show();
268 this.element.find("div.text_cell_render").show();
267 this.set_rendered("Rendering...");
269 this.set_rendered("Rendering...");
268 }
270 }
269 };
271 };
270
272
271
273
272 RSTCell.prototype.handle_render = function (data, status, xhr) {
274 RSTCell.prototype.handle_render = function (data, status, xhr) {
273 this.set_rendered(data);
275 this.set_rendered(data);
274 this.typeset();
276 this.typeset();
275 this.rendered = true;
277 this.rendered = true;
276 };
278 };
277
279
278
280
279 IPython.TextCell = TextCell;
281 IPython.TextCell = TextCell;
280 IPython.HTMLCell = HTMLCell;
282 IPython.HTMLCell = HTMLCell;
281 IPython.MarkdownCell = MarkdownCell;
283 IPython.MarkdownCell = MarkdownCell;
282 IPython.RSTCell = RSTCell;
284 IPython.RSTCell = RSTCell;
283
285
284
286
285 return IPython;
287 return IPython;
286
288
287 }(IPython));
289 }(IPython));
288
290
General Comments 0
You need to be logged in to leave comments. Login now