##// END OF EJS Templates
Merge pull request #2876 from Carreau/fixctff...
Bussonnier Matthias -
r9531:03ea8efc merge
parent child Browse files
Show More
@@ -1,103 +1,109
1 1 /* Css for the metadata edit area */
2 2
3 3
4 4 .celltoolbar {
5 5 border: thin solid #CFCFCF;
6 margin-left: 0px;
7 6 border-bottom: none;
8 margin:0;
9 padding:0;
10 7 background : #EEE;
11 8 border-top-right-radius: 3px;
12 9 border-top-left-radius: 3px;
13 }
14
15 .celltoolbar div{
16 line-height: 0;
17 margin:0;
18 padding:0;
10 width:100%;
11 -webkit-box-pack: end;
12 height:20px;
19 13 }
20 14
21 15
22 16 .no_input_radius {
23 17 border-top-right-radius: 0px;
24 18 border-top-left-radius: 0px;
25 19 }
26 20
27 21 .text_cell .ctb_prompt {
28 22 display: none;
29 23 }
30 24
31 25 .code_cell .ctb_prompt {
32 26 display: block;
33 27 }
34 28
35 29 .ctb_hideshow {
36 30 display: none;
31 vertical-align:bottom;
32 padding-right: 2px;
33 }
34
35 .celltoolbar > div {
36 padding-top: 0px;
37 37 }
38 38
39 39 .ctb_area {
40 40 margin:0;
41 41 padding:0;
42 width:100%;
42 43
43 44 }
44 45
45 46
46 47 /*ctb_show is added to either body or the ctb_hideshow div to show
47 48 all or one cell's toolbars.
48 49 */
49 50 .ctb_show.ctb_hideshow, .ctb_show .ctb_hideshow {
50 51 display: block;
51 52 }
52 53
53 .ctb_show .ctb_hideshow + div > div.input_area,
54 .ctb_show .input_area,
54 55 .ctb_show .ctb_hideshow + div.text_cell_input {
55 56 border-top-right-radius: 0px;
56 57 border-top-left-radius: 0px;
57 58 }
58 59
59 60 .ctb_show > .celltoolbar {
60 61 border-bottom-right-radius: 0px;
61 62 border-bottom-left-radius: 0px;
62 63 }
63 64
64 65 .button_container {
65 float: right;
66 padding-bottom: 1px;
66 margin-top:0;
67 margin-bottom:0;
67 68 }
68 69
69 .button_container .ui-state-default, .button_container .ui-state-hover, .button_container .ui-state-hover span{
70 border-radius : 0 0 0 0;
71 border : none;
72 }
73 70
71 .ui-button {
72 min-width:30px;
73 }
74 74 .celltoolbar .button_container select {
75 75 margin: 10px;
76 margin-top: 0px;
76 margin-top: 1px;
77 77 margin-bottom: 0px;
78 padding:0;
78 79 font-size: 87%;
79 height:18px;
80 display:inline;
81 80 width:auto;
81 display:inline-block;
82 height:18px;
83 line-height:18px;
84 vertical-align:top;
82 85 }
83 86
84 87 .celltoolbar label{
85 display:inline;
86 line-height:13px;
88 display:inline-block;
89 height:15px;
90 line-height:15px;
91 vertical-align:top;
87 92 }
88 93
89 94 .celltoolbar label span {
90 95 font-size: 85%;
91 96 }
92 97
93 98 .celltoolbar input[type=checkbox] {
94 99 margin: 0px;
95 100 margin-left: 4px;
96 101 margin-right: 4px;
97 102 }
98 103
99 104
100 .celltoolbar ui-button {
105 .celltoolbar .ui-button {
101 106 border: none;
107 vertical-align:top;
108 height:20px;
102 109 }
103
@@ -1,398 +1,392
1 1 //----------------------------------------------------------------------------
2 2 // Copyright (C) 2012 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 // CellToolbar
10 10 //============================================================================
11 11
12 12
13 13 /**
14 14 * A Module to control the per-cell toolbar.
15 15 * @module IPython
16 16 * @namespace IPython
17 17 * @submodule CellToolbar
18 18 */
19 19 var IPython = (function (IPython) {
20 20 "use strict";
21 21
22 22 /**
23 23 * @constructor
24 24 * @class CellToolbar
25 25 * @param {The cell to attach the metadata UI to} cell
26 26 */
27 27 var CellToolbar = function (cell) {
28 28 CellToolbar._instances.push(this);
29 29 this.cell = cell;
30 30 this.create_element();
31 31 this.rebuild();
32 32 return this;
33 33 };
34 34
35 35
36 36 CellToolbar.prototype.create_element = function () {
37 this.inner_element = $('<div/>');
38 var ctb_element = $('<div/>').addClass('celltoolbar')
39 .append(this.inner_element);
40 ctb_element.addClass('box-flex1');
41 var ctb_area = $('<div/>').addClass('ctb_area hbox');
42 var ctb_prompt = $('<div/>').addClass('ctb_prompt prompt');
43 ctb_area.append(ctb_prompt).append(ctb_element);
37 this.inner_element = $('<div/>').addClass('celltoolbar hbox reverse')
44 38 this.element = $('<div/>').addClass('ctb_hideshow')
45 .append(ctb_area);
39 .append(this.inner_element);
46 40 };
47 41
48 42
49 43 // The default css style for the outer celltoolbar div
50 44 // (ctb_hideshow) is display: none. We add the ctb_show
51 45 // class to either 1) the body to show all cell's toolbars
52 46 // or 2) to the individual celltoolbar divs to show just one
53 47 // cell's toolbar.
54 48
55 49 CellToolbar.global_hide = function () {
56 50 $('body').removeClass('ctb_show');
57 51 }
58 52
59 53
60 54 CellToolbar.global_show = function () {
61 55 $('body').addClass('ctb_show');
62 56 }
63 57
64 58
65 59 CellToolbar.prototype.hide = function () {
66 60 this.element.removeClass('ctb_show');
67 61 }
68 62
69 63
70 64 CellToolbar.prototype.show = function () {
71 65 this.element.addClass('ctb_show');
72 66 }
73 67
74 68
75 69 /**
76 70 * Class variable that should contain a dict of all availlable callback
77 71 * we need to think of wether or not we allow nested namespace
78 72 * @property _callback_dict
79 73 * @private
80 74 * @static
81 75 * @type Dict
82 76 */
83 77 CellToolbar._callback_dict = {};
84 78
85 79
86 80 /**
87 81 * Class variable that should contain the reverse order list of the button
88 82 * to add to the toolbar of each cell
89 83 * @property _ui_controls_list
90 84 * @private
91 85 * @static
92 86 * @type List
93 87 */
94 88 CellToolbar._ui_controls_list = [];
95 89
96 90
97 91 /**
98 92 * Class variable that should contains the CellToolbar instances for each
99 93 * cell of the notebook
100 94 *
101 95 * @private
102 96 * @property _instances
103 97 * @static
104 98 * @type List
105 99 */
106 100 CellToolbar._instances =[]
107 101
108 102
109 103 /**
110 104 * keep a list of all the availlabel presets for the toolbar
111 105 * @private
112 106 * @property _presets
113 107 * @static
114 108 * @type Dict
115 109 */
116 110 CellToolbar._presets ={}
117 111
118 112
119 113 // this is by design not a prototype.
120 114 /**
121 115 * Register a callback to create an UI element in a cell toolbar.
122 116 * @method register_callback
123 117 * @param name {String} name to use to refer to the callback. It is advised to use a prefix with the name
124 118 * for easier sorting and avoid collision
125 119 * @param callback {function(div, cell)} callback that will be called to generate the ui element
126 120 *
127 121 *
128 122 * The callback will receive the following element :
129 123 *
130 124 * * a div in which to add element.
131 125 * * the cell it is responsible from
132 126 *
133 127 * @example
134 128 *
135 129 * Example that create callback for a button that toggle between `true` and `false` label,
136 130 * with the metadata under the key 'foo' to reflect the status of the button.
137 131 *
138 132 * // first param reference to a DOM div
139 133 * // second param reference to the cell.
140 134 * var toggle = function(div, cell) {
141 135 * var button_container = $(div)
142 136 *
143 137 * // let's create a button that show the current value of the metadata
144 138 * var button = $('<div/>').button({label:String(cell.metadata.foo)});
145 139 *
146 140 * // On click, change the metadata value and update the button label
147 141 * button.click(function(){
148 142 * var v = cell.metadata.foo;
149 143 * cell.metadata.foo = !v;
150 144 * button.button("option", "label", String(!v));
151 145 * })
152 146 *
153 147 * // add the button to the DOM div.
154 148 * button_container.append(button);
155 149 * }
156 150 *
157 151 * // now we register the callback under the name `foo` to give the
158 152 * // user the ability to use it later
159 153 * CellToolbar.register_callback('foo', toggle);
160 154 */
161 155 CellToolbar.register_callback = function(name, callback){
162 156 // Overwrite if it already exists.
163 157 CellToolbar._callback_dict[name] = callback;
164 158 };
165 159
166 160
167 161 /**
168 162 * Register a preset of UI element in a cell toolbar.
169 163 * Not supported Yet.
170 164 * @method register_preset
171 165 * @param name {String} name to use to refer to the preset. It is advised to use a prefix with the name
172 166 * for easier sorting and avoid collision
173 167 * @param preset_list {List of String} reverse order of the button in the toolbar. Each String of the list
174 168 * should correspond to a name of a registerd callback.
175 169 *
176 170 * @private
177 171 * @example
178 172 *
179 173 * CellToolbar.register_callback('foo.c1', function(div, cell){...});
180 174 * CellToolbar.register_callback('foo.c2', function(div, cell){...});
181 175 * CellToolbar.register_callback('foo.c3', function(div, cell){...});
182 176 * CellToolbar.register_callback('foo.c4', function(div, cell){...});
183 177 * CellToolbar.register_callback('foo.c5', function(div, cell){...});
184 178 *
185 179 * CellToolbar.register_preset('foo.foo_preset1', ['foo.c1', 'foo.c2', 'foo.c5'])
186 180 * CellToolbar.register_preset('foo.foo_preset2', ['foo.c4', 'foo.c5'])
187 181 */
188 182 CellToolbar.register_preset = function(name, preset_list) {
189 183 CellToolbar._presets[name] = preset_list
190 184 $([IPython.events]).trigger('preset_added.CellToolbar', {name: name});
191 185 };
192 186
193 187
194 188 /**
195 189 * List the names of the presets that are currently registered.
196 190 *
197 191 * @method list_presets
198 192 * @static
199 193 */
200 194 CellToolbar.list_presets = function() {
201 195 var keys = [];
202 196 for (var k in CellToolbar._presets) {
203 197 keys.push(k);
204 198 }
205 199 return keys;
206 200 };
207 201
208 202
209 203 /**
210 204 * Activate an UI preset from `register_preset`
211 205 *
212 206 * This does not update the selection UI.
213 207 *
214 208 * @method activate_preset
215 209 * @param preset_name {String} string corresponding to the preset name
216 210 *
217 211 * @static
218 212 * @private
219 213 * @example
220 214 *
221 215 * CellToolbar.activate_preset('foo.foo_preset1');
222 216 */
223 217 CellToolbar.activate_preset= function(preset_name){
224 218 var preset = CellToolbar._presets[preset_name];
225 219
226 220 if(preset != undefined){
227 221 CellToolbar._ui_controls_list = preset;
228 222 CellToolbar.rebuild_all();
229 223 }
230 224 }
231 225
232 226
233 227 /**
234 228 * This should be called on the class and not on a instance as it will trigger
235 229 * rebuild of all the instances.
236 230 * @method rebuild_all
237 231 * @static
238 232 *
239 233 */
240 234 CellToolbar.rebuild_all = function(){
241 235 for(var i in CellToolbar._instances){
242 236 CellToolbar._instances[i].rebuild();
243 237 }
244 238 }
245 239
246 240 /**
247 241 * Rebuild all the button on the toolbar to update it's state.
248 242 * @method rebuild
249 243 */
250 244 CellToolbar.prototype.rebuild = function(){
251 245 // strip evrything from the div
252 246 // which is probabli metainner.
253 247 // or this.element.
254 248 this.inner_element.empty();
255 249
256 250 var cdict = CellToolbar._callback_dict;
257 251 var preset = CellToolbar._ui_controls_list;
258 252 // Yes we iterate on the class varaible, not the instance one.
259 253 for ( var index in CellToolbar._ui_controls_list){
260 254 var local_div = $('<div/>').addClass('button_container');
261 255 // Note,
262 256 // do this the other way, wrap in try/catch and don't append if any errors.
263 257 this.inner_element.append(local_div)
264 258 cdict[preset[index]](local_div, this.cell)
265 259 }
266 260 }
267 261
268 262
269 263 /**
270 264 */
271 265 CellToolbar.utils = {};
272 266
273 267
274 268 /**
275 269 * A utility function to generate bindings between a checkbox and cell/metadata
276 270 * @method utils.checkbox_ui_generator
277 271 * @static
278 272 *
279 273 * @param name {string} Label in front of the checkbox
280 274 * @param setter {function( cell, newValue )}
281 275 * A setter method to set the newValue
282 276 * @param getter {function( cell )}
283 277 * A getter methods which return the current value.
284 278 *
285 279 * @return callback {function( div, cell )} Callback to be passed to `register_callback`
286 280 *
287 281 * @example
288 282 *
289 283 * An exmple that bind the subkey `slideshow.isSectionStart` to a checkbox with a `New Slide` label
290 284 *
291 285 * var newSlide = CellToolbar.utils.checkbox_ui_generator('New Slide',
292 286 * // setter
293 287 * function(cell, value){
294 288 * // we check that the slideshow namespace exist and create it if needed
295 289 * if (cell.metadata.slideshow == undefined){cell.metadata.slideshow = {}}
296 290 * // set the value
297 291 * cell.metadata.slideshow.isSectionStart = value
298 292 * },
299 293 * //geter
300 294 * function(cell){ var ns = cell.metadata.slideshow;
301 295 * // if the slideshow namespace does not exist return `undefined`
302 296 * // (will be interpreted as `false` by checkbox) otherwise
303 297 * // return the value
304 298 * return (ns == undefined)? undefined: ns.isSectionStart
305 299 * }
306 300 * );
307 301 *
308 302 * CellToolbar.register_callback('newSlide', newSlide);
309 303 *
310 304 */
311 305 CellToolbar.utils.checkbox_ui_generator = function(name, setter, getter){
312 306 return function(div, cell) {
313 307 var button_container = $(div)
314 308
315 309 var chkb = $('<input/>').attr('type', 'checkbox');
316 310 var lbl = $('<label/>').append($('<span/>').text(name));
317 311 lbl.append(chkb);
318 312 chkb.attr("checked", getter(cell));
319 313
320 314 chkb.click(function(){
321 315 var v = getter(cell);
322 316 setter(cell, !v);
323 317 chkb.attr("checked", !v);
324 318 })
325 319 button_container.append($('<div/>').append(lbl));
326 320
327 321 }
328 322 }
329 323
330 324
331 325 /**
332 326 * A utility function to generate bindings between a dropdown list cell
333 327 * @method utils.select_ui_generator
334 328 * @static
335 329 *
336 330 * @param list_list {list of sublist} List of sublist of metadata value and name in the dropdown list.
337 331 * subslit shoud contain 2 element each, first a string that woul be displayed in the dropdown list,
338 332 * and second the corresponding value to be passed to setter/return by getter.
339 333 * @param setter {function( cell, newValue )}
340 334 * A setter method to set the newValue
341 335 * @param getter {function( cell )}
342 336 * A getter methods which return the current value of the metadata.
343 337 * @param [label=""] {String} optionnal label for the dropdown menu
344 338 *
345 339 * @return callback {function( div, cell )} Callback to be passed to `register_callback`
346 340 *
347 341 * @example
348 342 *
349 343 * var select_type = CellToolbar.utils.select_ui_generator([
350 344 * ["<None>" , undefined ],
351 345 * ["Header Slide" , "header_slide" ],
352 346 * ["Slide" , "slide" ],
353 347 * ["Fragment" , "fragment" ],
354 348 * ["Skip" , "skip" ],
355 349 * ],
356 350 * // setter
357 351 * function(cell, value){
358 352 * // we check that the slideshow namespace exist and create it if needed
359 353 * if (cell.metadata.slideshow == undefined){cell.metadata.slideshow = {}}
360 354 * // set the value
361 355 * cell.metadata.slideshow.slide_type = value
362 356 * },
363 357 * //geter
364 358 * function(cell){ var ns = cell.metadata.slideshow;
365 359 * // if the slideshow namespace does not exist return `undefined`
366 360 * // (will be interpreted as `false` by checkbox) otherwise
367 361 * // return the value
368 362 * return (ns == undefined)? undefined: ns.slide_type
369 363 * }
370 364 * CellToolbar.register_callback('slideshow.select', select_type);
371 365 *
372 366 */
373 367 CellToolbar.utils.select_ui_generator = function(list_list, setter, getter, label){
374 368 label= label? label: "";
375 369 return function(div, cell) {
376 370 var button_container = $(div)
377 371 var lbl = $("<label/>").append($('<span/>').text(label));
378 372 var select = $('<select/>').addClass('ui-widget ui-widget-content');
379 373 for(var itemn in list_list){
380 374 var opt = $('<option/>');
381 375 opt.attr('value', list_list[itemn][1])
382 376 opt.text(list_list[itemn][0])
383 377 select.append(opt);
384 378 }
385 379 select.val(getter(cell));
386 380 select.change(function(){
387 381 setter(cell, select.val());
388 382 });
389 383 button_container.append($('<div/>').append(lbl).append(select));
390 384
391 385 }
392 386 };
393 387
394 388
395 389 IPython.CellToolbar = CellToolbar;
396 390
397 391 return IPython;
398 392 }(IPython));
@@ -1,384 +1,386
1 1 //----------------------------------------------------------------------------
2 2 // Copyright (C) 2008-2011 The IPython Development Team
3 3 //
4 4 // Distributed under the terms of the BSD License. The full license is in
5 5 // the file COPYING, distributed as part of this software.
6 6 //----------------------------------------------------------------------------
7 7
8 8 //============================================================================
9 9 // CodeCell
10 10 //============================================================================
11 11 /**
12 12 * An extendable module that provide base functionnality to create cell for notebook.
13 13 * @module IPython
14 14 * @namespace IPython
15 15 * @submodule CodeCell
16 16 */
17 17
18 18 var IPython = (function (IPython) {
19 19 "use strict";
20 20
21 21 var utils = IPython.utils;
22 22 var key = IPython.utils.keycodes;
23 23 CodeMirror.modeURL = "/static/codemirror/mode/%N/%N.js";
24 24
25 25 /**
26 26 * A Cell conceived to write code.
27 27 *
28 28 * The kernel doesn't have to be set at creation time, in that case
29 29 * it will be null and set_kernel has to be called later.
30 30 * @class CodeCell
31 31 * @extends IPython.Cell
32 32 *
33 33 * @constructor
34 34 * @param {Object|null} kernel
35 35 */
36 36 var CodeCell = function (kernel) {
37 37 this.kernel = kernel || null;
38 38 this.code_mirror = null;
39 39 this.input_prompt_number = null;
40 40 this.collapsed = false;
41 41 this.default_mode = 'python';
42 42 IPython.Cell.apply(this, arguments);
43 43
44 44 var that = this;
45 45 this.element.focusout(
46 46 function() { that.auto_highlight(); }
47 47 );
48 48 };
49 49
50 50 CodeCell.prototype = new IPython.Cell();
51 51
52 52 /**
53 53 * @method auto_highlight
54 54 */
55 55 CodeCell.prototype.auto_highlight = function () {
56 56 this._auto_highlight(IPython.config.cell_magic_highlight)
57 57 };
58 58
59 59 /** @method create_element */
60 60 CodeCell.prototype.create_element = function () {
61 61 IPython.Cell.prototype.create_element.apply(this, arguments);
62 62
63 63 var cell = $('<div></div>').addClass('cell border-box-sizing code_cell vbox');
64 64 cell.attr('tabindex','2');
65 65
66 66 this.celltoolbar = new IPython.CellToolbar(this);
67 cell.append(this.celltoolbar.element);
68 67
69 68 var input = $('<div></div>').addClass('input hbox');
69 var vbox = $('<div/>').addClass('vbox box-flex1')
70 70 input.append($('<div/>').addClass('prompt input_prompt'));
71 var input_area = $('<div/>').addClass('input_area box-flex1');
71 vbox.append(this.celltoolbar.element);
72 var input_area = $('<div/>').addClass('input_area');
72 73 this.code_mirror = CodeMirror(input_area.get(0), {
73 74 indentUnit : 4,
74 75 mode: 'python',
75 76 theme: 'ipython',
76 77 readOnly: this.read_only,
77 78 extraKeys: {"Tab": "indentMore","Shift-Tab" : "indentLess",'Backspace':"delSpaceToPrevTabStop"},
78 79 onKeyEvent: $.proxy(this.handle_codemirror_keyevent,this),
79 80 matchBrackets: true
80 81 });
81 input.append(input_area);
82 vbox.append(input_area);
83 input.append(vbox);
82 84 var output = $('<div></div>');
83 85 cell.append(input).append(output);
84 86 this.element = cell;
85 87 this.output_area = new IPython.OutputArea(output, true);
86 88
87 89 // construct a completer only if class exist
88 90 // otherwise no print view
89 91 if (IPython.Completer !== undefined)
90 92 {
91 93 this.completer = new IPython.Completer(this);
92 94 }
93 95 };
94 96
95 97 /**
96 98 * This method gets called in CodeMirror's onKeyDown/onKeyPress
97 99 * handlers and is used to provide custom key handling. Its return
98 100 * value is used to determine if CodeMirror should ignore the event:
99 101 * true = ignore, false = don't ignore.
100 102 * @method handle_codemirror_keyevent
101 103 */
102 104 CodeCell.prototype.handle_codemirror_keyevent = function (editor, event) {
103 105
104 106 if (this.read_only){
105 107 return false;
106 108 }
107 109
108 110 var that = this;
109 111 // whatever key is pressed, first, cancel the tooltip request before
110 112 // they are sent, and remove tooltip if any, except for tab again
111 113 if (event.type === 'keydown' && event.which != key.TAB ) {
112 114 IPython.tooltip.remove_and_cancel_tooltip();
113 115 };
114 116
115 117 var cur = editor.getCursor();
116 118 if (event.keyCode === key.ENTER){
117 119 this.auto_highlight();
118 120 }
119 121
120 122 if (event.keyCode === key.ENTER && (event.shiftKey || event.ctrlKey)) {
121 123 // Always ignore shift-enter in CodeMirror as we handle it.
122 124 return true;
123 125 } else if (event.which === 40 && event.type === 'keypress' && IPython.tooltip.time_before_tooltip >= 0) {
124 126 // triger on keypress (!) otherwise inconsistent event.which depending on plateform
125 127 // browser and keyboard layout !
126 128 // Pressing '(' , request tooltip, don't forget to reappend it
127 129 IPython.tooltip.pending(that);
128 130 } else if (event.which === key.UPARROW && event.type === 'keydown') {
129 131 // If we are not at the top, let CM handle the up arrow and
130 132 // prevent the global keydown handler from handling it.
131 133 if (!that.at_top()) {
132 134 event.stop();
133 135 return false;
134 136 } else {
135 137 return true;
136 138 };
137 139 } else if (event.which === key.ESC) {
138 140 IPython.tooltip.remove_and_cancel_tooltip(true);
139 141 return true;
140 142 } else if (event.which === key.DOWNARROW && event.type === 'keydown') {
141 143 // If we are not at the bottom, let CM handle the down arrow and
142 144 // prevent the global keydown handler from handling it.
143 145 if (!that.at_bottom()) {
144 146 event.stop();
145 147 return false;
146 148 } else {
147 149 return true;
148 150 };
149 151 } else if (event.keyCode === key.TAB && event.type == 'keydown' && event.shiftKey) {
150 152 if (editor.somethingSelected()){
151 153 var anchor = editor.getCursor("anchor");
152 154 var head = editor.getCursor("head");
153 155 if( anchor.line != head.line){
154 156 return false;
155 157 }
156 158 }
157 159 IPython.tooltip.request(that);
158 160 event.stop();
159 161 return true;
160 162 } else if (event.keyCode === key.TAB && event.type == 'keydown') {
161 163 // Tab completion.
162 164 //Do not trim here because of tooltip
163 165 if (editor.somethingSelected()){return false}
164 166 var pre_cursor = editor.getRange({line:cur.line,ch:0},cur);
165 167 if (pre_cursor.trim() === "") {
166 168 // Don't autocomplete if the part of the line before the cursor
167 169 // is empty. In this case, let CodeMirror handle indentation.
168 170 return false;
169 171 } else if ((pre_cursor.substr(-1) === "("|| pre_cursor.substr(-1) === " ") && IPython.config.tooltip_on_tab ) {
170 172 IPython.tooltip.request(that);
171 173 // Prevent the event from bubbling up.
172 174 event.stop();
173 175 // Prevent CodeMirror from handling the tab.
174 176 return true;
175 177 } else {
176 178 event.stop();
177 179 this.completer.startCompletion();
178 180 return true;
179 181 };
180 182 } else {
181 183 // keypress/keyup also trigger on TAB press, and we don't want to
182 184 // use those to disable tab completion.
183 185 return false;
184 186 };
185 187 return false;
186 188 };
187 189
188 190
189 191 // Kernel related calls.
190 192
191 193 CodeCell.prototype.set_kernel = function (kernel) {
192 194 this.kernel = kernel;
193 195 }
194 196
195 197 /**
196 198 * Execute current code cell to the kernel
197 199 * @method execute
198 200 */
199 201 CodeCell.prototype.execute = function () {
200 202 this.output_area.clear_output(true, true, true);
201 203 this.set_input_prompt('*');
202 204 this.element.addClass("running");
203 205 var callbacks = {
204 206 'execute_reply': $.proxy(this._handle_execute_reply, this),
205 207 'output': $.proxy(this.output_area.handle_output, this.output_area),
206 208 'clear_output': $.proxy(this.output_area.handle_clear_output, this.output_area),
207 209 'set_next_input': $.proxy(this._handle_set_next_input, this)
208 210 };
209 211 var msg_id = this.kernel.execute(this.get_text(), callbacks, {silent: false});
210 212 };
211 213
212 214 /**
213 215 * @method _handle_execute_reply
214 216 * @private
215 217 */
216 218 CodeCell.prototype._handle_execute_reply = function (content) {
217 219 this.set_input_prompt(content.execution_count);
218 220 this.element.removeClass("running");
219 221 $([IPython.events]).trigger('set_dirty.Notebook', {'value': true});
220 222 }
221 223
222 224 CodeCell.prototype._handle_set_next_input = function (text) {
223 225 var data = {'cell': this, 'text': text}
224 226 $([IPython.events]).trigger('set_next_input.Notebook', data);
225 227 }
226 228
227 229 // Basic cell manipulation.
228 230
229 231 CodeCell.prototype.select = function () {
230 232 IPython.Cell.prototype.select.apply(this);
231 233 this.code_mirror.refresh();
232 234 this.code_mirror.focus();
233 235 this.auto_highlight();
234 236 // We used to need an additional refresh() after the focus, but
235 237 // it appears that this has been fixed in CM. This bug would show
236 238 // up on FF when a newly loaded markdown cell was edited.
237 239 };
238 240
239 241
240 242 CodeCell.prototype.select_all = function () {
241 243 var start = {line: 0, ch: 0};
242 244 var nlines = this.code_mirror.lineCount();
243 245 var last_line = this.code_mirror.getLine(nlines-1);
244 246 var end = {line: nlines-1, ch: last_line.length};
245 247 this.code_mirror.setSelection(start, end);
246 248 };
247 249
248 250
249 251 CodeCell.prototype.collapse = function () {
250 252 this.collapsed = true;
251 253 this.output_area.collapse();
252 254 };
253 255
254 256
255 257 CodeCell.prototype.expand = function () {
256 258 this.collapsed = false;
257 259 this.output_area.expand();
258 260 };
259 261
260 262
261 263 CodeCell.prototype.toggle_output = function () {
262 264 this.collapsed = Boolean(1 - this.collapsed);
263 265 this.output_area.toggle_output();
264 266 };
265 267
266 268
267 269 CodeCell.prototype.toggle_output_scroll = function () {
268 270 this.output_area.toggle_scroll();
269 271 };
270 272
271 273
272 274 CodeCell.input_prompt_classical = function (prompt_value, lines_number) {
273 275 var ns = prompt_value || "&nbsp;";
274 276 return 'In&nbsp;[' + ns + ']:'
275 277 };
276 278
277 279 CodeCell.input_prompt_continuation = function (prompt_value, lines_number) {
278 280 var html = [CodeCell.input_prompt_classical(prompt_value, lines_number)];
279 281 for(var i=1; i < lines_number; i++){html.push(['...:'])};
280 282 return html.join('</br>')
281 283 };
282 284
283 285 CodeCell.input_prompt_function = CodeCell.input_prompt_classical;
284 286
285 287
286 288 CodeCell.prototype.set_input_prompt = function (number) {
287 289 var nline = 1
288 290 if( this.code_mirror != undefined) {
289 291 nline = this.code_mirror.lineCount();
290 292 }
291 293 this.input_prompt_number = number;
292 294 var prompt_html = CodeCell.input_prompt_function(this.input_prompt_number, nline);
293 295 this.element.find('div.input_prompt').html(prompt_html);
294 296 };
295 297
296 298
297 299 CodeCell.prototype.clear_input = function () {
298 300 this.code_mirror.setValue('');
299 301 };
300 302
301 303
302 304 CodeCell.prototype.get_text = function () {
303 305 return this.code_mirror.getValue();
304 306 };
305 307
306 308
307 309 CodeCell.prototype.set_text = function (code) {
308 310 return this.code_mirror.setValue(code);
309 311 };
310 312
311 313
312 314 CodeCell.prototype.at_top = function () {
313 315 var cursor = this.code_mirror.getCursor();
314 316 if (cursor.line === 0 && cursor.ch === 0) {
315 317 return true;
316 318 } else {
317 319 return false;
318 320 }
319 321 };
320 322
321 323
322 324 CodeCell.prototype.at_bottom = function () {
323 325 var cursor = this.code_mirror.getCursor();
324 326 if (cursor.line === (this.code_mirror.lineCount()-1) && cursor.ch === this.code_mirror.getLine(cursor.line).length) {
325 327 return true;
326 328 } else {
327 329 return false;
328 330 }
329 331 };
330 332
331 333
332 334 CodeCell.prototype.clear_output = function (stdout, stderr, other) {
333 335 this.output_area.clear_output(stdout, stderr, other);
334 336 };
335 337
336 338
337 339 // JSON serialization
338 340
339 341 CodeCell.prototype.fromJSON = function (data) {
340 342 IPython.Cell.prototype.fromJSON.apply(this, arguments);
341 343 if (data.cell_type === 'code') {
342 344 if (data.input !== undefined) {
343 345 this.set_text(data.input);
344 346 // make this value the starting point, so that we can only undo
345 347 // to this state, instead of a blank cell
346 348 this.code_mirror.clearHistory();
347 349 this.auto_highlight();
348 350 }
349 351 if (data.prompt_number !== undefined) {
350 352 this.set_input_prompt(data.prompt_number);
351 353 } else {
352 354 this.set_input_prompt();
353 355 };
354 356 this.output_area.fromJSON(data.outputs);
355 357 if (data.collapsed !== undefined) {
356 358 if (data.collapsed) {
357 359 this.collapse();
358 360 } else {
359 361 this.expand();
360 362 };
361 363 };
362 364 };
363 365 };
364 366
365 367
366 368 CodeCell.prototype.toJSON = function () {
367 369 var data = IPython.Cell.prototype.toJSON.apply(this);
368 370 data.input = this.get_text();
369 371 data.cell_type = 'code';
370 372 if (this.input_prompt_number) {
371 373 data.prompt_number = this.input_prompt_number;
372 374 };
373 375 var outputs = this.output_area.toJSON();
374 376 data.outputs = outputs;
375 377 data.language = 'python';
376 378 data.collapsed = this.collapsed;
377 379 return data;
378 380 };
379 381
380 382
381 383 IPython.CodeCell = CodeCell;
382 384
383 385 return IPython;
384 386 }(IPython));
General Comments 0
You need to be logged in to leave comments. Login now