##// END OF EJS Templates
Don't allow edit mode up arrow to continue past index == 0
Jonathan Frederic -
Show More
@@ -1,786 +1,787
1 1 //----------------------------------------------------------------------------
2 2 // Copyright (C) 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 // Keyboard management
10 10 //============================================================================
11 11
12 12 var IPython = (function (IPython) {
13 13 "use strict";
14 14
15 15 // Setup global keycodes and inverse keycodes.
16 16
17 17 // See http://unixpapa.com/js/key.html for a complete description. The short of
18 18 // it is that there are different keycode sets. Firefox uses the "Mozilla keycodes"
19 19 // and Webkit/IE use the "IE keycodes". These keycode sets are mostly the same
20 20 // but have minor differences.
21 21
22 22 // These apply to Firefox, (Webkit and IE)
23 23 var _keycodes = {
24 24 'a': 65, 'b': 66, 'c': 67, 'd': 68, 'e': 69, 'f': 70, 'g': 71, 'h': 72, 'i': 73,
25 25 'j': 74, 'k': 75, 'l': 76, 'm': 77, 'n': 78, 'o': 79, 'p': 80, 'q': 81, 'r': 82,
26 26 's': 83, 't': 84, 'u': 85, 'v': 86, 'w': 87, 'x': 88, 'y': 89, 'z': 90,
27 27 '1 !': 49, '2 @': 50, '3 #': 51, '4 $': 52, '5 %': 53, '6 ^': 54,
28 28 '7 &': 55, '8 *': 56, '9 (': 57, '0 )': 48,
29 29 '[ {': 219, '] }': 221, '` ~': 192, ', <': 188, '. >': 190, '/ ?': 191,
30 30 '\\ |': 220, '\' "': 222,
31 31 'numpad0': 96, 'numpad1': 97, 'numpad2': 98, 'numpad3': 99, 'numpad4': 100,
32 32 'numpad5': 101, 'numpad6': 102, 'numpad7': 103, 'numpad8': 104, 'numpad9': 105,
33 33 'multiply': 106, 'add': 107, 'subtract': 109, 'decimal': 110, 'divide': 111,
34 34 'f1': 112, 'f2': 113, 'f3': 114, 'f4': 115, 'f5': 116, 'f6': 117, 'f7': 118,
35 35 'f8': 119, 'f9': 120, 'f11': 122, 'f12': 123, 'f13': 124, 'f14': 125, 'f15': 126,
36 36 'backspace': 8, 'tab': 9, 'enter': 13, 'shift': 16, 'ctrl': 17, 'alt': 18,
37 37 'meta': 91, 'capslock': 20, 'esc': 27, 'space': 32, 'pageup': 33, 'pagedown': 34,
38 38 'end': 35, 'home': 36, 'left': 37, 'up': 38, 'right': 39, 'down': 40,
39 39 'insert': 45, 'delete': 46, 'numlock': 144,
40 40 };
41 41
42 42 // These apply to Firefox and Opera
43 43 var _mozilla_keycodes = {
44 44 '; :': 59, '= +': 61, '- _': 173, 'meta': 224
45 45 };
46 46
47 47 // This apply to Webkit and IE
48 48 var _ie_keycodes = {
49 49 '; :': 186, '= +': 187, '- _': 189,
50 50 };
51 51
52 52 var browser = IPython.utils.browser[0];
53 53 var platform = IPython.utils.platform;
54 54
55 55 if (browser === 'Firefox' || browser === 'Opera') {
56 56 $.extend(_keycodes, _mozilla_keycodes);
57 57 } else if (browser === 'Safari' || browser === 'Chrome' || browser === 'MSIE') {
58 58 $.extend(_keycodes, _ie_keycodes);
59 59 }
60 60
61 61 var keycodes = {};
62 62 var inv_keycodes = {};
63 63 for (var name in _keycodes) {
64 64 var names = name.split(' ');
65 65 if (names.length === 1) {
66 66 var n = names[0];
67 67 keycodes[n] = _keycodes[n];
68 68 inv_keycodes[_keycodes[n]] = n;
69 69 } else {
70 70 var primary = names[0];
71 71 var secondary = names[1];
72 72 keycodes[primary] = _keycodes[name];
73 73 keycodes[secondary] = _keycodes[name];
74 74 inv_keycodes[_keycodes[name]] = primary;
75 75 }
76 76 }
77 77
78 78
79 79 // Default keyboard shortcuts
80 80
81 81 var default_common_shortcuts = {
82 82 'shift' : {
83 83 help : '',
84 84 help_index : '',
85 85 handler : function (event) {
86 86 // ignore shift keydown
87 87 return true;
88 88 }
89 89 },
90 90 'shift+enter' : {
91 91 help : 'run cell, select below',
92 92 help_index : 'ba',
93 93 handler : function (event) {
94 94 IPython.notebook.execute_cell_and_select_below();
95 95 return false;
96 96 }
97 97 },
98 98 'ctrl+enter' : {
99 99 help : 'run cell',
100 100 help_index : 'bb',
101 101 handler : function (event) {
102 102 IPython.notebook.execute_cell();
103 103 return false;
104 104 }
105 105 },
106 106 'alt+enter' : {
107 107 help : 'run cell, insert below',
108 108 help_index : 'bc',
109 109 handler : function (event) {
110 110 IPython.notebook.execute_cell_and_insert_below();
111 111 return false;
112 112 }
113 113 }
114 114 };
115 115
116 116 if (platform === 'MacOS') {
117 117 default_common_shortcuts['cmd+s'] =
118 118 {
119 119 help : 'save notebook',
120 120 help_index : 'fb',
121 121 handler : function (event) {
122 122 IPython.notebook.save_checkpoint();
123 123 event.preventDefault();
124 124 return false;
125 125 }
126 126 };
127 127 } else {
128 128 default_common_shortcuts['ctrl+s'] =
129 129 {
130 130 help : 'save notebook',
131 131 help_index : 'fb',
132 132 handler : function (event) {
133 133 IPython.notebook.save_checkpoint();
134 134 event.preventDefault();
135 135 return false;
136 136 }
137 137 };
138 138 }
139 139
140 140 // Edit mode defaults
141 141
142 142 var default_edit_shortcuts = {
143 143 'esc' : {
144 144 help : 'command mode',
145 145 help_index : 'aa',
146 146 handler : function (event) {
147 147 IPython.notebook.command_mode();
148 148 IPython.notebook.focus_cell();
149 149 return false;
150 150 }
151 151 },
152 152 'ctrl+m' : {
153 153 help : 'command mode',
154 154 help_index : 'ab',
155 155 handler : function (event) {
156 156 IPython.notebook.command_mode();
157 157 IPython.notebook.focus_cell();
158 158 return false;
159 159 }
160 160 },
161 161 'up' : {
162 162 help : '',
163 163 help_index : '',
164 164 handler : function (event) {
165 var index = IPython.notebook.get_selected_index();
165 166 var cell = IPython.notebook.get_selected_cell();
166 if (cell && cell.at_top()) {
167 if (index !== 0 && cell && cell.at_top()) {
167 168 event.preventDefault();
168 169 IPython.notebook.command_mode();
169 170 IPython.notebook.select_prev();
170 171 IPython.notebook.edit_mode();
171 172 return false;
172 173 }
173 174 }
174 175 },
175 176 'down' : {
176 177 help : '',
177 178 help_index : '',
178 179 handler : function (event) {
179 180 var cell = IPython.notebook.get_selected_cell();
180 181 if (cell && cell.at_bottom()) {
181 182 event.preventDefault();
182 183 IPython.notebook.command_mode();
183 184 IPython.notebook.select_next();
184 185 IPython.notebook.edit_mode();
185 186 return false;
186 187 }
187 188 }
188 189 },
189 190 'alt+-' : {
190 191 help : 'split cell',
191 192 help_index : 'ea',
192 193 handler : function (event) {
193 194 IPython.notebook.split_cell();
194 195 return false;
195 196 }
196 197 },
197 198 'alt+subtract' : {
198 199 help : '',
199 200 help_index : 'eb',
200 201 handler : function (event) {
201 202 IPython.notebook.split_cell();
202 203 return false;
203 204 }
204 205 },
205 206 'tab' : {
206 207 help : 'indent or complete',
207 208 help_index : 'ec',
208 209 },
209 210 'shift+tab' : {
210 211 help : 'tooltip',
211 212 help_index : 'ed',
212 213 },
213 214 };
214 215
215 216 if (platform === 'MacOS') {
216 217 default_edit_shortcuts['cmd+/'] =
217 218 {
218 219 help : 'toggle comment',
219 220 help_index : 'ee'
220 221 };
221 222 default_edit_shortcuts['cmd+]'] =
222 223 {
223 224 help : 'indent',
224 225 help_index : 'ef'
225 226 };
226 227 default_edit_shortcuts['cmd+['] =
227 228 {
228 229 help : 'dedent',
229 230 help_index : 'eg'
230 231 };
231 232 } else {
232 233 default_edit_shortcuts['ctrl+/'] =
233 234 {
234 235 help : 'toggle comment',
235 236 help_index : 'ee'
236 237 };
237 238 default_edit_shortcuts['ctrl+]'] =
238 239 {
239 240 help : 'indent',
240 241 help_index : 'ef'
241 242 };
242 243 default_edit_shortcuts['ctrl+['] =
243 244 {
244 245 help : 'dedent',
245 246 help_index : 'eg'
246 247 };
247 248 }
248 249
249 250 // Command mode defaults
250 251
251 252 var default_command_shortcuts = {
252 253 'enter' : {
253 254 help : 'edit mode',
254 255 help_index : 'aa',
255 256 handler : function (event) {
256 257 IPython.notebook.edit_mode();
257 258 return false;
258 259 }
259 260 },
260 261 'up' : {
261 262 help : 'select previous cell',
262 263 help_index : 'da',
263 264 handler : function (event) {
264 265 var index = IPython.notebook.get_selected_index();
265 266 if (index !== 0 && index !== null) {
266 267 IPython.notebook.select_prev();
267 268 IPython.notebook.focus_cell();
268 269 }
269 270 return false;
270 271 }
271 272 },
272 273 'down' : {
273 274 help : 'select next cell',
274 275 help_index : 'db',
275 276 handler : function (event) {
276 277 var index = IPython.notebook.get_selected_index();
277 278 if (index !== (IPython.notebook.ncells()-1) && index !== null) {
278 279 IPython.notebook.select_next();
279 280 IPython.notebook.focus_cell();
280 281 }
281 282 return false;
282 283 }
283 284 },
284 285 'k' : {
285 286 help : 'select previous cell',
286 287 help_index : 'dc',
287 288 handler : function (event) {
288 289 var index = IPython.notebook.get_selected_index();
289 290 if (index !== 0 && index !== null) {
290 291 IPython.notebook.select_prev();
291 292 IPython.notebook.focus_cell();
292 293 }
293 294 return false;
294 295 }
295 296 },
296 297 'j' : {
297 298 help : 'select next cell',
298 299 help_index : 'dd',
299 300 handler : function (event) {
300 301 var index = IPython.notebook.get_selected_index();
301 302 if (index !== (IPython.notebook.ncells()-1) && index !== null) {
302 303 IPython.notebook.select_next();
303 304 IPython.notebook.focus_cell();
304 305 }
305 306 return false;
306 307 }
307 308 },
308 309 'x' : {
309 310 help : 'cut cell',
310 311 help_index : 'ee',
311 312 handler : function (event) {
312 313 IPython.notebook.cut_cell();
313 314 return false;
314 315 }
315 316 },
316 317 'c' : {
317 318 help : 'copy cell',
318 319 help_index : 'ef',
319 320 handler : function (event) {
320 321 IPython.notebook.copy_cell();
321 322 return false;
322 323 }
323 324 },
324 325 'shift+v' : {
325 326 help : 'paste cell above',
326 327 help_index : 'eg',
327 328 handler : function (event) {
328 329 IPython.notebook.paste_cell_above();
329 330 return false;
330 331 }
331 332 },
332 333 'v' : {
333 334 help : 'paste cell below',
334 335 help_index : 'eh',
335 336 handler : function (event) {
336 337 IPython.notebook.paste_cell_below();
337 338 return false;
338 339 }
339 340 },
340 341 'd' : {
341 342 help : 'delete cell (press twice)',
342 343 help_index : 'ej',
343 344 count: 2,
344 345 handler : function (event) {
345 346 IPython.notebook.delete_cell();
346 347 return false;
347 348 }
348 349 },
349 350 'a' : {
350 351 help : 'insert cell above',
351 352 help_index : 'ec',
352 353 handler : function (event) {
353 354 IPython.notebook.insert_cell_above('code');
354 355 IPython.notebook.select_prev();
355 356 IPython.notebook.focus_cell();
356 357 return false;
357 358 }
358 359 },
359 360 'b' : {
360 361 help : 'insert cell below',
361 362 help_index : 'ed',
362 363 handler : function (event) {
363 364 IPython.notebook.insert_cell_below('code');
364 365 IPython.notebook.select_next();
365 366 IPython.notebook.focus_cell();
366 367 return false;
367 368 }
368 369 },
369 370 'y' : {
370 371 help : 'to code',
371 372 help_index : 'ca',
372 373 handler : function (event) {
373 374 IPython.notebook.to_code();
374 375 return false;
375 376 }
376 377 },
377 378 'm' : {
378 379 help : 'to markdown',
379 380 help_index : 'cb',
380 381 handler : function (event) {
381 382 IPython.notebook.to_markdown();
382 383 return false;
383 384 }
384 385 },
385 386 'r' : {
386 387 help : 'to raw',
387 388 help_index : 'cc',
388 389 handler : function (event) {
389 390 IPython.notebook.to_raw();
390 391 return false;
391 392 }
392 393 },
393 394 '1' : {
394 395 help : 'to heading 1',
395 396 help_index : 'cd',
396 397 handler : function (event) {
397 398 IPython.notebook.to_heading(undefined, 1);
398 399 return false;
399 400 }
400 401 },
401 402 '2' : {
402 403 help : 'to heading 2',
403 404 help_index : 'ce',
404 405 handler : function (event) {
405 406 IPython.notebook.to_heading(undefined, 2);
406 407 return false;
407 408 }
408 409 },
409 410 '3' : {
410 411 help : 'to heading 3',
411 412 help_index : 'cf',
412 413 handler : function (event) {
413 414 IPython.notebook.to_heading(undefined, 3);
414 415 return false;
415 416 }
416 417 },
417 418 '4' : {
418 419 help : 'to heading 4',
419 420 help_index : 'cg',
420 421 handler : function (event) {
421 422 IPython.notebook.to_heading(undefined, 4);
422 423 return false;
423 424 }
424 425 },
425 426 '5' : {
426 427 help : 'to heading 5',
427 428 help_index : 'ch',
428 429 handler : function (event) {
429 430 IPython.notebook.to_heading(undefined, 5);
430 431 return false;
431 432 }
432 433 },
433 434 '6' : {
434 435 help : 'to heading 6',
435 436 help_index : 'ci',
436 437 handler : function (event) {
437 438 IPython.notebook.to_heading(undefined, 6);
438 439 return false;
439 440 }
440 441 },
441 442 'o' : {
442 443 help : 'toggle output',
443 444 help_index : 'gb',
444 445 handler : function (event) {
445 446 IPython.notebook.toggle_output();
446 447 return false;
447 448 }
448 449 },
449 450 'shift+o' : {
450 451 help : 'toggle output scrolling',
451 452 help_index : 'gc',
452 453 handler : function (event) {
453 454 IPython.notebook.toggle_output_scroll();
454 455 return false;
455 456 }
456 457 },
457 458 's' : {
458 459 help : 'save notebook',
459 460 help_index : 'fa',
460 461 handler : function (event) {
461 462 IPython.notebook.save_checkpoint();
462 463 return false;
463 464 }
464 465 },
465 466 'ctrl+j' : {
466 467 help : 'move cell down',
467 468 help_index : 'eb',
468 469 handler : function (event) {
469 470 IPython.notebook.move_cell_down();
470 471 return false;
471 472 }
472 473 },
473 474 'ctrl+k' : {
474 475 help : 'move cell up',
475 476 help_index : 'ea',
476 477 handler : function (event) {
477 478 IPython.notebook.move_cell_up();
478 479 return false;
479 480 }
480 481 },
481 482 'l' : {
482 483 help : 'toggle line numbers',
483 484 help_index : 'ga',
484 485 handler : function (event) {
485 486 IPython.notebook.cell_toggle_line_numbers();
486 487 return false;
487 488 }
488 489 },
489 490 'i' : {
490 491 help : 'interrupt kernel (press twice)',
491 492 help_index : 'ha',
492 493 count: 2,
493 494 handler : function (event) {
494 495 IPython.notebook.kernel.interrupt();
495 496 return false;
496 497 }
497 498 },
498 499 '0' : {
499 500 help : 'restart kernel (press twice)',
500 501 help_index : 'hb',
501 502 count: 2,
502 503 handler : function (event) {
503 504 IPython.notebook.restart_kernel();
504 505 return false;
505 506 }
506 507 },
507 508 'h' : {
508 509 help : 'keyboard shortcuts',
509 510 help_index : 'ge',
510 511 handler : function (event) {
511 512 IPython.quick_help.show_keyboard_shortcuts();
512 513 return false;
513 514 }
514 515 },
515 516 'z' : {
516 517 help : 'undo last delete',
517 518 help_index : 'ei',
518 519 handler : function (event) {
519 520 IPython.notebook.undelete_cell();
520 521 return false;
521 522 }
522 523 },
523 524 'shift+m' : {
524 525 help : 'merge cell below',
525 526 help_index : 'ek',
526 527 handler : function (event) {
527 528 IPython.notebook.merge_cell_below();
528 529 return false;
529 530 }
530 531 },
531 532 'q' : {
532 533 help : 'close pager',
533 534 help_index : 'gd',
534 535 handler : function (event) {
535 536 IPython.pager.collapse();
536 537 return false;
537 538 }
538 539 },
539 540 };
540 541
541 542
542 543 // Shortcut manager class
543 544
544 545 var ShortcutManager = function (delay) {
545 546 this._shortcuts = {};
546 547 this._counts = {};
547 548 this._timers = {};
548 549 this.delay = delay || 800; // delay in milliseconds
549 550 };
550 551
551 552 ShortcutManager.prototype.help = function () {
552 553 var help = [];
553 554 for (var shortcut in this._shortcuts) {
554 555 var help_string = this._shortcuts[shortcut].help;
555 556 var help_index = this._shortcuts[shortcut].help_index;
556 557 if (help_string) {
557 558 if (platform === 'MacOS') {
558 559 shortcut = shortcut.replace('meta', 'cmd');
559 560 }
560 561 help.push({
561 562 shortcut: shortcut,
562 563 help: help_string,
563 564 help_index: help_index}
564 565 );
565 566 }
566 567 }
567 568 help.sort(function (a, b) {
568 569 if (a.help_index > b.help_index)
569 570 return 1;
570 571 if (a.help_index < b.help_index)
571 572 return -1;
572 573 return 0;
573 574 });
574 575 return help;
575 576 };
576 577
577 578 ShortcutManager.prototype.normalize_key = function (key) {
578 579 return inv_keycodes[keycodes[key]];
579 580 };
580 581
581 582 ShortcutManager.prototype.normalize_shortcut = function (shortcut) {
582 583 // Sort a sequence of + separated modifiers into the order alt+ctrl+meta+shift
583 584 shortcut = shortcut.replace('cmd', 'meta').toLowerCase();
584 585 var values = shortcut.split("+");
585 586 if (values.length === 1) {
586 587 return this.normalize_key(values[0]);
587 588 } else {
588 589 var modifiers = values.slice(0,-1);
589 590 var key = this.normalize_key(values[values.length-1]);
590 591 modifiers.sort();
591 592 return modifiers.join('+') + '+' + key;
592 593 }
593 594 };
594 595
595 596 ShortcutManager.prototype.event_to_shortcut = function (event) {
596 597 // Convert a jQuery keyboard event to a strong based keyboard shortcut
597 598 var shortcut = '';
598 599 var key = inv_keycodes[event.which];
599 600 if (event.altKey && key !== 'alt') {shortcut += 'alt+';}
600 601 if (event.ctrlKey && key !== 'ctrl') {shortcut += 'ctrl+';}
601 602 if (event.metaKey && key !== 'meta') {shortcut += 'meta+';}
602 603 if (event.shiftKey && key !== 'shift') {shortcut += 'shift+';}
603 604 shortcut += key;
604 605 return shortcut;
605 606 };
606 607
607 608 ShortcutManager.prototype.clear_shortcuts = function () {
608 609 this._shortcuts = {};
609 610 };
610 611
611 612 ShortcutManager.prototype.add_shortcut = function (shortcut, data) {
612 613 if (typeof(data) === 'function') {
613 614 data = {help: '', help_index: '', handler: data};
614 615 }
615 616 data.help_index = data.help_index || '';
616 617 data.help = data.help || '';
617 618 data.count = data.count || 1;
618 619 if (data.help_index === '') {
619 620 data.help_index = 'zz';
620 621 }
621 622 shortcut = this.normalize_shortcut(shortcut);
622 623 this._counts[shortcut] = 0;
623 624 this._shortcuts[shortcut] = data;
624 625 };
625 626
626 627 ShortcutManager.prototype.add_shortcuts = function (data) {
627 628 for (var shortcut in data) {
628 629 this.add_shortcut(shortcut, data[shortcut]);
629 630 }
630 631 };
631 632
632 633 ShortcutManager.prototype.remove_shortcut = function (shortcut) {
633 634 shortcut = this.normalize_shortcut(shortcut);
634 635 delete this._counts[shortcut];
635 636 delete this._shortcuts[shortcut];
636 637 };
637 638
638 639 ShortcutManager.prototype.count_handler = function (shortcut, event, data) {
639 640 var that = this;
640 641 var c = this._counts;
641 642 var t = this._timers;
642 643 var timer = null;
643 644 if (c[shortcut] === data.count-1) {
644 645 c[shortcut] = 0;
645 646 timer = t[shortcut];
646 647 if (timer) {clearTimeout(timer); delete t[shortcut];}
647 648 return data.handler(event);
648 649 } else {
649 650 c[shortcut] = c[shortcut] + 1;
650 651 timer = setTimeout(function () {
651 652 c[shortcut] = 0;
652 653 }, that.delay);
653 654 t[shortcut] = timer;
654 655 }
655 656 return false;
656 657 };
657 658
658 659 ShortcutManager.prototype.call_handler = function (event) {
659 660 var shortcut = this.event_to_shortcut(event);
660 661 var data = this._shortcuts[shortcut];
661 662 if (data) {
662 663 var handler = data.handler;
663 664 if (handler) {
664 665 if (data.count === 1) {
665 666 return handler(event);
666 667 } else if (data.count > 1) {
667 668 return this.count_handler(shortcut, event, data);
668 669 }
669 670 }
670 671 }
671 672 return true;
672 673 };
673 674
674 675
675 676 // Main keyboard manager for the notebook
676 677
677 678 var KeyboardManager = function () {
678 679 this.mode = 'command';
679 680 this.enabled = true;
680 681 this.bind_events();
681 682 this.command_shortcuts = new ShortcutManager();
682 683 this.command_shortcuts.add_shortcuts(default_common_shortcuts);
683 684 this.command_shortcuts.add_shortcuts(default_command_shortcuts);
684 685 this.edit_shortcuts = new ShortcutManager();
685 686 this.edit_shortcuts.add_shortcuts(default_common_shortcuts);
686 687 this.edit_shortcuts.add_shortcuts(default_edit_shortcuts);
687 688 };
688 689
689 690 KeyboardManager.prototype.bind_events = function () {
690 691 var that = this;
691 692 $(document).keydown(function (event) {
692 693 return that.handle_keydown(event);
693 694 });
694 695 };
695 696
696 697 KeyboardManager.prototype.handle_keydown = function (event) {
697 698 var notebook = IPython.notebook;
698 699
699 700 if (event.which === keycodes.esc) {
700 701 // Intercept escape at highest level to avoid closing
701 702 // websocket connection with firefox
702 703 event.preventDefault();
703 704 }
704 705
705 706 if (!this.enabled) {
706 707 if (event.which === keycodes.esc) {
707 708 // ESC
708 709 notebook.command_mode();
709 710 return false;
710 711 }
711 712 return true;
712 713 }
713 714
714 715 if (this.mode === 'edit') {
715 716 return this.edit_shortcuts.call_handler(event);
716 717 } else if (this.mode === 'command') {
717 718 return this.command_shortcuts.call_handler(event);
718 719 }
719 720 return true;
720 721 };
721 722
722 723 KeyboardManager.prototype.edit_mode = function () {
723 724 this.last_mode = this.mode;
724 725 this.mode = 'edit';
725 726 };
726 727
727 728 KeyboardManager.prototype.command_mode = function () {
728 729 this.last_mode = this.mode;
729 730 this.mode = 'command';
730 731 };
731 732
732 733 KeyboardManager.prototype.enable = function () {
733 734 this.enabled = true;
734 735 };
735 736
736 737 KeyboardManager.prototype.disable = function () {
737 738 this.enabled = false;
738 739 };
739 740
740 741 KeyboardManager.prototype.register_events = function (e) {
741 742 var that = this;
742 743 var handle_focus = function () {
743 744 that.disable();
744 745 };
745 746 var handle_blur = function () {
746 747 that.enable();
747 748 };
748 749 e.on('focusin', handle_focus);
749 750 e.on('focusout', handle_blur);
750 751 // TODO: Very strange. The focusout event does not seem fire for the
751 752 // bootstrap textboxes on FF25&26... This works around that by
752 753 // registering focus and blur events recursively on all inputs within
753 754 // registered element.
754 755 e.find('input').blur(handle_blur);
755 756 e.on('DOMNodeInserted', function (event) {
756 757 var target = $(event.target);
757 758 if (target.is('input')) {
758 759 target.blur(handle_blur);
759 760 } else {
760 761 target.find('input').blur(handle_blur);
761 762 }
762 763 });
763 764 // There are times (raw_input) where we remove the element from the DOM before
764 765 // focusout is called. In this case we bind to the remove event of jQueryUI,
765 766 // which gets triggered upon removal, iff it is focused at the time.
766 767 // is_focused must be used to check for the case where an element within
767 768 // the element being removed is focused.
768 769 e.on('remove', function () {
769 770 if (IPython.utils.is_focused(e[0])) {
770 771 that.enable();
771 772 }
772 773 });
773 774 };
774 775
775 776
776 777 IPython.keycodes = keycodes;
777 778 IPython.inv_keycodes = inv_keycodes;
778 779 IPython.default_common_shortcuts = default_common_shortcuts;
779 780 IPython.default_edit_shortcuts = default_edit_shortcuts;
780 781 IPython.default_command_shortcuts = default_command_shortcuts;
781 782 IPython.ShortcutManager = ShortcutManager;
782 783 IPython.KeyboardManager = KeyboardManager;
783 784
784 785 return IPython;
785 786
786 787 }(IPython));
General Comments 0
You need to be logged in to leave comments. Login now