##// END OF EJS Templates
More work on the dual mode UX.
Brian E. Granger -
Show More
@@ -123,7 +123,12 b' var IPython = (function (IPython) {'
123 123 this.code_mirror.on("change", function(cm, change) {
124 124 $([IPython.events]).trigger("set_dirty.Notebook", {value: true});
125 125 });
126 }
126 };
127 if (this.code_mirror) {
128 this.code_mirror.on('focus', function(cm, change) {
129 $([IPython.events]).trigger('edit_mode.Cell', {cell: that});
130 });
131 };
127 132 };
128 133
129 134 /**
@@ -143,12 +148,14 b' var IPython = (function (IPython) {'
143 148 * @return is the action being taken
144 149 */
145 150 Cell.prototype.select = function () {
151 console.log('Cell.select');
146 152 if (!this.selected) {
147 153 this.element.addClass('selected');
148 154 this.element.removeClass('unselected');
149 155 this.selected = true;
150 156 return true;
151 157 } else {
158 console.log('WARNING: select');
152 159 return false;
153 160 };
154 161 };
@@ -159,12 +166,14 b' var IPython = (function (IPython) {'
159 166 * @return is the action being taken
160 167 */
161 168 Cell.prototype.unselect = function () {
169 console.log('Cell.unselect');
162 170 if (this.selected) {
163 171 this.element.addClass('unselected');
164 172 this.element.removeClass('selected');
165 173 this.selected = false;
166 174 return true;
167 175 } else {
176 console.log('WARNING: unselect');
168 177 return false;
169 178 };
170 179 };
@@ -175,12 +184,14 b' var IPython = (function (IPython) {'
175 184 * @return is the action being taken
176 185 */
177 186 Cell.prototype.render = function () {
187 console.log('Cell.render');
178 188 if (!this.rendered) {
179 189 this.element.addClass('rendered');
180 190 this.element.removeClass('unrendered');
181 191 this.rendered = true;
182 192 return true;
183 193 } else {
194 console.log('WARNING: render');
184 195 return false;
185 196 };
186 197 };
@@ -191,12 +202,14 b' var IPython = (function (IPython) {'
191 202 * @return is the action being taken
192 203 */
193 204 Cell.prototype.unrender = function () {
205 console.log('Cell.unrender');
194 206 if (this.rendered) {
195 207 this.element.addClass('unrendered');
196 208 this.element.removeClass('rendered');
197 209 this.rendered = false;
198 210 return true;
199 211 } else {
212 console.log('WARNING: unrender');
200 213 return false;
201 214 };
202 215 };
@@ -207,12 +220,14 b' var IPython = (function (IPython) {'
207 220 * @return is the action being taken
208 221 */
209 222 Cell.prototype.command_mode = function () {
223 console.log('Cell.command_mode:', this.mode);
210 224 if (this.mode !== 'command') {
211 225 this.element.addClass('command_mode');
212 226 this.element.removeClass('edit_mode');
213 227 this.mode = 'command';
214 228 return true;
215 229 } else {
230 console.log('WARNING: command_mode');
216 231 return false;
217 232 };
218 233 };
@@ -223,12 +238,14 b' var IPython = (function (IPython) {'
223 238 * @return is the action being taken
224 239 */
225 240 Cell.prototype.edit_mode = function () {
241 console.log('Cell.edit_mode:', this.mode);
226 242 if (this.mode !== 'edit') {
227 243 this.element.addClass('edit_mode');
228 244 this.element.removeClass('command_mode');
229 245 this.mode = 'edit';
230 246 return true;
231 247 } else {
248 console.log('WARNING: edit_mode');
232 249 return false;
233 250 };
234 251 }
@@ -246,26 +263,11 b' var IPython = (function (IPython) {'
246 263 * @method focus_editor
247 264 */
248 265 Cell.prototype.focus_editor = function () {
249 this.code_mirror.refresh();
266 this.refresh();
250 267 this.code_mirror.focus();
251 268 }
252 269
253 270 /**
254 * should be overritten by subclass
255 * @method get_text
256 */
257 Cell.prototype.get_text = function () {
258 };
259
260 /**
261 * should be overritten by subclass
262 * @method set_text
263 * @param {string} text
264 */
265 Cell.prototype.set_text = function (text) {
266 };
267
268 /**
269 271 * Refresh codemirror instance
270 272 * @method refresh
271 273 */
@@ -273,20 +275,19 b' var IPython = (function (IPython) {'
273 275 this.code_mirror.refresh();
274 276 };
275 277
276
277 278 /**
278 279 * should be overritten by subclass
279 * @method edit
280 **/
281 Cell.prototype.edit = function () {
280 * @method get_text
281 */
282 Cell.prototype.get_text = function () {
282 283 };
283 284
284
285 285 /**
286 286 * should be overritten by subclass
287 * @method render
288 **/
289 Cell.prototype.render = function () {
287 * @method set_text
288 * @param {string} text
289 */
290 Cell.prototype.set_text = function (text) {
290 291 };
291 292
292 293 /**
@@ -139,6 +139,16 b' var IPython = (function (IPython) {'
139 139 this.completer = new IPython.Completer(this);
140 140 };
141 141
142 /** @method bind_events */
143 CodeCell.prototype.bind_events = function () {
144 IPython.Cell.prototype.bind_events.apply(this);
145 var that = this;
146
147 this.element.focusout(
148 function() { that.auto_highlight(); }
149 );
150 };
151
142 152 /**
143 153 * This method gets called in CodeMirror's onKeyDown/onKeyPress
144 154 * handlers and is used to provide custom key handling. Its return
@@ -308,44 +318,43 b' var IPython = (function (IPython) {'
308 318 // Basic cell manipulation.
309 319
310 320 CodeCell.prototype.select = function () {
311 var continue = IPython.Cell.prototype.select.apply(this);
312 if (continue) {
321 var cont = IPython.Cell.prototype.select.apply(this);
322 console.log('CodeCell.select', cont);
323 if (cont) {
313 324 this.code_mirror.refresh();
314 325 this.auto_highlight();
315 326 };
316 return continue;
327 return cont;
317 328 };
318 329
319 330 CodeCell.prototype.render = function () {
320 var continue = IPython.Cell.prototype.render.apply(this);
321 if (continue) {
322 this.execute();
323 };
324 return continue;
331 var cont = IPython.Cell.prototype.render.apply(this);
332 console.log('CodeCell.render');
333 // Always execute, even if we are already in the rendered state
334 return cont;
325 335 };
326
336
327 337 CodeCell.prototype.unrender = function () {
328 var continue = IPython.Cell.prototype.unrender.apply(this);
329 if (continue) {
330 this.clear_output(true, true, true);
331 };
332 return continue;
338 // CodeCell is always rendered
339 return false;
333 340 };
334 341
335 342 CodeCell.prototype.command_mode = function () {
336 var continue = IPython.Cell.prototype.command_mode.apply(this);
337 if (continue) {
343 var cont = IPython.Cell.prototype.command_mode.apply(this);
344 console.log('CodeCell.command_mode');
345 if (cont) {
338 346 this.focus_cell();
339 347 };
340 return continue;
348 return cont;
341 349 }
342 350
343 351 CodeCell.prototype.edit_mode = function () {
344 var continue = IPython.Cell.prototype.edit_mode.apply(this);
345 if (continue) {
352 var cont = IPython.Cell.prototype.edit_mode.apply(this);
353 console.log('CodeCell.edit_mode');
354 if (cont) {
346 355 this.focus_editor();
347 356 };
348 return continue;
357 return cont;
349 358 }
350 359
351 360 CodeCell.prototype.select_all = function () {
@@ -39,6 +39,8 b' var IPython = (function (IPython) {'
39 39 this.undelete_index = null;
40 40 this.undelete_below = false;
41 41 this.paste_enabled = false;
42 this.mode = 'command';
43 this.edit_index = null;
42 44 this.set_dirty(false);
43 45 this.metadata = {};
44 46 this._checkpoint_after_save = false;
@@ -74,7 +76,7 b' var IPython = (function (IPython) {'
74 76 * @method baseProjectUrl
75 77 * @return {String} The base project URL
76 78 */
77 Notebook.prototype.baseProjectUrl = function(){
79 Notebook.prototype.baseProjectUrl = function() {
78 80 return this._baseProjectUrl || $('body').data('baseProjectUrl');
79 81 };
80 82
@@ -131,6 +133,12 b' var IPython = (function (IPython) {'
131 133 var index = that.find_cell_index(data.cell);
132 134 that.select(index);
133 135 });
136
137 $([IPython.events]).on('edit_mode.Cell', function (event, data) {
138 var index = that.find_cell_index(data.cell);
139 that.select(index);
140 that.edit_mode();
141 });
134 142
135 143 $([IPython.events]).on('status_autorestarting.Kernel', function () {
136 144 IPython.dialog.modal({
@@ -144,220 +152,222 b' var IPython = (function (IPython) {'
144 152 });
145 153 });
146 154
147
148 155 $(document).keydown(function (event) {
149 156
150 // Save (CTRL+S) or (AppleKey+S)
151 //metaKey = applekey on mac
157 // Event handlers for both command and edit mode
152 158 if ((event.ctrlKey || event.metaKey) && event.keyCode==83) {
159 // Save (CTRL+S) or (Command+S on Mac)
153 160 that.save_checkpoint();
154 161 event.preventDefault();
155 162 return false;
156 163 } else if (event.which === key.ESC) {
157 164 // Intercept escape at highest level to avoid closing
158 165 // websocket connection with firefox
159 IPython.pager.collapse();
160 166 event.preventDefault();
167 // Don't return yet to allow edit/command modes to handle
161 168 } else if (event.which === key.SHIFT) {
162 169 // ignore shift keydown
163 170 return true;
164 }
165 if (event.which === key.UPARROW && !event.shiftKey) {
166 var cell = that.get_selected_cell();
167 if (cell && cell.at_top()) {
168 event.preventDefault();
169 that.select_prev();
170 };
171 } else if (event.which === key.DOWNARROW && !event.shiftKey) {
172 var cell = that.get_selected_cell();
173 if (cell && cell.at_bottom()) {
174 event.preventDefault();
175 that.select_next();
176 };
177 171 } else if (event.which === key.ENTER && event.shiftKey) {
178 that.execute_selected_cell();
172 that.execute_selected_cell('shift');
179 173 return false;
180 174 } else if (event.which === key.ENTER && event.altKey) {
181 175 // Execute code cell, and insert new in place
182 that.execute_selected_cell();
183 // Only insert a new cell, if we ended up in an already populated cell
184 if (/\S/.test(that.get_selected_cell().get_text()) == true) {
185 that.insert_cell_above('code');
186 }
176 that.execute_selected_cell('alt');
187 177 return false;
188 178 } else if (event.which === key.ENTER && event.ctrlKey) {
189 that.execute_selected_cell({terminal:true});
190 return false;
191 } else if (event.which === 77 && event.ctrlKey && that.control_key_active == false) {
192 that.control_key_active = true;
193 return false;
194 } else if (event.which === 88 && that.control_key_active) {
195 // Cut selected cell = x
196 that.cut_cell();
197 that.control_key_active = false;
198 return false;
199 } else if (event.which === 67 && that.control_key_active) {
200 // Copy selected cell = c
201 that.copy_cell();
202 that.control_key_active = false;
203 return false;
204 } else if (event.which === 86 && that.control_key_active) {
205 // Paste below selected cell = v
206 that.paste_cell_below();
207 that.control_key_active = false;
208 return false;
209 } else if (event.which === 68 && that.control_key_active) {
210 // Delete selected cell = d
211 that.delete_cell();
212 that.control_key_active = false;
213 return false;
214 } else if (event.which === 65 && that.control_key_active) {
215 // Insert code cell above selected = a
216 that.insert_cell_above('code');
217 that.control_key_active = false;
218 return false;
219 } else if (event.which === 66 && that.control_key_active) {
220 // Insert code cell below selected = b
221 that.insert_cell_below('code');
222 that.control_key_active = false;
223 return false;
224 } else if (event.which === 89 && that.control_key_active) {
225 // To code = y
226 that.to_code();
227 that.control_key_active = false;
228 return false;
229 } else if (event.which === 77 && that.control_key_active) {
230 // To markdown = m
231 that.to_markdown();
232 that.control_key_active = false;
233 return false;
234 } else if (event.which === 84 && that.control_key_active) {
235 // To Raw = t
236 that.to_raw();
237 that.control_key_active = false;
179 that.execute_selected_cell('ctrl');
238 180 return false;
239 } else if (event.which === 49 && that.control_key_active) {
240 // To Heading 1 = 1
241 that.to_heading(undefined, 1);
242 that.control_key_active = false;
243 return false;
244 } else if (event.which === 50 && that.control_key_active) {
245 // To Heading 2 = 2
246 that.to_heading(undefined, 2);
247 that.control_key_active = false;
248 return false;
249 } else if (event.which === 51 && that.control_key_active) {
250 // To Heading 3 = 3
251 that.to_heading(undefined, 3);
252 that.control_key_active = false;
253 return false;
254 } else if (event.which === 52 && that.control_key_active) {
255 // To Heading 4 = 4
256 that.to_heading(undefined, 4);
257 that.control_key_active = false;
258 return false;
259 } else if (event.which === 53 && that.control_key_active) {
260 // To Heading 5 = 5
261 that.to_heading(undefined, 5);
262 that.control_key_active = false;
263 return false;
264 } else if (event.which === 54 && that.control_key_active) {
265 // To Heading 6 = 6
266 that.to_heading(undefined, 6);
267 that.control_key_active = false;
268 return false;
269 } else if (event.which === 79 && that.control_key_active) {
270 // Toggle output = o
271 if (event.shiftKey){
272 that.toggle_output_scroll();
273 } else {
274 that.toggle_output();
275 }
276 that.control_key_active = false;
277 return false;
278 } else if (event.which === 83 && that.control_key_active) {
279 // Save notebook = s
280 that.save_checkpoint();
281 that.control_key_active = false;
282 return false;
283 } else if (event.which === 74 && that.control_key_active) {
284 // Move cell down = j
285 that.move_cell_down();
286 that.control_key_active = false;
287 return false;
288 } else if (event.which === 75 && that.control_key_active) {
289 // Move cell up = k
290 that.move_cell_up();
291 that.control_key_active = false;
292 return false;
293 } else if (event.which === 80 && that.control_key_active) {
294 // Select previous = p
295 that.select_prev();
296 that.control_key_active = false;
297 return false;
298 } else if (event.which === 78 && that.control_key_active) {
299 // Select next = n
300 that.select_next();
301 that.control_key_active = false;
302 return false;
303 } else if (event.which === 76 && that.control_key_active) {
304 // Toggle line numbers = l
305 that.cell_toggle_line_numbers();
306 that.control_key_active = false;
307 return false;
308 } else if (event.which === 73 && that.control_key_active) {
309 // Interrupt kernel = i
310 that.session.interrupt_kernel();
311 that.control_key_active = false;
312 return false;
313 } else if (event.which === 190 && that.control_key_active) {
314 // Restart kernel = . # matches qt console
315 that.restart_kernel();
316 that.control_key_active = false;
317 return false;
318 } else if (event.which === 72 && that.control_key_active) {
319 // Show keyboard shortcuts = h
320 IPython.quick_help.show_keyboard_shortcuts();
321 that.control_key_active = false;
322 return false;
323 } else if (event.which === 90 && that.control_key_active) {
324 // Undo last cell delete = z
325 that.undelete();
326 that.control_key_active = false;
327 return false;
328 } else if ((event.which === 189 || event.which === 173) &&
329 that.control_key_active) {
330 // how fun! '-' is 189 in Chrome, but 173 in FF and Opera
331 // Split cell = -
332 that.split_cell();
333 that.control_key_active = false;
334 return false;
335 } else if (that.control_key_active) {
336 that.control_key_active = false;
337 return true;
338 181 }
182
183 // Event handlers for edit mode
184 if (that.mode === 'edit') {
185 if (event.which === key.ESC) {
186 // ESC
187 that.command_mode();
188 return false;
189 } else if (event.which === 77 && event.ctrlKey) {
190 // Ctrl-m
191 that.command_mode();
192 return false;
193 } else if (event.which === key.UPARROW && !event.shiftKey) {
194 var cell = that.get_selected_cell();
195 if (cell && cell.at_top()) {
196 event.preventDefault();
197 that.command_mode()
198 that.select_prev();
199 that.edit_mode();
200 return false;
201 };
202 } else if (event.which === key.DOWNARROW && !event.shiftKey) {
203 var cell = that.get_selected_cell();
204 if (cell && cell.at_bottom()) {
205 event.preventDefault();
206 that.command_mode()
207 that.select_next();
208 that.edit_mode();
209 return false;
210 };
211 };
212 // Event handlers for command mode
213 } else if (that.mode === 'command' && !(event.ctrlKey || event.altKey)) {
214 if (event.which === key.ENTER && !(event.ctrlKey || event.altKey || event.shiftKey)) {
215 // Enter edit mode = ENTER alone
216 that.edit_mode();
217 return false
218 } else if (event.which === key.UPARROW && !event.shiftKey) {
219 var index = that.get_selected_index();
220 if (index !== 0 && index !== null) {
221 that.select_prev();
222 var cell = that.get_selected_cell();
223 cell.focus_cell();
224 };
225 return false;
226 } else if (event.which === key.DOWNARROW && !event.shiftKey) {
227 var index = that.get_selected_index();
228 if (index !== (that.ncells()-1) && index !== null) {
229 that.select_next();
230 var cell = that.get_selected_cell();
231 cell.focus_cell();
232 };
233 return false;
234 } else if (event.which === 88) {
235 // Cut selected cell = x
236 that.cut_cell();
237 return false;
238 } else if (event.which === 67) {
239 // Copy selected cell = c
240 that.copy_cell();
241 return false;
242 } else if (event.which === 86) {
243 // Paste below selected cell = v
244 that.paste_cell_below();
245 return false;
246 } else if (event.which === 68) {
247 // Delete selected cell = d
248 that.delete_cell();
249 return false;
250 } else if (event.which === 65) {
251 // Insert code cell above selected = a
252 that.insert_cell_above('code');
253 that.select_prev();
254 return false;
255 } else if (event.which === 66) {
256 // Insert code cell below selected = b
257 that.insert_cell_below('code');
258 that.select_next();
259 return false;
260 } else if (event.which === 89) {
261 // To code = y
262 that.to_code();
263 return false;
264 } else if (event.which === 77) {
265 // To markdown = m
266 that.to_markdown();
267 return false;
268 } else if (event.which === 84) {
269 // To Raw = t
270 that.to_raw();
271 return false;
272 } else if (event.which === 49) {
273 // To Heading 1 = 1
274 that.to_heading(undefined, 1);
275 return false;
276 } else if (event.which === 50) {
277 // To Heading 2 = 2
278 that.to_heading(undefined, 2);
279 return false;
280 } else if (event.which === 51) {
281 // To Heading 3 = 3
282 that.to_heading(undefined, 3);
283 return false;
284 } else if (event.which === 52) {
285 // To Heading 4 = 4
286 that.to_heading(undefined, 4);
287 return false;
288 } else if (event.which === 53) {
289 // To Heading 5 = 5
290 that.to_heading(undefined, 5);
291 return false;
292 } else if (event.which === 54) {
293 // To Heading 6 = 6
294 that.to_heading(undefined, 6);
295 return false;
296 } else if (event.which === 79) {
297 // Toggle output = o
298 if (event.shiftKey) {
299 that.toggle_output_scroll();
300 } else {
301 that.toggle_output();
302 };
303 return false;
304 } else if (event.which === 83) {
305 // Save notebook = s
306 that.save_checkpoint();
307 that.control_key_active = false;
308 return false;
309 } else if (event.which === 74) {
310 // Move cell down = j
311 that.move_cell_down();
312 return false;
313 } else if (event.which === 75) {
314 // Move cell up = k
315 that.move_cell_up();
316 return false;
317 } else if (event.which === 80) {
318 // Select previous = p
319 that.select_prev();
320 return false;
321 } else if (event.which === 78) {
322 // Select next = n
323 that.select_next();
324 return false;
325 } else if (event.which === 76) {
326 // Toggle line numbers = l
327 that.cell_toggle_line_numbers();
328 return false;
329 } else if (event.which === 73) {
330 // Interrupt kernel = i
331 that.kernel.interrupt();
332 return false;
333 } else if (event.which === 190) {
334 // Restart kernel = . # matches qt console
335 that.restart_kernel();
336 return false;
337 } else if (event.which === 72) {
338 // Show keyboard shortcuts = h
339 IPython.quick_help.show_keyboard_shortcuts();
340 return false;
341 } else if (event.which === 90) {
342 // Undo last cell delete = z
343 that.undelete();
344 return false;
345 };
346 };
347
348 // If we havn't handled it, let someone else.
339 349 return true;
340 350 });
341 351
342 var collapse_time = function(time){
352 var collapse_time = function (time) {
343 353 var app_height = $('#ipython-main-app').height(); // content height
344 354 var splitter_height = $('div#pager_splitter').outerHeight(true);
345 355 var new_height = app_height - splitter_height;
346 356 that.element.animate({height : new_height + 'px'}, time);
347 }
357 };
348 358
349 this.element.bind('collapse_pager', function (event,extrap) {
359 this.element.bind('collapse_pager', function (event, extrap) {
350 360 var time = (extrap != undefined) ? ((extrap.duration != undefined ) ? extrap.duration : 'fast') : 'fast';
351 361 collapse_time(time);
352 362 });
353 363
354 var expand_time = function(time) {
364 var expand_time = function (time) {
355 365 var app_height = $('#ipython-main-app').height(); // content height
356 366 var splitter_height = $('div#pager_splitter').outerHeight(true);
357 367 var pager_height = $('div#pager').outerHeight(true);
358 368 var new_height = app_height - pager_height - splitter_height;
359 369 that.element.animate({height : new_height + 'px'}, time);
360 }
370 };
361 371
362 372 this.element.bind('expand_pager', function (event, extrap) {
363 373 var time = (extrap != undefined) ? ((extrap.duration != undefined ) ? extrap.duration : 'fast') : 'fast';
@@ -653,6 +663,7 b' var IPython = (function (IPython) {'
653 663 this.get_cell(sindex).unselect();
654 664 };
655 665 var cell = this.get_cell(index);
666 console.log('Notebook.select', index);
656 667 cell.select();
657 668 if (cell.cell_type === 'heading') {
658 669 $([IPython.events]).trigger('selected_cell_type_changed.Notebook',
@@ -692,6 +703,48 b' var IPython = (function (IPython) {'
692 703 };
693 704
694 705
706 // Edit/Command mode
707
708 /**
709 * Enter command mode for the currently selected cell
710 *
711 * @method command_mode
712 */
713 Notebook.prototype.command_mode = function () {
714 console.log('Notebook.command_mode', this.mode, this.edit_index);
715 if (this.mode !== 'command') {
716 var cell = this.get_cell(this.edit_index);
717 if (cell) {
718 cell.command_mode();
719 this.mode = 'command';
720 this.edit_index = null;
721 };
722 };
723 };
724
725 /**
726 * Enter edit mode for the currently selected cell
727 *
728 * @method editmode
729 */
730 Notebook.prototype.edit_mode = function () {
731 var index = this.get_selected_index();
732 console.log('Notebook.edit_mode', this.mode, index);
733 if (index !== this.edit_index) {
734 if (this.edit_index !== null) {
735 var old_cell = this.get_cell(this.edit_index)
736 old_cell.command_mode();
737 }
738 var cell = this.get_cell(index);
739 if (cell) {
740 cell.edit_mode();
741 this.mode = 'edit';
742 this.edit_index = index;
743 };
744 };
745 };
746
747
695 748 // Cell movement
696 749
697 750 /**
@@ -804,10 +857,12 b' var IPython = (function (IPython) {'
804 857 cell = new IPython.HeadingCell();
805 858 }
806 859
807 if(this._insert_element_at_index(cell.element,index)){
860 if(this._insert_element_at_index(cell.element,index)) {
808 861 cell.render();
809 this.select(this.find_cell_index(cell));
810 862 $([IPython.events]).trigger('create.Cell', {'cell': cell, 'index': index});
863 cell.refresh();
864 // TODO: should we really get rid of this?
865 //this.select(this.find_cell_index(cell));
811 866 this.set_dirty(true);
812 867 }
813 868 }
@@ -952,6 +1007,8 b' var IPython = (function (IPython) {'
952 1007 // to this state, instead of a blank cell
953 1008 target_cell.code_mirror.clearHistory();
954 1009 source_element.remove();
1010 this.select(i);
1011 this.edit_mode();
955 1012 this.set_dirty(true);
956 1013 };
957 1014 };
@@ -1440,31 +1497,41 b' var IPython = (function (IPython) {'
1440 1497 * @method execute_selected_cell
1441 1498 * @param {Object} options Customize post-execution behavior
1442 1499 */
1443 Notebook.prototype.execute_selected_cell = function (options) {
1444 // add_new: should a new cell be added if we are at the end of the nb
1445 // terminal: execute in terminal mode, which stays in the current cell
1446 var default_options = {terminal: false, add_new: true};
1447 $.extend(default_options, options);
1500 Notebook.prototype.execute_selected_cell = function (mode) {
1501 // mode = shift, ctrl, alt
1502 mode = mode || 'shift'
1448 1503 var that = this;
1449 1504 var cell = that.get_selected_cell();
1450 1505 var cell_index = that.find_cell_index(cell);
1451 if (cell instanceof IPython.CodeCell) {
1452 cell.execute();
1453 }
1454 if (default_options.terminal) {
1455 cell.select_all();
1456 } else {
1457 if ((cell_index === (that.ncells()-1)) && default_options.add_new) {
1506
1507 cell.execute();
1508 console.log('Notebook.execute_selected_cell', mode);
1509 if (mode === 'shift') {
1510 if (cell_index === (that.ncells()-1)) {
1458 1511 that.insert_cell_below('code');
1459 // If we are adding a new cell at the end, scroll down to show it.
1512 that.select(cell_index+1);
1513 that.edit_mode();
1460 1514 that.scroll_to_bottom();
1461 1515 } else {
1462 that.select(cell_index+1);
1463 };
1464 };
1516 that.command_mode();
1517 }
1518 } else if (mode === 'ctrl') {
1519 that.select(cell_index+1);
1520 that.get_cell(cell_index+1).focus_cell();
1521 } else if (mode === 'alt') {
1522 // Only insert a new cell, if we ended up in an already populated cell
1523 if (/\S/.test(that.get_next_cell().get_text()) == true) {
1524 that.insert_cell_below('code');
1525 }
1526 var next_index = cell_index+1;
1527 that.select(cell_index+1);
1528 that.edit_mode();
1529 }
1530
1465 1531 this.set_dirty(true);
1466 1532 };
1467 1533
1534
1468 1535 /**
1469 1536 * Execute all cells below the selected cell.
1470 1537 *
@@ -1909,9 +1976,13 b' var IPython = (function (IPython) {'
1909 1976 this.fromJSON(data);
1910 1977 if (this.ncells() === 0) {
1911 1978 this.insert_cell_below('code');
1979 this.select(0);
1980 this.edit_mode();
1981 } else {
1982 this.select(0);
1983 this.command_mode();
1912 1984 };
1913 1985 this.set_dirty(false);
1914 this.select(0);
1915 1986 this.scroll_to_top();
1916 1987 if (data.orig_nbformat !== undefined && data.nbformat !== data.orig_nbformat) {
1917 1988 var msg = "This notebook has been converted from an older " +
@@ -64,7 +64,6 b' var IPython = (function (IPython) {'
64 64 };
65 65
66 66
67
68 67 /**
69 68 * Create the DOM element of the TextCell
70 69 * @method create_element
@@ -101,6 +100,8 b' var IPython = (function (IPython) {'
101 100 TextCell.prototype.bind_events = function () {
102 101 IPython.Cell.prototype.bind_events.apply(this);
103 102 var that = this;
103
104 // TODO: move this to the notebook event handler
104 105 this.element.keydown(function (event) {
105 106 if (event.which === 13 && !event.shiftKey) {
106 107 if (that.rendered) {
@@ -109,11 +110,13 b' var IPython = (function (IPython) {'
109 110 };
110 111 };
111 112 });
113
112 114 this.element.dblclick(function () {
113 115 that.unrender();
114 116 });
115 117 };
116 118
119
117 120 /**
118 121 * This method gets called in CodeMirror's onKeyDown/onKeyPress
119 122 * handlers and is used to provide custom key handling.
@@ -126,38 +129,34 b' var IPython = (function (IPython) {'
126 129 * @return {Boolean} `true` if CodeMirror should ignore the event, `false` Otherwise
127 130 */
128 131 TextCell.prototype.handle_codemirror_keyevent = function (editor, event) {
129
130 if (event.keyCode === 13 && (event.shiftKey || event.ctrlKey)) {
131 // Always ignore shift-enter in CodeMirror as we handle it.
132 return true;
133 }
132 if (this.mode === 'command') {
133 return false
134 } else if (this.mode === 'edit') {
135 if (event.keyCode === 13 && (event.shiftKey || event.ctrlKey)) {
136 // Always ignore shift-enter in CodeMirror as we handle it.
137 return true;
138 };
139 return false;
140 };
134 141 return false;
135 142 };
136 143
137 144 // Cell level actions
138 145
139 146 TextCell.prototype.select = function () {
140 var continue = IPython.Cell.prototype.select.apply(this);
141 if (continue) {
147 var cont = IPython.Cell.prototype.select.apply(this);
148 if (cont) {
142 149 if (this.mode === 'edit') {
143 150 this.code_mirror.refresh();
144 151 }
145 152 };
146 return continue;
147 };
148
149 TextCell.prototype.render = function () {
150 var continue = IPython.Cell.prototype.render.apply(this);
151 if (continue) {
152 this.execute();
153 };
154 return continue;
153 return cont;
155 154 };
156 155
157 156 TextCell.prototype.unrender = function () {
158 157 if (this.read_only) return;
159 var continue = IPython.Cell.prototype.unrender.apply(this);
160 if (continue) {
158 var cont = IPython.Cell.prototype.unrender.apply(this);
159 if (cont) {
161 160 var text_cell = this.element;
162 161 var output = text_cell.find("div.text_cell_render");
163 162 output.hide();
@@ -169,23 +168,27 b' var IPython = (function (IPython) {'
169 168 }
170 169
171 170 };
172 return continue;
171 return cont;
172 };
173
174 TextCell.prototype.execute = function () {
175 this.render();
173 176 };
174 177
175 178 TextCell.prototype.command_mode = function () {
176 var continue = IPython.Cell.prototype.command_mode.apply(this);
177 if (continue) {
179 var cont = IPython.Cell.prototype.command_mode.apply(this);
180 if (cont) {
178 181 this.focus_cell();
179 182 };
180 return continue;
183 return cont;
181 184 }
182 185
183 186 TextCell.prototype.edit_mode = function () {
184 var continue = IPython.Cell.prototype.edit_mode.apply(this);
185 if (continue) {
187 var cont = IPython.Cell.prototype.edit_mode.apply(this);
188 if (cont) {
186 189 this.focus_editor();
187 190 };
188 return continue;
191 return cont;
189 192 }
190 193
191 194 /**
@@ -224,36 +227,51 b' var IPython = (function (IPython) {'
224 227 };
225 228
226 229 /**
227 * not deprecated, but implementation wrong
228 230 * @method at_top
229 * @deprecated
230 * @return {Boolean} true is cell rendered, false otherwise
231 * I doubt this is what it is supposed to do
232 * this implementation is completly false
231 * @return {Boolean}
233 232 */
234 233 TextCell.prototype.at_top = function () {
235 234 if (this.rendered) {
236 235 return true;
237 236 } else {
238 return false;
239 }
237 if (cursor.line === 0 && cursor.ch === 0) {
238 return true;
239 } else {
240 return false;
241 };
242 };
240 243 };
241 244
242 245
246 /** @method at_bottom **/
247 TextCell.prototype.at_bottom = function () {
248 if (this.rendered) {
249 return true
250 } else {
251 var cursor = this.code_mirror.getCursor();
252 if (cursor.line === (this.code_mirror.lineCount()-1) && cursor.ch === this.code_mirror.getLine(cursor.line).length) {
253 return true;
254 } else {
255 return false;
256 };
257 };
258 };
259
243 260 /**
244 * not deprecated, but implementation wrong
245 261 * @method at_bottom
246 * @deprecated
247 * @return {Boolean} true is cell rendered, false otherwise
248 * I doubt this is what it is supposed to do
249 * this implementation is completly false
262 * @return {Boolean}
250 263 * */
251 264 TextCell.prototype.at_bottom = function () {
252 265 if (this.rendered) {
253 266 return true;
254 267 } else {
255 return false;
256 }
268 var cursor = this.code_mirror.getCursor();
269 if (cursor.line === (this.code_mirror.lineCount()-1) && cursor.ch === this.code_mirror.getLine(cursor.line).length) {
270 return true;
271 } else {
272 return false;
273 };
274 };
257 275 };
258 276
259 277 /**
@@ -308,16 +326,14 b' var IPython = (function (IPython) {'
308 326 placeholder: "Type *Markdown* and LaTeX: $\\alpha^2$"
309 327 }
310 328
311
312
313
314 329 MarkdownCell.prototype = new TextCell();
315 330
316 331 /**
317 332 * @method render
318 333 */
319 334 MarkdownCell.prototype.render = function () {
320 if (this.rendered === false) {
335 var cont = IPython.TextCell.prototype.render.apply(this);
336 if (cont) {
321 337 var text = this.get_text();
322 338 var math = null;
323 339 if (text === "") { text = this.placeholder; }
@@ -339,9 +355,9 b' var IPython = (function (IPython) {'
339 355 }
340 356 this.element.find('div.text_cell_input').hide();
341 357 this.element.find("div.text_cell_render").show();
342 this.typeset();
343 this.rendered = true;
344 }
358 this.typeset()
359 };
360 return cont;
345 361 };
346 362
347 363
@@ -357,11 +373,6 b' var IPython = (function (IPython) {'
357 373
358 374 this.cell_type = 'raw';
359 375 TextCell.apply(this, [options]);
360
361 var that = this;
362 this.element.focusout(
363 function() { that.auto_highlight(); }
364 );
365 376 };
366 377
367 378 RawCell.options_default = {
@@ -370,10 +381,17 b' var IPython = (function (IPython) {'
370 381 "When passing through nbconvert, a Raw Cell's content is added to the output unmodified."
371 382 };
372 383
373
374
375 384 RawCell.prototype = new TextCell();
376 385
386 /** @method bind_events **/
387 RawCell.prototype.bind_events = function () {
388 TextCell.prototype.bind_events.apply(this);
389 var that = this
390 this.element.focusout(function() {
391 that.auto_highlight();
392 });
393 };
394
377 395 /**
378 396 * Trigger autodetection of highlight scheme for current cell
379 397 * @method auto_highlight
@@ -384,12 +402,13 b' var IPython = (function (IPython) {'
384 402
385 403 /** @method render **/
386 404 RawCell.prototype.render = function () {
387
388 this.rendered = true;
405 // Make sure that this cell type can never be rendered
406 if (this.rendered) {
407 this.unrender();
408 }
389 409 var text = this.get_text();
390 410 if (text === "") { text = this.placeholder; }
391 411 this.set_text(text);
392 this.unrender();
393 412 };
394 413
395 414
@@ -397,55 +416,34 b' var IPython = (function (IPython) {'
397 416 RawCell.prototype.handle_codemirror_keyevent = function (editor, event) {
398 417
399 418 var that = this;
400 if (event.which === key.UPARROW && event.type === 'keydown') {
401 // If we are not at the top, let CM handle the up arrow and
402 // prevent the global keydown handler from handling it.
403 if (!that.at_top()) {
404 event.stop();
405 return false;
406 } else {
407 return true;
408 };
409 } else if (event.which === key.DOWNARROW && event.type === 'keydown') {
410 // If we are not at the bottom, let CM handle the down arrow and
411 // prevent the global keydown handler from handling it.
412 if (!that.at_bottom()) {
413 event.stop();
414 return false;
415 } else {
416 return true;
419 if (this.mode === 'command') {
420 return false
421 } else if (this.mode === 'edit') {
422 // TODO: review these handlers...
423 if (event.which === key.UPARROW && event.type === 'keydown') {
424 // If we are not at the top, let CM handle the up arrow and
425 // prevent the global keydown handler from handling it.
426 if (!that.at_top()) {
427 event.stop();
428 return false;
429 } else {
430 return true;
431 };
432 } else if (event.which === key.DOWNARROW && event.type === 'keydown') {
433 // If we are not at the bottom, let CM handle the down arrow and
434 // prevent the global keydown handler from handling it.
435 if (!that.at_bottom()) {
436 event.stop();
437 return false;
438 } else {
439 return true;
440 };
417 441 };
442 return false;
418 443 };
419 444 return false;
420 445 };
421 446
422 /** @method select **/
423 RawCell.prototype.select = function () {
424 IPython.Cell.prototype.select.apply(this);
425 this.edit();
426 };
427
428 /** @method at_top **/
429 RawCell.prototype.at_top = function () {
430 var cursor = this.code_mirror.getCursor();
431 if (cursor.line === 0 && cursor.ch === 0) {
432 return true;
433 } else {
434 return false;
435 }
436 };
437
438
439 /** @method at_bottom **/
440 RawCell.prototype.at_bottom = function () {
441 var cursor = this.code_mirror.getCursor();
442 if (cursor.line === (this.code_mirror.lineCount()-1) && cursor.ch === this.code_mirror.getLine(cursor.line).length) {
443 return true;
444 } else {
445 return false;
446 }
447 };
448
449 447
450 448 /**
451 449 * @class HeadingCell
@@ -541,7 +539,8 b' var IPython = (function (IPython) {'
541 539
542 540
543 541 HeadingCell.prototype.render = function () {
544 if (this.rendered === false) {
542 var cont = IPython.TextCell.prototype.render.apply(this);
543 if (cont) {
545 544 var text = this.get_text();
546 545 var math = null;
547 546 // Markdown headings must be a single line
@@ -567,8 +566,9 b' var IPython = (function (IPython) {'
567 566 this.typeset();
568 567 this.element.find('div.text_cell_input').hide();
569 568 this.element.find("div.text_cell_render").show();
570 this.rendered = true;
569
571 570 };
571 return cont;
572 572 };
573 573
574 574 IPython.TextCell = TextCell;
@@ -6,6 +6,14 b' div.cell {'
6 6 .corner-all;
7 7 border : thin @border_color solid;
8 8 }
9
10 &.edit_mode {
11 .corner-all;
12 border : thin green solid;
13 }
14 }
15
16 div.cell {
9 17 width: 100%;
10 18 padding: 5px 5px 5px 0px;
11 19 /* This acts as a spacer between cells, that is outside the border */
@@ -54,7 +54,9 b' input.engine_num_input{height:20px;margin-bottom:2px;padding-top:0;padding-botto'
54 54 .ansibgpurple{background-color:magenta;}
55 55 .ansibgcyan{background-color:cyan;}
56 56 .ansibggray{background-color:gray;}
57 div.cell{border:1px solid transparent;display:-webkit-box;-webkit-box-orient:vertical;-webkit-box-align:stretch;display:-moz-box;-moz-box-orient:vertical;-moz-box-align:stretch;display:box;box-orient:vertical;box-align:stretch;width:100%;padding:5px 5px 5px 0px;margin:0px;outline:none;}div.cell.selected{border-radius:4px;border:thin #ababab solid;}
57 div.cell{border:1px solid transparent;display:-webkit-box;-webkit-box-orient:vertical;-webkit-box-align:stretch;display:-moz-box;-moz-box-orient:vertical;-moz-box-align:stretch;display:box;box-orient:vertical;box-align:stretch;width:100%;}div.cell.selected{border-radius:4px;border:thin #ababab solid;}
58 div.cell.edit_mode{border-radius:4px;border:thin green solid;}
59 div.cell{width:100%;padding:5px 5px 5px 0px;margin:0px;outline:none;}
58 60 div.prompt{min-width:11ex;padding:0.4em;margin:0px;font-family:monospace;text-align:right;line-height:1.231em;}
59 61 div.inner_cell{display:-webkit-box;-webkit-box-orient:vertical;-webkit-box-align:stretch;display:-moz-box;-moz-box-orient:vertical;-moz-box-align:stretch;display:box;box-orient:vertical;box-align:stretch;width:100%;-webkit-box-flex:1;-moz-box-flex:1;box-flex:1;}
60 62 div.prompt:empty{padding-top:0;padding-bottom:0;}
@@ -1435,7 +1435,9 b' input.engine_num_input{height:20px;margin-bottom:2px;padding-top:0;padding-botto'
1435 1435 .ansibgpurple{background-color:magenta;}
1436 1436 .ansibgcyan{background-color:cyan;}
1437 1437 .ansibggray{background-color:gray;}
1438 div.cell{border:1px solid transparent;display:-webkit-box;-webkit-box-orient:vertical;-webkit-box-align:stretch;display:-moz-box;-moz-box-orient:vertical;-moz-box-align:stretch;display:box;box-orient:vertical;box-align:stretch;width:100%;padding:5px 5px 5px 0px;margin:0px;outline:none;}div.cell.selected{border-radius:4px;border:thin #ababab solid;}
1438 div.cell{border:1px solid transparent;display:-webkit-box;-webkit-box-orient:vertical;-webkit-box-align:stretch;display:-moz-box;-moz-box-orient:vertical;-moz-box-align:stretch;display:box;box-orient:vertical;box-align:stretch;width:100%;}div.cell.selected{border-radius:4px;border:thin #ababab solid;}
1439 div.cell.edit_mode{border-radius:4px;border:thin green solid;}
1440 div.cell{width:100%;padding:5px 5px 5px 0px;margin:0px;outline:none;}
1439 1441 div.prompt{min-width:11ex;padding:0.4em;margin:0px;font-family:monospace;text-align:right;line-height:1.231em;}
1440 1442 div.inner_cell{display:-webkit-box;-webkit-box-orient:vertical;-webkit-box-align:stretch;display:-moz-box;-moz-box-orient:vertical;-moz-box-align:stretch;display:box;box-orient:vertical;box-align:stretch;width:100%;-webkit-box-flex:1;-moz-box-flex:1;box-flex:1;}
1441 1443 div.prompt:empty{padding-top:0;padding-bottom:0;}
General Comments 0
You need to be logged in to leave comments. Login now