##// END OF EJS Templates
Merge pull request #7476 from Carreau/nofocus...
Min RK -
r19959:5a383a18 merge
parent child Browse files
Show More
@@ -1,507 +1,513
1 1 // Copyright (c) IPython Development Team.
2 2 // Distributed under the terms of the Modified BSD License.
3 3
4 4 define(function(require){
5 5 "use strict";
6 6
7 7 var ActionHandler = function (env) {
8 8 this.env = env || {};
9 9 Object.seal(this);
10 10 };
11 11
12 12 /**
13 13 * A bunch of predefined `Simple Actions` used by IPython.
14 14 * `Simple Actions` have the following keys:
15 15 * help (optional): a short string the describe the action.
16 16 * will be used in various context, like as menu name, tool tips on buttons,
17 17 * and short description in help menu.
18 18 * help_index (optional): a string used to sort action in help menu.
19 19 * icon (optional): a short string that represent the icon that have to be used with this
20 20 * action. this should mainly correspond to a Font_awesome class.
21 21 * handler : a function which is called when the action is activated. It will receive at first parameter
22 22 * a dictionary containing various handle to element of the notebook.
23 23 *
24 24 * action need to be registered with a **name** that can be use to refer to this action.
25 25 *
26 26 *
27 27 * if `help` is not provided it will be derived by replacing any dash by space
28 28 * in the **name** of the action. It is advised to provide a prefix to action name to
29 29 * avoid conflict the prefix should be all lowercase and end with a dot `.`
30 30 * in the absence of a prefix the behavior of the action is undefined.
31 31 *
32 32 * All action provided by IPython are prefixed with `ipython.`.
33 33 *
34 34 * One can register extra actions or replace an existing action with another one is possible
35 35 * but is considered undefined behavior.
36 36 *
37 37 **/
38 38 var _actions = {
39 39 'run-select-next': {
40 40 icon: 'fa-play',
41 41 help : 'run cell, select below',
42 42 help_index : 'ba',
43 43 handler : function (env) {
44 44 env.notebook.execute_cell_and_select_below();
45 45 }
46 46 },
47 47 'execute-in-place':{
48 48 help : 'run cell',
49 49 help_index : 'bb',
50 50 handler : function (env) {
51 51 env.notebook.execute_cell();
52 52 }
53 53 },
54 54 'execute-and-insert-after':{
55 55 help : 'run cell, insert below',
56 56 help_index : 'bc',
57 57 handler : function (env) {
58 58 env.notebook.execute_cell_and_insert_below();
59 59 }
60 60 },
61 61 'go-to-command-mode': {
62 62 help : 'command mode',
63 63 help_index : 'aa',
64 64 handler : function (env) {
65 65 env.notebook.command_mode();
66 66 }
67 67 },
68 68 'split-cell-at-cursor': {
69 69 help : 'split cell',
70 70 help_index : 'ea',
71 71 handler : function (env) {
72 72 env.notebook.split_cell();
73 73 }
74 74 },
75 75 'enter-edit-mode' : {
76 76 help_index : 'aa',
77 77 handler : function (env) {
78 78 env.notebook.edit_mode();
79 79 }
80 80 },
81 81 'select-previous-cell' : {
82 82 help_index : 'da',
83 83 handler : function (env) {
84 84 var index = env.notebook.get_selected_index();
85 85 if (index !== 0 && index !== null) {
86 86 env.notebook.select_prev();
87 87 env.notebook.focus_cell();
88 88 }
89 89 }
90 90 },
91 91 'select-next-cell' : {
92 92 help_index : 'db',
93 93 handler : function (env) {
94 94 var index = env.notebook.get_selected_index();
95 95 if (index !== (env.notebook.ncells()-1) && index !== null) {
96 96 env.notebook.select_next();
97 97 env.notebook.focus_cell();
98 98 }
99 99 }
100 100 },
101 101 'cut-selected-cell' : {
102 102 icon: 'fa-cut',
103 103 help_index : 'ee',
104 104 handler : function (env) {
105 var index = env.notebook.get_selected_index();
105 106 env.notebook.cut_cell();
107 env.notebook.select(index);
108 env.notebook.focus_cell();
106 109 }
107 110 },
108 111 'copy-selected-cell' : {
109 112 icon: 'fa-copy',
110 113 help_index : 'ef',
111 114 handler : function (env) {
112 115 env.notebook.copy_cell();
116 env.notebook.focus_cell();
113 117 }
114 118 },
115 119 'paste-cell-before' : {
116 120 help_index : 'eg',
117 121 handler : function (env) {
118 122 env.notebook.paste_cell_above();
119 123 }
120 124 },
121 125 'paste-cell-after' : {
122 126 icon: 'fa-paste',
123 127 help_index : 'eh',
124 128 handler : function (env) {
125 129 env.notebook.paste_cell_below();
126 130 }
127 131 },
128 132 'insert-cell-before' : {
129 133 help_index : 'ec',
130 134 handler : function (env) {
131 135 env.notebook.insert_cell_above();
132 136 env.notebook.select_prev();
133 137 env.notebook.focus_cell();
134 138 }
135 139 },
136 140 'insert-cell-after' : {
137 141 icon : 'fa-plus',
138 142 help_index : 'ed',
139 143 handler : function (env) {
140 144 env.notebook.insert_cell_below();
141 145 env.notebook.select_next();
142 146 env.notebook.focus_cell();
143 147 }
144 148 },
145 149 'change-selected-cell-to-code-cell' : {
146 150 help : 'to code',
147 151 help_index : 'ca',
148 152 handler : function (env) {
149 153 env.notebook.to_code();
150 154 }
151 155 },
152 156 'change-selected-cell-to-markdown-cell' : {
153 157 help : 'to markdown',
154 158 help_index : 'cb',
155 159 handler : function (env) {
156 160 env.notebook.to_markdown();
157 161 }
158 162 },
159 163 'change-selected-cell-to-raw-cell' : {
160 164 help : 'to raw',
161 165 help_index : 'cc',
162 166 handler : function (env) {
163 167 env.notebook.to_raw();
164 168 }
165 169 },
166 170 'change-selected-cell-to-heading-1' : {
167 171 help : 'to heading 1',
168 172 help_index : 'cd',
169 173 handler : function (env) {
170 174 env.notebook.to_heading(undefined, 1);
171 175 }
172 176 },
173 177 'change-selected-cell-to-heading-2' : {
174 178 help : 'to heading 2',
175 179 help_index : 'ce',
176 180 handler : function (env) {
177 181 env.notebook.to_heading(undefined, 2);
178 182 }
179 183 },
180 184 'change-selected-cell-to-heading-3' : {
181 185 help : 'to heading 3',
182 186 help_index : 'cf',
183 187 handler : function (env) {
184 188 env.notebook.to_heading(undefined, 3);
185 189 }
186 190 },
187 191 'change-selected-cell-to-heading-4' : {
188 192 help : 'to heading 4',
189 193 help_index : 'cg',
190 194 handler : function (env) {
191 195 env.notebook.to_heading(undefined, 4);
192 196 }
193 197 },
194 198 'change-selected-cell-to-heading-5' : {
195 199 help : 'to heading 5',
196 200 help_index : 'ch',
197 201 handler : function (env) {
198 202 env.notebook.to_heading(undefined, 5);
199 203 }
200 204 },
201 205 'change-selected-cell-to-heading-6' : {
202 206 help : 'to heading 6',
203 207 help_index : 'ci',
204 208 handler : function (env) {
205 209 env.notebook.to_heading(undefined, 6);
206 210 }
207 211 },
208 212 'toggle-output-visibility-selected-cell' : {
209 213 help : 'toggle output',
210 214 help_index : 'gb',
211 215 handler : function (env) {
212 216 env.notebook.toggle_output();
213 217 }
214 218 },
215 219 'toggle-output-scrolling-selected-cell' : {
216 220 help : 'toggle output scrolling',
217 221 help_index : 'gc',
218 222 handler : function (env) {
219 223 env.notebook.toggle_output_scroll();
220 224 }
221 225 },
222 226 'move-selected-cell-down' : {
223 227 icon: 'fa-arrow-down',
224 228 help_index : 'eb',
225 229 handler : function (env) {
226 230 env.notebook.move_cell_down();
227 231 }
228 232 },
229 233 'move-selected-cell-up' : {
230 234 icon: 'fa-arrow-up',
231 235 help_index : 'ea',
232 236 handler : function (env) {
233 237 env.notebook.move_cell_up();
234 238 }
235 239 },
236 240 'toggle-line-number-selected-cell' : {
237 241 help : 'toggle line numbers',
238 242 help_index : 'ga',
239 243 handler : function (env) {
240 244 env.notebook.cell_toggle_line_numbers();
241 245 }
242 246 },
243 247 'show-keyboard-shortcut-help-dialog' : {
244 248 help_index : 'ge',
245 249 handler : function (env) {
246 250 env.quick_help.show_keyboard_shortcuts();
247 251 }
248 252 },
249 253 'delete-cell': {
250 254 help_index : 'ej',
251 255 handler : function (env) {
252 256 env.notebook.delete_cell();
253 257 }
254 258 },
255 259 'interrupt-kernel':{
256 260 icon: 'fa-stop',
257 261 help_index : 'ha',
258 262 handler : function (env) {
259 263 env.notebook.kernel.interrupt();
264 env.notebook.focus_cell();
260 265 }
261 266 },
262 267 'restart-kernel':{
263 268 icon: 'fa-repeat',
264 269 help_index : 'hb',
265 270 handler : function (env) {
266 271 env.notebook.restart_kernel();
272 env.notebook.focus_cell();
267 273 }
268 274 },
269 275 'undo-last-cell-deletion' : {
270 276 help_index : 'ei',
271 277 handler : function (env) {
272 278 env.notebook.undelete_cell();
273 279 }
274 280 },
275 281 'merge-selected-cell-with-cell-after' : {
276 282 help : 'merge cell below',
277 283 help_index : 'ek',
278 284 handler : function (env) {
279 285 env.notebook.merge_cell_below();
280 286 }
281 287 },
282 288 'close-pager' : {
283 289 help_index : 'gd',
284 290 handler : function (env) {
285 291 env.pager.collapse();
286 292 }
287 293 }
288 294
289 295 };
290 296
291 297 /**
292 298 * A bunch of `Advance actions` for IPython.
293 299 * Cf `Simple Action` plus the following properties.
294 300 *
295 301 * handler: first argument of the handler is the event that triggerd the action
296 302 * (typically keypress). The handler is responsible for any modification of the
297 303 * event and event propagation.
298 304 * Is also responsible for returning false if the event have to be further ignored,
299 305 * true, to tell keyboard manager that it ignored the event.
300 306 *
301 307 * the second parameter of the handler is the environemnt passed to Simple Actions
302 308 *
303 309 **/
304 310 var custom_ignore = {
305 311 'ignore':{
306 312 handler : function () {
307 313 return true;
308 314 }
309 315 },
310 316 'move-cursor-up-or-previous-cell':{
311 317 handler : function (env, event) {
312 318 var index = env.notebook.get_selected_index();
313 319 var cell = env.notebook.get_cell(index);
314 320 var cm = env.notebook.get_selected_cell().code_mirror;
315 321 var cur = cm.getCursor();
316 322 if (cell && cell.at_top() && index !== 0 && cur.ch === 0) {
317 323 if(event){
318 324 event.preventDefault();
319 325 }
320 326 env.notebook.command_mode();
321 327 env.notebook.select_prev();
322 328 env.notebook.edit_mode();
323 329 cm = env.notebook.get_selected_cell().code_mirror;
324 330 cm.setCursor(cm.lastLine(), 0);
325 331 }
326 332 return false;
327 333 }
328 334 },
329 335 'move-cursor-down-or-next-cell':{
330 336 handler : function (env, event) {
331 337 var index = env.notebook.get_selected_index();
332 338 var cell = env.notebook.get_cell(index);
333 339 if (cell.at_bottom() && index !== (env.notebook.ncells()-1)) {
334 340 if(event){
335 341 event.preventDefault();
336 342 }
337 343 env.notebook.command_mode();
338 344 env.notebook.select_next();
339 345 env.notebook.edit_mode();
340 346 var cm = env.notebook.get_selected_cell().code_mirror;
341 347 cm.setCursor(0, 0);
342 348 }
343 349 return false;
344 350 }
345 351 },
346 352 'scroll-down': {
347 353 handler: function(env, event) {
348 354 if(event){
349 355 event.preventDefault();
350 356 }
351 357 return env.notebook.scroll_manager.scroll(1);
352 358 },
353 359 },
354 360 'scroll-up': {
355 361 handler: function(env, event) {
356 362 if(event){
357 363 event.preventDefault();
358 364 }
359 365 return env.notebook.scroll_manager.scroll(-1);
360 366 },
361 367 },
362 368 'save-notebook':{
363 369 help: "Save and Checkpoint",
364 370 help_index : 'fb',
365 371 icon: 'fa-save',
366 372 handler : function (env, event) {
367 373 env.notebook.save_checkpoint();
368 374 if(event){
369 375 event.preventDefault();
370 376 }
371 377 return false;
372 378 }
373 379 },
374 380 };
375 381
376 382 // private stuff that prepend `.ipython` to actions names
377 383 // and uniformize/fill in missing pieces in of an action.
378 384 var _prepare_handler = function(registry, subkey, source){
379 385 registry['ipython.'+subkey] = {};
380 386 registry['ipython.'+subkey].help = source[subkey].help||subkey.replace(/-/g,' ');
381 387 registry['ipython.'+subkey].help_index = source[subkey].help_index;
382 388 registry['ipython.'+subkey].icon = source[subkey].icon;
383 389 return source[subkey].handler;
384 390 };
385 391
386 392 // Will actually generate/register all the IPython actions
387 393 var fun = function(){
388 394 var final_actions = {};
389 395 var k;
390 396 for(k in _actions){
391 397 if(_actions.hasOwnProperty(k)){
392 398 // Js closure are function level not block level need to wrap in a IIFE
393 399 // and append ipython to event name these things do intercept event so are wrapped
394 400 // in a function that return false.
395 401 var handler = _prepare_handler(final_actions, k, _actions);
396 402 (function(key, handler){
397 403 final_actions['ipython.'+key].handler = function(env, event){
398 404 handler(env);
399 405 if(event){
400 406 event.preventDefault();
401 407 }
402 408 return false;
403 409 };
404 410 })(k, handler);
405 411 }
406 412 }
407 413
408 414 for(k in custom_ignore){
409 415 // Js closure are function level not block level need to wrap in a IIFE
410 416 // same as above, but decide for themselves wether or not they intercept events.
411 417 if(custom_ignore.hasOwnProperty(k)){
412 418 var handler = _prepare_handler(final_actions, k, custom_ignore);
413 419 (function(key, handler){
414 420 final_actions['ipython.'+key].handler = function(env, event){
415 421 return handler(env, event);
416 422 };
417 423 })(k, handler);
418 424 }
419 425 }
420 426
421 427 return final_actions;
422 428 };
423 429 ActionHandler.prototype._actions = fun();
424 430
425 431
426 432 /**
427 433 * extend the environment variable that will be pass to handlers
428 434 **/
429 435 ActionHandler.prototype.extend_env = function(env){
430 436 for(var k in env){
431 437 this.env[k] = env[k];
432 438 }
433 439 };
434 440
435 441 ActionHandler.prototype.register = function(action, name, prefix){
436 442 /**
437 443 * Register an `action` with an optional name and prefix.
438 444 *
439 445 * if name and prefix are not given they will be determined automatically.
440 446 * if action if just a `function` it will be wrapped in an anonymous action.
441 447 *
442 448 * @return the full name to access this action .
443 449 **/
444 450 action = this.normalise(action);
445 451 if( !name ){
446 452 name = 'autogenerated-'+String(action.handler);
447 453 }
448 454 prefix = prefix || 'auto';
449 455 var full_name = prefix+'.'+name;
450 456 this._actions[full_name] = action;
451 457 return full_name;
452 458
453 459 };
454 460
455 461
456 462 ActionHandler.prototype.normalise = function(data){
457 463 /**
458 464 * given an `action` or `function`, return a normalised `action`
459 465 * by setting all known attributes and removing unknown attributes;
460 466 **/
461 467 if(typeof(data) === 'function'){
462 468 data = {handler:data};
463 469 }
464 470 if(typeof(data.handler) !== 'function'){
465 471 throw('unknown datatype, cannot register');
466 472 }
467 473 var _data = data;
468 474 data = {};
469 475 data.handler = _data.handler;
470 476 data.help = _data.help || '';
471 477 data.icon = _data.icon || '';
472 478 data.help_index = _data.help_index || '';
473 479 return data;
474 480 };
475 481
476 482 ActionHandler.prototype.get_name = function(name_or_data){
477 483 /**
478 484 * given an `action` or `name` of a action, return the name attached to this action.
479 485 * if given the name of and corresponding actions does not exist in registry, return `null`.
480 486 **/
481 487
482 488 if(typeof(name_or_data) === 'string'){
483 489 if(this.exists(name_or_data)){
484 490 return name_or_data;
485 491 } else {
486 492 return null;
487 493 }
488 494 } else {
489 495 return this.register(name_or_data);
490 496 }
491 497 };
492 498
493 499 ActionHandler.prototype.get = function(name){
494 500 return this._actions[name];
495 501 };
496 502
497 503 ActionHandler.prototype.call = function(name, event, env){
498 504 return this._actions[name].handler(env|| this.env, event);
499 505 };
500 506
501 507 ActionHandler.prototype.exists = function(name){
502 508 return (typeof(this._actions[name]) !== 'undefined');
503 509 };
504 510
505 511 return {init:ActionHandler};
506 512
507 513 });
@@ -1,162 +1,164
1 1 // Copyright (c) IPython Development Team.
2 2 // Distributed under the terms of the Modified BSD License.
3 3
4 4 define([
5 5 'require',
6 6 'base/js/namespace',
7 7 'jquery',
8 8 './toolbar',
9 9 './celltoolbar'
10 10 ], function(require, IPython, $, toolbar, celltoolbar) {
11 11 "use strict";
12 12
13 13 var MainToolBar = function (selector, options) {
14 14 /**
15 15 * Constructor
16 16 *
17 17 * Parameters:
18 18 * selector: string
19 19 * options: dictionary
20 20 * Dictionary of keyword arguments.
21 21 * events: $(Events) instance
22 22 * notebook: Notebook instance
23 23 **/
24 24 toolbar.ToolBar.apply(this, [selector, options] );
25 25 this.events = options.events;
26 26 this.notebook = options.notebook;
27 27 this._make();
28 28 this.notebook.keyboard_manager.register_events(this.element);
29 29 Object.seal(this);
30 30 };
31 31
32 32 MainToolBar.prototype = Object.create(toolbar.ToolBar.prototype);
33 33
34 34 MainToolBar.prototype._make = function () {
35 35 var grps = [
36 36 [
37 37 ['ipython.save-notebook'],
38 38 'save-notbook'
39 39 ],
40 40 [
41 41 ['ipython.insert-cell-after'],
42 42 'insert_above_below'],
43 43 [
44 44 ['ipython.cut-selected-cell',
45 45 'ipython.copy-selected-cell',
46 46 'ipython.paste-cell-after'
47 47 ] ,
48 48 'cut_copy_paste'],
49 49 [
50 50 ['ipython.move-selected-cell-up',
51 51 'ipython.move-selected-cell-down'
52 52 ],
53 53 'move_up_down'],
54 54 [ ['ipython.run-select-next',
55 55 'ipython.interrupt-kernel',
56 56 'ipython.restart-kernel'
57 57 ],
58 58 'run_int'],
59 59 ['<add_celltype_list>'],
60 60 ['<add_celltoolbar_list>']
61 61 ];
62 62 this.construct(grps);
63 63 };
64 64
65 65 // add a cell type drop down to the maintoolbar.
66 66 // triggered when the pseudo action `<add_celltype_list>` is
67 67 // encountered when building a toolbar.
68 68 MainToolBar.prototype._pseudo_actions.add_celltype_list = function () {
69 69 var that = this;
70 70 var sel = $('<select/>')
71 71 .attr('id','cell_type')
72 72 .addClass('form-control select-xs')
73 73 .append($('<option/>').attr('value','code').text('Code'))
74 74 .append($('<option/>').attr('value','markdown').text('Markdown'))
75 75 .append($('<option/>').attr('value','raw').text('Raw NBConvert'))
76 76 .append($('<option/>').attr('value','heading').text('Heading'));
77 77 this.events.on('selected_cell_type_changed.Notebook', function (event, data) {
78 78 if (data.cell_type === 'heading') {
79 79 sel.val('Markdown');
80 80 } else {
81 81 sel.val(data.cell_type);
82 82 }
83 83 });
84 84 sel.change(function () {
85 85 var cell_type = $(this).val();
86 86 switch (cell_type) {
87 87 case 'code':
88 88 that.notebook.to_code();
89 89 break;
90 90 case 'markdown':
91 91 that.notebook.to_markdown();
92 92 break;
93 93 case 'raw':
94 94 that.notebook.to_raw();
95 95 break;
96 96 case 'heading':
97 97 that.notebook._warn_heading();
98 98 that.notebook.to_heading();
99 99 sel.val('markdown');
100 100 break;
101 101 default:
102 102 console.log("unrecognized cell type:", cell_type);
103 103 }
104 that.notebook.focus_cell();
104 105 });
105 106 return sel;
106 107
107 108 };
108 109
109 110 MainToolBar.prototype._pseudo_actions.add_celltoolbar_list = function () {
110 111 var label = $('<span/>').addClass("navbar-text").text('Cell Toolbar:');
111 112 var select = $('<select/>')
112 113 .attr('id', 'ctb_select')
113 114 .addClass('form-control select-xs')
114 115 .append($('<option/>').attr('value', '').text('None'));
115 116 var that = this;
116 117 select.change(function() {
117 118 var val = $(this).val();
118 119 if (val ==='') {
119 120 celltoolbar.CellToolbar.global_hide();
120 121 delete that.notebook.metadata.celltoolbar;
121 122 } else {
122 123 celltoolbar.CellToolbar.global_show();
123 124 celltoolbar.CellToolbar.activate_preset(val, that.events);
124 125 that.notebook.metadata.celltoolbar = val;
125 126 }
127 that.notebook.focus_cell();
126 128 });
127 129 // Setup the currently registered presets.
128 130 var presets = celltoolbar.CellToolbar.list_presets();
129 131 for (var i=0; i<presets.length; i++) {
130 132 var name = presets[i];
131 133 select.append($('<option/>').attr('value', name).text(name));
132 134 }
133 135 // Setup future preset registrations.
134 136 this.events.on('preset_added.CellToolbar', function (event, data) {
135 137 var name = data.name;
136 138 select.append($('<option/>').attr('value', name).text(name));
137 139 });
138 140 this.events.on('unregistered_preset.CellToolbar', function (event, data) {
139 141 if (select.val() === data.name){
140 142 select.val('');
141 143 celltoolbar.CellToolbar.global_hide();
142 144 delete that.notebook.metadata.celltoolbar;
143 145 }
144 146 select.find("option[value='"+name+"']" ).remove();
145 147 });
146 148 // Update select value when a preset is activated.
147 149 this.events.on('preset_activated.CellToolbar', function (event, data) {
148 150 if (select.val() !== data.name){
149 151 select.val(data.name);
150 152 }
151 153 });
152 154
153 155 var wrapper = $('<div/>').addClass('btn-group');
154 156 wrapper.append(label).append(select);
155 157 return wrapper;
156 158 };
157 159
158 160 // Backwards compatibility.
159 161 IPython.MainToolBar = MainToolBar;
160 162
161 163 return {'MainToolBar': MainToolBar};
162 164 });
General Comments 0
You need to be logged in to leave comments. Login now