##// END OF EJS Templates
Fixed bug
Jonathan Frederic -
Show More
@@ -1,581 +1,573
1 //----------------------------------------------------------------------------
2 // Copyright (C) 2011 The IPython Development Team
3 //
4 // Distributed under the terms of the BSD License. The full license is in
5 // the file COPYING, distributed as part of this software.
6 //----------------------------------------------------------------------------
7
8 //============================================================================
9 // Keyboard management
10 //============================================================================
1 // Copyright (c) IPython Development Team.
2 // Distributed under the terms of the Modified BSD License.
11 3
12 4 var IPython = (function (IPython) {
13 5 "use strict";
14 6
15 7 var browser = utils.browser[0];
16 8 var platform = utils.platform;
17 9
18 10 // Main keyboard manager for the notebook
19 11 var keycodes = keyboard.keycodes;
20 12
21 13 var KeyboardManager = function (options) {
22 14 // Constructor
23 15 //
24 16 // Parameters:
25 17 // options: dictionary
26 18 // Dictionary of keyword arguments.
27 19 // events: $(Events) instance
28 20 // pager: Pager instance
29 21 this.mode = 'command';
30 22 this.enabled = true;
31 23 this.pager = options.pager;
32 24 this.quick_help = undefined;
33 25 this.notebook = undefined;
34 26 this.bind_events();
35 27 this.command_shortcuts = new keyboard.ShortcutManager(undefined, options.events);
36 28 this.command_shortcuts.add_shortcuts(this.get_default_common_shortcuts());
37 29 this.command_shortcuts.add_shortcuts(this.get_default_command_shortcuts());
38 30 this.edit_shortcuts = new keyboard.ShortcutManager(undefined, options.events);
39 31 this.edit_shortcuts.add_shortcuts(this.get_default_common_shortcuts());
40 32 this.edit_shortcuts.add_shortcuts(this.get_default_edit_shortcuts());
41 33 };
42 34
43 35 KeyboardManager.prototype.get_default_common_shortcuts = function() {
44 36 var that = this;
45 37 var shortcuts = {
46 38 'shift' : {
47 39 help : '',
48 40 help_index : '',
49 41 handler : function (event) {
50 42 // ignore shift keydown
51 43 return true;
52 44 }
53 45 },
54 46 'shift-enter' : {
55 47 help : 'run cell, select below',
56 48 help_index : 'ba',
57 49 handler : function (event) {
58 50 that.notebook.execute_cell_and_select_below();
59 51 return false;
60 52 }
61 53 },
62 54 'ctrl-enter' : {
63 55 help : 'run cell',
64 56 help_index : 'bb',
65 57 handler : function (event) {
66 58 that.notebook.execute_cell();
67 59 return false;
68 60 }
69 61 },
70 62 'alt-enter' : {
71 63 help : 'run cell, insert below',
72 64 help_index : 'bc',
73 65 handler : function (event) {
74 66 that.notebook.execute_cell_and_insert_below();
75 67 return false;
76 68 }
77 69 }
78 70 };
79 71
80 72 if (platform === 'MacOS') {
81 73 shortcuts['cmd-s'] =
82 74 {
83 75 help : 'save notebook',
84 76 help_index : 'fb',
85 77 handler : function (event) {
86 78 that.notebook.save_checkpoint();
87 79 event.preventDefault();
88 80 return false;
89 81 }
90 82 };
91 83 } else {
92 84 shortcuts['ctrl-s'] =
93 85 {
94 86 help : 'save notebook',
95 87 help_index : 'fb',
96 88 handler : function (event) {
97 89 that.notebook.save_checkpoint();
98 90 event.preventDefault();
99 91 return false;
100 92 }
101 93 };
102 94 }
103 95 return shortcuts;
104 96 };
105 97
106 98 KeyboardManager.prototype.get_default_edit_shortcuts = function() {
107 99 var that = this;
108 100 return {
109 101 'esc' : {
110 102 help : 'command mode',
111 103 help_index : 'aa',
112 104 handler : function (event) {
113 105 that.notebook.command_mode();
114 106 return false;
115 107 }
116 108 },
117 109 'ctrl-m' : {
118 110 help : 'command mode',
119 111 help_index : 'ab',
120 112 handler : function (event) {
121 113 that.notebook.command_mode();
122 114 return false;
123 115 }
124 116 },
125 117 'up' : {
126 118 help : '',
127 119 help_index : '',
128 120 handler : function (event) {
129 121 var index = that.notebook.get_selected_index();
130 122 var cell = that.notebook.get_cell(index);
131 123 if (cell && cell.at_top() && index !== 0) {
132 124 event.preventDefault();
133 125 that.notebook.command_mode();
134 126 that.notebook.select_prev();
135 127 that.notebook.edit_mode();
136 128 var cm = that.notebook.get_selected_cell().code_mirror;
137 129 cm.setCursor(cm.lastLine(), 0);
138 130 return false;
139 131 } else if (cell) {
140 132 var cm = cell.code_mirror;
141 133 cm.execCommand('goLineUp');
142 134 return false;
143 135 }
144 136 }
145 137 },
146 138 'down' : {
147 139 help : '',
148 140 help_index : '',
149 141 handler : function (event) {
150 142 var index = that.notebook.get_selected_index();
151 143 var cell = that.notebook.get_cell(index);
152 144 if (cell.at_bottom() && index !== (that.notebook.ncells()-1)) {
153 145 event.preventDefault();
154 146 that.notebook.command_mode();
155 147 that.notebook.select_next();
156 148 that.notebook.edit_mode();
157 149 var cm = that.notebook.get_selected_cell().code_mirror;
158 150 cm.setCursor(0, 0);
159 151 return false;
160 152 } else {
161 153 var cm = cell.code_mirror;
162 154 cm.execCommand('goLineDown');
163 155 return false;
164 156 }
165 157 }
166 158 },
167 159 'ctrl-shift--' : {
168 160 help : 'split cell',
169 161 help_index : 'ea',
170 162 handler : function (event) {
171 163 that.notebook.split_cell();
172 164 return false;
173 165 }
174 166 },
175 167 'ctrl-shift-subtract' : {
176 168 help : '',
177 169 help_index : 'eb',
178 170 handler : function (event) {
179 171 that.notebook.split_cell();
180 172 return false;
181 173 }
182 174 },
183 175 };
184 176 };
185 177
186 178 KeyboardManager.prototype.get_default_command_shortcuts = function() {
187 179 var that = this;
188 180 return {
189 181 'space': {
190 182 help: "Scroll down to next H1 cell",
191 183 handler: function(event) {
192 184 return that.notebook.scrollmanager.scroll(1);
193 185 },
194 186 },
195 187 'shift-space': {
196 188 help: "Scroll up to previous H1 cell",
197 189 handler: function(event) {
198 190 return that.notebook.scrollmanager.scroll(-1);
199 191 },
200 192 },
201 193 'enter' : {
202 194 help : 'edit mode',
203 195 help_index : 'aa',
204 196 handler : function (event) {
205 197 that.notebook.edit_mode();
206 198 return false;
207 199 }
208 200 },
209 201 'up' : {
210 202 help : 'select previous cell',
211 203 help_index : 'da',
212 204 handler : function (event) {
213 205 var index = that.notebook.get_selected_index();
214 206 if (index !== 0 && index !== null) {
215 207 that.notebook.select_prev();
216 208 that.notebook.focus_cell();
217 209 }
218 210 return false;
219 211 }
220 212 },
221 213 'down' : {
222 214 help : 'select next cell',
223 215 help_index : 'db',
224 216 handler : function (event) {
225 217 var index = that.notebook.get_selected_index();
226 218 if (index !== (that.notebook.ncells()-1) && index !== null) {
227 219 that.notebook.select_next();
228 220 that.notebook.focus_cell();
229 221 }
230 222 return false;
231 223 }
232 224 },
233 225 'k' : {
234 226 help : 'select previous cell',
235 227 help_index : 'dc',
236 228 handler : function (event) {
237 229 var index = that.notebook.get_selected_index();
238 230 if (index !== 0 && index !== null) {
239 231 that.notebook.select_prev();
240 232 that.notebook.focus_cell();
241 233 }
242 234 return false;
243 235 }
244 236 },
245 237 'j' : {
246 238 help : 'select next cell',
247 239 help_index : 'dd',
248 240 handler : function (event) {
249 241 var index = that.notebook.get_selected_index();
250 242 if (index !== (that.notebook.ncells()-1) && index !== null) {
251 243 that.notebook.select_next();
252 244 that.notebook.focus_cell();
253 245 }
254 246 return false;
255 247 }
256 248 },
257 249 'x' : {
258 250 help : 'cut cell',
259 251 help_index : 'ee',
260 252 handler : function (event) {
261 253 that.notebook.cut_cell();
262 254 return false;
263 255 }
264 256 },
265 257 'c' : {
266 258 help : 'copy cell',
267 259 help_index : 'ef',
268 260 handler : function (event) {
269 261 that.notebook.copy_cell();
270 262 return false;
271 263 }
272 264 },
273 265 'shift-v' : {
274 266 help : 'paste cell above',
275 267 help_index : 'eg',
276 268 handler : function (event) {
277 269 that.notebook.paste_cell_above();
278 270 return false;
279 271 }
280 272 },
281 273 'v' : {
282 274 help : 'paste cell below',
283 275 help_index : 'eh',
284 276 handler : function (event) {
285 277 that.notebook.paste_cell_below();
286 278 return false;
287 279 }
288 280 },
289 281 'd' : {
290 282 help : 'delete cell (press twice)',
291 283 help_index : 'ej',
292 284 count: 2,
293 285 handler : function (event) {
294 286 that.notebook.delete_cell();
295 287 return false;
296 288 }
297 289 },
298 290 'a' : {
299 291 help : 'insert cell above',
300 292 help_index : 'ec',
301 293 handler : function (event) {
302 294 that.notebook.insert_cell_above();
303 295 that.notebook.select_prev();
304 296 that.notebook.focus_cell();
305 297 return false;
306 298 }
307 299 },
308 300 'b' : {
309 301 help : 'insert cell below',
310 302 help_index : 'ed',
311 303 handler : function (event) {
312 304 that.notebook.insert_cell_below();
313 305 that.notebook.select_next();
314 306 that.notebook.focus_cell();
315 307 return false;
316 308 }
317 309 },
318 310 'y' : {
319 311 help : 'to code',
320 312 help_index : 'ca',
321 313 handler : function (event) {
322 314 that.notebook.to_code();
323 315 return false;
324 316 }
325 317 },
326 318 'm' : {
327 319 help : 'to markdown',
328 320 help_index : 'cb',
329 321 handler : function (event) {
330 322 that.notebook.to_markdown();
331 323 return false;
332 324 }
333 325 },
334 326 'r' : {
335 327 help : 'to raw',
336 328 help_index : 'cc',
337 329 handler : function (event) {
338 330 that.notebook.to_raw();
339 331 return false;
340 332 }
341 333 },
342 334 '1' : {
343 335 help : 'to heading 1',
344 336 help_index : 'cd',
345 337 handler : function (event) {
346 338 that.notebook.to_heading(undefined, 1);
347 339 return false;
348 340 }
349 341 },
350 342 '2' : {
351 343 help : 'to heading 2',
352 344 help_index : 'ce',
353 345 handler : function (event) {
354 346 that.notebook.to_heading(undefined, 2);
355 347 return false;
356 348 }
357 349 },
358 350 '3' : {
359 351 help : 'to heading 3',
360 352 help_index : 'cf',
361 353 handler : function (event) {
362 354 that.notebook.to_heading(undefined, 3);
363 355 return false;
364 356 }
365 357 },
366 358 '4' : {
367 359 help : 'to heading 4',
368 360 help_index : 'cg',
369 361 handler : function (event) {
370 362 that.notebook.to_heading(undefined, 4);
371 363 return false;
372 364 }
373 365 },
374 366 '5' : {
375 367 help : 'to heading 5',
376 368 help_index : 'ch',
377 369 handler : function (event) {
378 370 that.notebook.to_heading(undefined, 5);
379 371 return false;
380 372 }
381 373 },
382 374 '6' : {
383 375 help : 'to heading 6',
384 376 help_index : 'ci',
385 377 handler : function (event) {
386 378 that.notebook.to_heading(undefined, 6);
387 379 return false;
388 380 }
389 381 },
390 382 'o' : {
391 383 help : 'toggle output',
392 384 help_index : 'gb',
393 385 handler : function (event) {
394 386 that.notebook.toggle_output();
395 387 return false;
396 388 }
397 389 },
398 390 'shift-o' : {
399 391 help : 'toggle output scrolling',
400 392 help_index : 'gc',
401 393 handler : function (event) {
402 394 that.notebook.toggle_output_scroll();
403 395 return false;
404 396 }
405 397 },
406 398 's' : {
407 399 help : 'save notebook',
408 400 help_index : 'fa',
409 401 handler : function (event) {
410 402 that.notebook.save_checkpoint();
411 403 return false;
412 404 }
413 405 },
414 406 'ctrl-j' : {
415 407 help : 'move cell down',
416 408 help_index : 'eb',
417 409 handler : function (event) {
418 410 that.notebook.move_cell_down();
419 411 return false;
420 412 }
421 413 },
422 414 'ctrl-k' : {
423 415 help : 'move cell up',
424 416 help_index : 'ea',
425 417 handler : function (event) {
426 418 that.notebook.move_cell_up();
427 419 return false;
428 420 }
429 421 },
430 422 'l' : {
431 423 help : 'toggle line numbers',
432 424 help_index : 'ga',
433 425 handler : function (event) {
434 426 that.notebook.cell_toggle_line_numbers();
435 427 return false;
436 428 }
437 429 },
438 430 'i' : {
439 431 help : 'interrupt kernel (press twice)',
440 432 help_index : 'ha',
441 433 count: 2,
442 434 handler : function (event) {
443 435 that.notebook.kernel.interrupt();
444 436 return false;
445 437 }
446 438 },
447 439 '0' : {
448 440 help : 'restart kernel (press twice)',
449 441 help_index : 'hb',
450 442 count: 2,
451 443 handler : function (event) {
452 444 that.notebook.restart_kernel();
453 445 return false;
454 446 }
455 447 },
456 448 'h' : {
457 449 help : 'keyboard shortcuts',
458 450 help_index : 'ge',
459 451 handler : function (event) {
460 452 that.quick_help.show_keyboard_shortcuts();
461 453 return false;
462 454 }
463 455 },
464 456 'z' : {
465 457 help : 'undo last delete',
466 458 help_index : 'ei',
467 459 handler : function (event) {
468 460 that.notebook.undelete_cell();
469 461 return false;
470 462 }
471 463 },
472 464 'shift-m' : {
473 465 help : 'merge cell below',
474 466 help_index : 'ek',
475 467 handler : function (event) {
476 468 that.notebook.merge_cell_below();
477 469 return false;
478 470 }
479 471 },
480 472 'q' : {
481 473 help : 'close pager',
482 474 help_index : 'gd',
483 475 handler : function (event) {
484 476 that.pager.collapse();
485 477 return false;
486 478 }
487 479 },
488 480 };
489 481 };
490 482
491 483 KeyboardManager.prototype.bind_events = function () {
492 484 var that = this;
493 485 $(document).keydown(function (event) {
494 486 return that.handle_keydown(event);
495 487 });
496 488 };
497 489
498 490 KeyboardManager.prototype.handle_keydown = function (event) {
499 491 var notebook = this.notebook;
500 492
501 493 if (event.which === keycodes.esc) {
502 494 // Intercept escape at highest level to avoid closing
503 495 // websocket connection with firefox
504 496 event.preventDefault();
505 497 }
506 498
507 499 if (!this.enabled) {
508 500 if (event.which === keycodes.esc) {
509 501 // ESC
510 502 notebook.command_mode();
511 503 return false;
512 504 }
513 505 return true;
514 506 }
515 507
516 508 if (this.mode === 'edit') {
517 509 return this.edit_shortcuts.call_handler(event);
518 510 } else if (this.mode === 'command') {
519 511 return this.command_shortcuts.call_handler(event);
520 512 }
521 513 return true;
522 514 };
523 515
524 516 KeyboardManager.prototype.edit_mode = function () {
525 517 this.last_mode = this.mode;
526 518 this.mode = 'edit';
527 519 };
528 520
529 521 KeyboardManager.prototype.command_mode = function () {
530 522 this.last_mode = this.mode;
531 523 this.mode = 'command';
532 524 };
533 525
534 526 KeyboardManager.prototype.enable = function () {
535 527 this.enabled = true;
536 528 };
537 529
538 530 KeyboardManager.prototype.disable = function () {
539 531 this.enabled = false;
540 532 };
541 533
542 534 KeyboardManager.prototype.register_events = function (e) {
543 535 var that = this;
544 536 var handle_focus = function () {
545 537 that.disable();
546 538 };
547 539 var handle_blur = function () {
548 540 that.enable();
549 541 };
550 542 e.on('focusin', handle_focus);
551 543 e.on('focusout', handle_blur);
552 544 // TODO: Very strange. The focusout event does not seem fire for the
553 545 // bootstrap textboxes on FF25&26... This works around that by
554 546 // registering focus and blur events recursively on all inputs within
555 547 // registered element.
556 548 e.find('input').blur(handle_blur);
557 549 e.on('DOMNodeInserted', function (event) {
558 550 var target = $(event.target);
559 551 if (target.is('input')) {
560 552 target.blur(handle_blur);
561 553 } else {
562 554 target.find('input').blur(handle_blur);
563 555 }
564 556 });
565 557 // There are times (raw_input) where we remove the element from the DOM before
566 558 // focusout is called. In this case we bind to the remove event of jQueryUI,
567 559 // which gets triggered upon removal, iff it is focused at the time.
568 560 // is_focused must be used to check for the case where an element within
569 561 // the element being removed is focused.
570 562 e.on('remove', function () {
571 563 if (utils.is_focused(e[0])) {
572 564 that.enable();
573 565 }
574 566 });
575 567 };
576 568
577 569 // For backwards compatability.
578 570 IPython.KeyboardManager = KeyboardManager;
579 571
580 572 return {'KeyboardManager': KeyboardManager};
581 573 });
General Comments 0
You need to be logged in to leave comments. Login now