##// END OF EJS Templates
Fixing Shift-Enter bug in text cells....
Brian Granger -
Show More
@@ -1,348 +1,348
1 1 //----------------------------------------------------------------------------
2 2 // Copyright (C) 2008-2011 The IPython Development Team
3 3 //
4 4 // Distributed under the terms of the BSD License. The full license is in
5 5 // the file COPYING, distributed as part of this software.
6 6 //----------------------------------------------------------------------------
7 7
8 8 //============================================================================
9 9 // TextCell
10 10 //============================================================================
11 11
12 12 var IPython = (function (IPython) {
13 13
14 14 // TextCell base class
15 15
16 16 var TextCell = function (notebook) {
17 17 this.code_mirror_mode = this.code_mirror_mode || 'htmlmixed';
18 18 IPython.Cell.apply(this, arguments);
19 19 this.rendered = false;
20 20 this.cell_type = this.cell_type || 'text';
21 21 };
22 22
23 23
24 24 TextCell.prototype = new IPython.Cell();
25 25
26 26
27 27 TextCell.prototype.create_element = function () {
28 28 var cell = $("<div>").addClass('cell text_cell border-box-sizing');
29 29 cell.attr('tabindex','2');
30 30 var input_area = $('<div/>').addClass('text_cell_input border-box-sizing');
31 31 this.code_mirror = CodeMirror(input_area.get(0), {
32 32 indentUnit : 4,
33 33 mode: this.code_mirror_mode,
34 34 theme: 'default',
35 35 value: this.placeholder,
36 36 readOnly: this.read_only,
37 37 lineWrapping : true,
38 38 onKeyEvent: $.proxy(this.handle_codemirror_keyevent,this)
39 39 });
40 40 // The tabindex=-1 makes this div focusable.
41 41 var render_area = $('<div/>').addClass('text_cell_render border-box-sizing').
42 42 addClass('rendered_html').attr('tabindex','-1');
43 43 cell.append(input_area).append(render_area);
44 44 this.element = cell;
45 45 };
46 46
47 47
48 48 TextCell.prototype.bind_events = function () {
49 49 IPython.Cell.prototype.bind_events.apply(this);
50 50 var that = this;
51 51 this.element.keydown(function (event) {
52 if (event.which === 13) {
52 if (event.which === 13 && !event.shiftKey) {
53 53 if (that.rendered) {
54 54 that.edit();
55 55 return false;
56 56 };
57 57 };
58 58 });
59 59 this.element.dblclick(function () {
60 60 that.edit();
61 61 });
62 62 };
63 63
64 64
65 65 TextCell.prototype.handle_codemirror_keyevent = function (editor, event) {
66 66 // This method gets called in CodeMirror's onKeyDown/onKeyPress
67 67 // handlers and is used to provide custom key handling. Its return
68 68 // value is used to determine if CodeMirror should ignore the event:
69 69 // true = ignore, false = don't ignore.
70 70
71 71 if (event.keyCode === 13 && (event.shiftKey || event.ctrlKey)) {
72 72 // Always ignore shift-enter in CodeMirror as we handle it.
73 73 return true;
74 74 }
75 75 return false;
76 76 };
77 77
78 78
79 79 TextCell.prototype.select = function () {
80 80 IPython.Cell.prototype.select.apply(this);
81 81 var output = this.element.find("div.text_cell_render");
82 82 output.trigger('focus');
83 83 };
84 84
85 85
86 86 TextCell.prototype.unselect = function() {
87 87 // render on selection of another cell
88 88 this.render();
89 89 IPython.Cell.prototype.unselect.apply(this);
90 90 };
91 91
92 92
93 93 TextCell.prototype.edit = function () {
94 94 if ( this.read_only ) return;
95 95 if (this.rendered === true) {
96 96 var text_cell = this.element;
97 97 var output = text_cell.find("div.text_cell_render");
98 98 output.hide();
99 99 text_cell.find('div.text_cell_input').show();
100 100 this.code_mirror.refresh();
101 101 this.code_mirror.focus();
102 102 // We used to need an additional refresh() after the focus, but
103 103 // it appears that this has been fixed in CM. This bug would show
104 104 // up on FF when a newly loaded markdown cell was edited.
105 105 this.rendered = false;
106 106 if (this.get_text() === this.placeholder) {
107 107 this.set_text('');
108 108 this.refresh();
109 109 }
110 110 }
111 111 };
112 112
113 113
114 114 // Subclasses must define render.
115 115 TextCell.prototype.render = function () {};
116 116
117 117
118 118 TextCell.prototype.get_text = function() {
119 119 return this.code_mirror.getValue();
120 120 };
121 121
122 122
123 123 TextCell.prototype.set_text = function(text) {
124 124 this.code_mirror.setValue(text);
125 125 this.code_mirror.refresh();
126 126 };
127 127
128 128
129 129 TextCell.prototype.get_rendered = function() {
130 130 return this.element.find('div.text_cell_render').html();
131 131 };
132 132
133 133
134 134 TextCell.prototype.set_rendered = function(text) {
135 135 this.element.find('div.text_cell_render').html(text);
136 136 };
137 137
138 138
139 139 TextCell.prototype.at_top = function () {
140 140 if (this.rendered) {
141 141 return true;
142 142 } else {
143 143 return false;
144 144 }
145 145 };
146 146
147 147
148 148 TextCell.prototype.at_bottom = function () {
149 149 if (this.rendered) {
150 150 return true;
151 151 } else {
152 152 return false;
153 153 }
154 154 };
155 155
156 156
157 157 TextCell.prototype.fromJSON = function (data) {
158 158 if (data.cell_type === this.cell_type) {
159 159 if (data.source !== undefined) {
160 160 this.set_text(data.source);
161 161 this.set_rendered(data.rendered || '');
162 162 this.rendered = false;
163 163 this.render();
164 164 }
165 165 }
166 166 };
167 167
168 168
169 169 TextCell.prototype.toJSON = function () {
170 170 var data = {};
171 171 data.cell_type = this.cell_type;
172 172 data.source = this.get_text();
173 173 return data;
174 174 };
175 175
176 176
177 177 // HTMLCell
178 178
179 179 var HTMLCell = function (notebook) {
180 180 this.placeholder = "Type <strong>HTML</strong> and LaTeX: $\\alpha^2$";
181 181 IPython.TextCell.apply(this, arguments);
182 182 this.cell_type = 'html';
183 183 };
184 184
185 185
186 186 HTMLCell.prototype = new TextCell();
187 187
188 188
189 189 HTMLCell.prototype.render = function () {
190 190 if (this.rendered === false) {
191 191 var text = this.get_text();
192 192 if (text === "") { text = this.placeholder; }
193 193 this.set_rendered(text);
194 194 this.typeset();
195 195 this.element.find('div.text_cell_input').hide();
196 196 this.element.find("div.text_cell_render").show();
197 197 this.rendered = true;
198 198 }
199 199 };
200 200
201 201
202 202 // MarkdownCell
203 203
204 204 var MarkdownCell = function (notebook) {
205 205 this.placeholder = "Type *Markdown* and LaTeX: $\\alpha^2$";
206 206 IPython.TextCell.apply(this, arguments);
207 207 this.cell_type = 'markdown';
208 208 };
209 209
210 210
211 211 MarkdownCell.prototype = new TextCell();
212 212
213 213
214 214 MarkdownCell.prototype.render = function () {
215 215 if (this.rendered === false) {
216 216 var text = this.get_text();
217 217 if (text === "") { text = this.placeholder; }
218 218 var html = IPython.markdown_converter.makeHtml(text);
219 219 this.set_rendered(html);
220 220 this.typeset()
221 221 this.element.find('div.text_cell_input').hide();
222 222 this.element.find("div.text_cell_render").show();
223 223 var code_snippets = this.element.find("pre > code");
224 224 code_snippets.replaceWith(function () {
225 225 var code = $(this).html();
226 226 /* Substitute br for newlines and &nbsp; for spaces
227 227 before highlighting, since prettify doesn't
228 228 preserve those on all browsers */
229 229 code = code.replace(/(\r\n|\n|\r)/gm, "<br/>");
230 230 code = code.replace(/ /gm, '&nbsp;');
231 231 code = prettyPrintOne(code);
232 232
233 233 return '<code class="prettyprint">' + code + '</code>';
234 234 });
235 235 this.rendered = true;
236 236 }
237 237 };
238 238
239 239
240 240 // PlaintextCell
241 241
242 242 var PlaintextCell = function (notebook) {
243 243 this.placeholder = "Type plain text and LaTeX: $\\alpha^2$";
244 244 this.code_mirror_mode = 'rst';
245 245 IPython.TextCell.apply(this, arguments);
246 246 this.cell_type = 'plaintext';
247 247 };
248 248
249 249
250 250 PlaintextCell.prototype = new TextCell();
251 251
252 252
253 253 PlaintextCell.prototype.render = function () {
254 254 this.rendered = true;
255 255 this.edit();
256 256 };
257 257
258 258
259 259 PlaintextCell.prototype.select = function () {
260 260 IPython.Cell.prototype.select.apply(this);
261 261 this.code_mirror.refresh();
262 262 this.code_mirror.focus();
263 263 };
264 264
265 265
266 266 PlaintextCell.prototype.at_top = function () {
267 267 var cursor = this.code_mirror.getCursor();
268 268 if (cursor.line === 0) {
269 269 return true;
270 270 } else {
271 271 return false;
272 272 }
273 273 };
274 274
275 275
276 276 PlaintextCell.prototype.at_bottom = function () {
277 277 var cursor = this.code_mirror.getCursor();
278 278 if (cursor.line === (this.code_mirror.lineCount()-1)) {
279 279 return true;
280 280 } else {
281 281 return false;
282 282 }
283 283 };
284 284
285 285
286 286 // HTMLCell
287 287
288 288 var HeadingCell = function (notebook) {
289 289 this.placeholder = "Type Heading Here";
290 290 IPython.TextCell.apply(this, arguments);
291 291 this.cell_type = 'heading';
292 292 this.level = 1;
293 293 };
294 294
295 295
296 296 HeadingCell.prototype = new TextCell();
297 297
298 298
299 299 HeadingCell.prototype.set_level = function (level) {
300 300 this.level = level;
301 301 if (this.rendered) {
302 302 this.rendered = false;
303 303 this.render();
304 304 };
305 305 };
306 306
307 307
308 308 HeadingCell.prototype.get_level = function () {
309 309 return this.level;
310 310 };
311 311
312 312
313 313 HeadingCell.prototype.set_rendered = function (text) {
314 314 var r = this.element.find("div.text_cell_render");
315 315 r.empty();
316 316 r.append($('<h'+this.level+'/>').html(text));
317 317 };
318 318
319 319
320 320 HeadingCell.prototype.get_rendered = function () {
321 321 var r = this.element.find("div.text_cell_render");
322 322 return r.children().first().html();
323 323 };
324 324
325 325
326 326 HeadingCell.prototype.render = function () {
327 327 if (this.rendered === false) {
328 328 var text = this.get_text();
329 329 if (text === "") { text = this.placeholder; }
330 330 this.set_rendered(text);
331 331 this.typeset();
332 332 this.element.find('div.text_cell_input').hide();
333 333 this.element.find("div.text_cell_render").show();
334 334 this.rendered = true;
335 335 };
336 336 };
337 337
338 338 IPython.TextCell = TextCell;
339 339 IPython.HTMLCell = HTMLCell;
340 340 IPython.MarkdownCell = MarkdownCell;
341 341 IPython.PlaintextCell = PlaintextCell;
342 342 IPython.HeadingCell = HeadingCell;
343 343
344 344
345 345 return IPython;
346 346
347 347 }(IPython));
348 348
General Comments 0
You need to be logged in to leave comments. Login now