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