##// END OF EJS Templates
fix celltoolbar layout on FF
Matthias BUSSONNIER -
Show More
@@ -1,103 +1,111 b''
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;
10 width:100%;
11 -webkit-box-pack: end;
12 height:20px;
13 }
13 }
14
14
15 .celltoolbar div{
16 line-height: 0;
17 margin:0;
18 padding:0;
19 }
20
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 .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-radius : 0 0 0 0;
71 border : none;
72 border : none;
73 margin:0;
72 }
74 }
73
75
74 .celltoolbar .button_container select {
76 .celltoolbar .button_container select {
75 margin: 10px;
77 margin: 10px;
76 margin-top: 0px;
78 margin-top: 1px;
77 margin-bottom: 0px;
79 margin-bottom: 0px;
80 padding:0;
78 font-size: 87%;
81 font-size: 87%;
79 height:18px;
80 display:inline;
81 width:auto;
82 width:auto;
83 display:inline-block;
84 height:18px;
85 line-height:18px;
86 vertical-align:top;
82 }
87 }
83
88
84 .celltoolbar label{
89 .celltoolbar label{
85 display:inline;
90 display:inline-block;
86 line-height:13px;
91 height:15px;
92 line-height:15px;
93 vertical-align:top;
87 }
94 }
88
95
89 .celltoolbar label span {
96 .celltoolbar label span {
90 font-size: 85%;
97 font-size: 85%;
91 }
98 }
92
99
93 .celltoolbar input[type=checkbox] {
100 .celltoolbar input[type=checkbox] {
94 margin: 0px;
101 margin: 0px;
95 margin-left: 4px;
102 margin-left: 4px;
96 margin-right: 4px;
103 margin-right: 4px;
97 }
104 }
98
105
99
106
100 .celltoolbar ui-button {
107 .celltoolbar .ui-button {
101 border: none;
108 border: none;
109 vertical-align:top;
110 height:20px;
102 }
111 }
103
@@ -1,398 +1,394 b''
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/>');
38 var ctb_element = $('<div/>').addClass('celltoolbar')
38 var ctb_element = $('<div/>').addClass('celltoolbar hbox reverse')
39 .append(this.inner_element);
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')
40 this.element = $('<div/>').addClass('ctb_hideshow')
45 .append(ctb_area);
41 .append(ctb_element);
46 };
42 };
47
43
48
44
49 // The default css style for the outer celltoolbar div
45 // The default css style for the outer celltoolbar div
50 // (ctb_hideshow) is display: none. We add the ctb_show
46 // (ctb_hideshow) is display: none. We add the ctb_show
51 // class to either 1) the body to show all cell's toolbars
47 // class to either 1) the body to show all cell's toolbars
52 // or 2) to the individual celltoolbar divs to show just one
48 // or 2) to the individual celltoolbar divs to show just one
53 // cell's toolbar.
49 // cell's toolbar.
54
50
55 CellToolbar.global_hide = function () {
51 CellToolbar.global_hide = function () {
56 $('body').removeClass('ctb_show');
52 $('body').removeClass('ctb_show');
57 }
53 }
58
54
59
55
60 CellToolbar.global_show = function () {
56 CellToolbar.global_show = function () {
61 $('body').addClass('ctb_show');
57 $('body').addClass('ctb_show');
62 }
58 }
63
59
64
60
65 CellToolbar.prototype.hide = function () {
61 CellToolbar.prototype.hide = function () {
66 this.element.removeClass('ctb_show');
62 this.element.removeClass('ctb_show');
67 }
63 }
68
64
69
65
70 CellToolbar.prototype.show = function () {
66 CellToolbar.prototype.show = function () {
71 this.element.addClass('ctb_show');
67 this.element.addClass('ctb_show');
72 }
68 }
73
69
74
70
75 /**
71 /**
76 * Class variable that should contain a dict of all availlable callback
72 * Class variable that should contain a dict of all availlable callback
77 * we need to think of wether or not we allow nested namespace
73 * we need to think of wether or not we allow nested namespace
78 * @property _callback_dict
74 * @property _callback_dict
79 * @private
75 * @private
80 * @static
76 * @static
81 * @type Dict
77 * @type Dict
82 */
78 */
83 CellToolbar._callback_dict = {};
79 CellToolbar._callback_dict = {};
84
80
85
81
86 /**
82 /**
87 * Class variable that should contain the reverse order list of the button
83 * Class variable that should contain the reverse order list of the button
88 * to add to the toolbar of each cell
84 * to add to the toolbar of each cell
89 * @property _ui_controls_list
85 * @property _ui_controls_list
90 * @private
86 * @private
91 * @static
87 * @static
92 * @type List
88 * @type List
93 */
89 */
94 CellToolbar._ui_controls_list = [];
90 CellToolbar._ui_controls_list = [];
95
91
96
92
97 /**
93 /**
98 * Class variable that should contains the CellToolbar instances for each
94 * Class variable that should contains the CellToolbar instances for each
99 * cell of the notebook
95 * cell of the notebook
100 *
96 *
101 * @private
97 * @private
102 * @property _instances
98 * @property _instances
103 * @static
99 * @static
104 * @type List
100 * @type List
105 */
101 */
106 CellToolbar._instances =[]
102 CellToolbar._instances =[]
107
103
108
104
109 /**
105 /**
110 * keep a list of all the availlabel presets for the toolbar
106 * keep a list of all the availlabel presets for the toolbar
111 * @private
107 * @private
112 * @property _presets
108 * @property _presets
113 * @static
109 * @static
114 * @type Dict
110 * @type Dict
115 */
111 */
116 CellToolbar._presets ={}
112 CellToolbar._presets ={}
117
113
118
114
119 // this is by design not a prototype.
115 // this is by design not a prototype.
120 /**
116 /**
121 * Register a callback to create an UI element in a cell toolbar.
117 * Register a callback to create an UI element in a cell toolbar.
122 * @method register_callback
118 * @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
119 * @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
120 * for easier sorting and avoid collision
125 * @param callback {function(div, cell)} callback that will be called to generate the ui element
121 * @param callback {function(div, cell)} callback that will be called to generate the ui element
126 *
122 *
127 *
123 *
128 * The callback will receive the following element :
124 * The callback will receive the following element :
129 *
125 *
130 * * a div in which to add element.
126 * * a div in which to add element.
131 * * the cell it is responsible from
127 * * the cell it is responsible from
132 *
128 *
133 * @example
129 * @example
134 *
130 *
135 * Example that create callback for a button that toggle between `true` and `false` label,
131 * 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.
132 * with the metadata under the key 'foo' to reflect the status of the button.
137 *
133 *
138 * // first param reference to a DOM div
134 * // first param reference to a DOM div
139 * // second param reference to the cell.
135 * // second param reference to the cell.
140 * var toggle = function(div, cell) {
136 * var toggle = function(div, cell) {
141 * var button_container = $(div)
137 * var button_container = $(div)
142 *
138 *
143 * // let's create a button that show the current value of the metadata
139 * // let's create a button that show the current value of the metadata
144 * var button = $('<div/>').button({label:String(cell.metadata.foo)});
140 * var button = $('<div/>').button({label:String(cell.metadata.foo)});
145 *
141 *
146 * // On click, change the metadata value and update the button label
142 * // On click, change the metadata value and update the button label
147 * button.click(function(){
143 * button.click(function(){
148 * var v = cell.metadata.foo;
144 * var v = cell.metadata.foo;
149 * cell.metadata.foo = !v;
145 * cell.metadata.foo = !v;
150 * button.button("option", "label", String(!v));
146 * button.button("option", "label", String(!v));
151 * })
147 * })
152 *
148 *
153 * // add the button to the DOM div.
149 * // add the button to the DOM div.
154 * button_container.append(button);
150 * button_container.append(button);
155 * }
151 * }
156 *
152 *
157 * // now we register the callback under the name `foo` to give the
153 * // now we register the callback under the name `foo` to give the
158 * // user the ability to use it later
154 * // user the ability to use it later
159 * CellToolbar.register_callback('foo', toggle);
155 * CellToolbar.register_callback('foo', toggle);
160 */
156 */
161 CellToolbar.register_callback = function(name, callback){
157 CellToolbar.register_callback = function(name, callback){
162 // Overwrite if it already exists.
158 // Overwrite if it already exists.
163 CellToolbar._callback_dict[name] = callback;
159 CellToolbar._callback_dict[name] = callback;
164 };
160 };
165
161
166
162
167 /**
163 /**
168 * Register a preset of UI element in a cell toolbar.
164 * Register a preset of UI element in a cell toolbar.
169 * Not supported Yet.
165 * Not supported Yet.
170 * @method register_preset
166 * @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
167 * @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
168 * 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
169 * @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.
170 * should correspond to a name of a registerd callback.
175 *
171 *
176 * @private
172 * @private
177 * @example
173 * @example
178 *
174 *
179 * CellToolbar.register_callback('foo.c1', function(div, cell){...});
175 * CellToolbar.register_callback('foo.c1', function(div, cell){...});
180 * CellToolbar.register_callback('foo.c2', function(div, cell){...});
176 * CellToolbar.register_callback('foo.c2', function(div, cell){...});
181 * CellToolbar.register_callback('foo.c3', function(div, cell){...});
177 * CellToolbar.register_callback('foo.c3', function(div, cell){...});
182 * CellToolbar.register_callback('foo.c4', function(div, cell){...});
178 * CellToolbar.register_callback('foo.c4', function(div, cell){...});
183 * CellToolbar.register_callback('foo.c5', function(div, cell){...});
179 * CellToolbar.register_callback('foo.c5', function(div, cell){...});
184 *
180 *
185 * CellToolbar.register_preset('foo.foo_preset1', ['foo.c1', 'foo.c2', 'foo.c5'])
181 * CellToolbar.register_preset('foo.foo_preset1', ['foo.c1', 'foo.c2', 'foo.c5'])
186 * CellToolbar.register_preset('foo.foo_preset2', ['foo.c4', 'foo.c5'])
182 * CellToolbar.register_preset('foo.foo_preset2', ['foo.c4', 'foo.c5'])
187 */
183 */
188 CellToolbar.register_preset = function(name, preset_list) {
184 CellToolbar.register_preset = function(name, preset_list) {
189 CellToolbar._presets[name] = preset_list
185 CellToolbar._presets[name] = preset_list
190 $([IPython.events]).trigger('preset_added.CellToolbar', {name: name});
186 $([IPython.events]).trigger('preset_added.CellToolbar', {name: name});
191 };
187 };
192
188
193
189
194 /**
190 /**
195 * List the names of the presets that are currently registered.
191 * List the names of the presets that are currently registered.
196 *
192 *
197 * @method list_presets
193 * @method list_presets
198 * @static
194 * @static
199 */
195 */
200 CellToolbar.list_presets = function() {
196 CellToolbar.list_presets = function() {
201 var keys = [];
197 var keys = [];
202 for (var k in CellToolbar._presets) {
198 for (var k in CellToolbar._presets) {
203 keys.push(k);
199 keys.push(k);
204 }
200 }
205 return keys;
201 return keys;
206 };
202 };
207
203
208
204
209 /**
205 /**
210 * Activate an UI preset from `register_preset`
206 * Activate an UI preset from `register_preset`
211 *
207 *
212 * This does not update the selection UI.
208 * This does not update the selection UI.
213 *
209 *
214 * @method activate_preset
210 * @method activate_preset
215 * @param preset_name {String} string corresponding to the preset name
211 * @param preset_name {String} string corresponding to the preset name
216 *
212 *
217 * @static
213 * @static
218 * @private
214 * @private
219 * @example
215 * @example
220 *
216 *
221 * CellToolbar.activate_preset('foo.foo_preset1');
217 * CellToolbar.activate_preset('foo.foo_preset1');
222 */
218 */
223 CellToolbar.activate_preset= function(preset_name){
219 CellToolbar.activate_preset= function(preset_name){
224 var preset = CellToolbar._presets[preset_name];
220 var preset = CellToolbar._presets[preset_name];
225
221
226 if(preset != undefined){
222 if(preset != undefined){
227 CellToolbar._ui_controls_list = preset;
223 CellToolbar._ui_controls_list = preset;
228 CellToolbar.rebuild_all();
224 CellToolbar.rebuild_all();
229 }
225 }
230 }
226 }
231
227
232
228
233 /**
229 /**
234 * This should be called on the class and not on a instance as it will trigger
230 * This should be called on the class and not on a instance as it will trigger
235 * rebuild of all the instances.
231 * rebuild of all the instances.
236 * @method rebuild_all
232 * @method rebuild_all
237 * @static
233 * @static
238 *
234 *
239 */
235 */
240 CellToolbar.rebuild_all = function(){
236 CellToolbar.rebuild_all = function(){
241 for(var i in CellToolbar._instances){
237 for(var i in CellToolbar._instances){
242 CellToolbar._instances[i].rebuild();
238 CellToolbar._instances[i].rebuild();
243 }
239 }
244 }
240 }
245
241
246 /**
242 /**
247 * Rebuild all the button on the toolbar to update it's state.
243 * Rebuild all the button on the toolbar to update it's state.
248 * @method rebuild
244 * @method rebuild
249 */
245 */
250 CellToolbar.prototype.rebuild = function(){
246 CellToolbar.prototype.rebuild = function(){
251 // strip evrything from the div
247 // strip evrything from the div
252 // which is probabli metainner.
248 // which is probabli metainner.
253 // or this.element.
249 // or this.element.
254 this.inner_element.empty();
250 this.inner_element.empty();
255
251
256 var cdict = CellToolbar._callback_dict;
252 var cdict = CellToolbar._callback_dict;
257 var preset = CellToolbar._ui_controls_list;
253 var preset = CellToolbar._ui_controls_list;
258 // Yes we iterate on the class varaible, not the instance one.
254 // Yes we iterate on the class varaible, not the instance one.
259 for ( var index in CellToolbar._ui_controls_list){
255 for ( var index in CellToolbar._ui_controls_list){
260 var local_div = $('<div/>').addClass('button_container');
256 var local_div = $('<div/>').addClass('button_container');
261 // Note,
257 // Note,
262 // do this the other way, wrap in try/catch and don't append if any errors.
258 // do this the other way, wrap in try/catch and don't append if any errors.
263 this.inner_element.append(local_div)
259 this.inner_element.append(local_div)
264 cdict[preset[index]](local_div, this.cell)
260 cdict[preset[index]](local_div, this.cell)
265 }
261 }
266 }
262 }
267
263
268
264
269 /**
265 /**
270 */
266 */
271 CellToolbar.utils = {};
267 CellToolbar.utils = {};
272
268
273
269
274 /**
270 /**
275 * A utility function to generate bindings between a checkbox and cell/metadata
271 * A utility function to generate bindings between a checkbox and cell/metadata
276 * @method utils.checkbox_ui_generator
272 * @method utils.checkbox_ui_generator
277 * @static
273 * @static
278 *
274 *
279 * @param name {string} Label in front of the checkbox
275 * @param name {string} Label in front of the checkbox
280 * @param setter {function( cell, newValue )}
276 * @param setter {function( cell, newValue )}
281 * A setter method to set the newValue
277 * A setter method to set the newValue
282 * @param getter {function( cell )}
278 * @param getter {function( cell )}
283 * A getter methods which return the current value.
279 * A getter methods which return the current value.
284 *
280 *
285 * @return callback {function( div, cell )} Callback to be passed to `register_callback`
281 * @return callback {function( div, cell )} Callback to be passed to `register_callback`
286 *
282 *
287 * @example
283 * @example
288 *
284 *
289 * An exmple that bind the subkey `slideshow.isSectionStart` to a checkbox with a `New Slide` label
285 * An exmple that bind the subkey `slideshow.isSectionStart` to a checkbox with a `New Slide` label
290 *
286 *
291 * var newSlide = CellToolbar.utils.checkbox_ui_generator('New Slide',
287 * var newSlide = CellToolbar.utils.checkbox_ui_generator('New Slide',
292 * // setter
288 * // setter
293 * function(cell, value){
289 * function(cell, value){
294 * // we check that the slideshow namespace exist and create it if needed
290 * // we check that the slideshow namespace exist and create it if needed
295 * if (cell.metadata.slideshow == undefined){cell.metadata.slideshow = {}}
291 * if (cell.metadata.slideshow == undefined){cell.metadata.slideshow = {}}
296 * // set the value
292 * // set the value
297 * cell.metadata.slideshow.isSectionStart = value
293 * cell.metadata.slideshow.isSectionStart = value
298 * },
294 * },
299 * //geter
295 * //geter
300 * function(cell){ var ns = cell.metadata.slideshow;
296 * function(cell){ var ns = cell.metadata.slideshow;
301 * // if the slideshow namespace does not exist return `undefined`
297 * // if the slideshow namespace does not exist return `undefined`
302 * // (will be interpreted as `false` by checkbox) otherwise
298 * // (will be interpreted as `false` by checkbox) otherwise
303 * // return the value
299 * // return the value
304 * return (ns == undefined)? undefined: ns.isSectionStart
300 * return (ns == undefined)? undefined: ns.isSectionStart
305 * }
301 * }
306 * );
302 * );
307 *
303 *
308 * CellToolbar.register_callback('newSlide', newSlide);
304 * CellToolbar.register_callback('newSlide', newSlide);
309 *
305 *
310 */
306 */
311 CellToolbar.utils.checkbox_ui_generator = function(name, setter, getter){
307 CellToolbar.utils.checkbox_ui_generator = function(name, setter, getter){
312 return function(div, cell) {
308 return function(div, cell) {
313 var button_container = $(div)
309 var button_container = $(div)
314
310
315 var chkb = $('<input/>').attr('type', 'checkbox');
311 var chkb = $('<input/>').attr('type', 'checkbox');
316 var lbl = $('<label/>').append($('<span/>').text(name));
312 var lbl = $('<label/>').append($('<span/>').text(name));
317 lbl.append(chkb);
313 lbl.append(chkb);
318 chkb.attr("checked", getter(cell));
314 chkb.attr("checked", getter(cell));
319
315
320 chkb.click(function(){
316 chkb.click(function(){
321 var v = getter(cell);
317 var v = getter(cell);
322 setter(cell, !v);
318 setter(cell, !v);
323 chkb.attr("checked", !v);
319 chkb.attr("checked", !v);
324 })
320 })
325 button_container.append($('<div/>').append(lbl));
321 button_container.append($('<div/>').append(lbl));
326
322
327 }
323 }
328 }
324 }
329
325
330
326
331 /**
327 /**
332 * A utility function to generate bindings between a dropdown list cell
328 * A utility function to generate bindings between a dropdown list cell
333 * @method utils.select_ui_generator
329 * @method utils.select_ui_generator
334 * @static
330 * @static
335 *
331 *
336 * @param list_list {list of sublist} List of sublist of metadata value and name in the dropdown list.
332 * @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,
333 * 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.
334 * and second the corresponding value to be passed to setter/return by getter.
339 * @param setter {function( cell, newValue )}
335 * @param setter {function( cell, newValue )}
340 * A setter method to set the newValue
336 * A setter method to set the newValue
341 * @param getter {function( cell )}
337 * @param getter {function( cell )}
342 * A getter methods which return the current value of the metadata.
338 * A getter methods which return the current value of the metadata.
343 * @param [label=""] {String} optionnal label for the dropdown menu
339 * @param [label=""] {String} optionnal label for the dropdown menu
344 *
340 *
345 * @return callback {function( div, cell )} Callback to be passed to `register_callback`
341 * @return callback {function( div, cell )} Callback to be passed to `register_callback`
346 *
342 *
347 * @example
343 * @example
348 *
344 *
349 * var select_type = CellToolbar.utils.select_ui_generator([
345 * var select_type = CellToolbar.utils.select_ui_generator([
350 * ["<None>" , undefined ],
346 * ["<None>" , undefined ],
351 * ["Header Slide" , "header_slide" ],
347 * ["Header Slide" , "header_slide" ],
352 * ["Slide" , "slide" ],
348 * ["Slide" , "slide" ],
353 * ["Fragment" , "fragment" ],
349 * ["Fragment" , "fragment" ],
354 * ["Skip" , "skip" ],
350 * ["Skip" , "skip" ],
355 * ],
351 * ],
356 * // setter
352 * // setter
357 * function(cell, value){
353 * function(cell, value){
358 * // we check that the slideshow namespace exist and create it if needed
354 * // we check that the slideshow namespace exist and create it if needed
359 * if (cell.metadata.slideshow == undefined){cell.metadata.slideshow = {}}
355 * if (cell.metadata.slideshow == undefined){cell.metadata.slideshow = {}}
360 * // set the value
356 * // set the value
361 * cell.metadata.slideshow.slide_type = value
357 * cell.metadata.slideshow.slide_type = value
362 * },
358 * },
363 * //geter
359 * //geter
364 * function(cell){ var ns = cell.metadata.slideshow;
360 * function(cell){ var ns = cell.metadata.slideshow;
365 * // if the slideshow namespace does not exist return `undefined`
361 * // if the slideshow namespace does not exist return `undefined`
366 * // (will be interpreted as `false` by checkbox) otherwise
362 * // (will be interpreted as `false` by checkbox) otherwise
367 * // return the value
363 * // return the value
368 * return (ns == undefined)? undefined: ns.slide_type
364 * return (ns == undefined)? undefined: ns.slide_type
369 * }
365 * }
370 * CellToolbar.register_callback('slideshow.select', select_type);
366 * CellToolbar.register_callback('slideshow.select', select_type);
371 *
367 *
372 */
368 */
373 CellToolbar.utils.select_ui_generator = function(list_list, setter, getter, label){
369 CellToolbar.utils.select_ui_generator = function(list_list, setter, getter, label){
374 label= label? label: "";
370 label= label? label: "";
375 return function(div, cell) {
371 return function(div, cell) {
376 var button_container = $(div)
372 var button_container = $(div)
377 var lbl = $("<label/>").append($('<span/>').text(label));
373 var lbl = $("<label/>").append($('<span/>').text(label));
378 var select = $('<select/>').addClass('ui-widget ui-widget-content');
374 var select = $('<select/>').addClass('ui-widget ui-widget-content');
379 for(var itemn in list_list){
375 for(var itemn in list_list){
380 var opt = $('<option/>');
376 var opt = $('<option/>');
381 opt.attr('value', list_list[itemn][1])
377 opt.attr('value', list_list[itemn][1])
382 opt.text(list_list[itemn][0])
378 opt.text(list_list[itemn][0])
383 select.append(opt);
379 select.append(opt);
384 }
380 }
385 select.val(getter(cell));
381 select.val(getter(cell));
386 select.change(function(){
382 select.change(function(){
387 setter(cell, select.val());
383 setter(cell, select.val());
388 });
384 });
389 button_container.append($('<div/>').append(lbl).append(select));
385 button_container.append($('<div/>').append(lbl).append(select));
390
386
391 }
387 }
392 };
388 };
393
389
394
390
395 IPython.CellToolbar = CellToolbar;
391 IPython.CellToolbar = CellToolbar;
396
392
397 return IPython;
393 return IPython;
398 }(IPython));
394 }(IPython));
@@ -1,384 +1,386 b''
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