##// END OF EJS Templates
Further cleanup for celltoolbars.
Brian Granger -
Show More
@@ -1,74 +1,72
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 #DDD;
5 border: thin solid #DDD;
6 margin-left: 0px;
6 margin-left: 0px;
7 border-bottom: none;
7 border-bottom: none;
8 background : #EEE;
8 background : #EEE;
9 border-top-right-radius: 3px;
9 border-top-right-radius: 3px;
10 border-top-left-radius: 3px;
10 border-top-left-radius: 3px;
11 }
11 }
12
12
13 .no_input_radius {
13 .no_input_radius {
14 border-top-right-radius: 0px;
14 border-top-right-radius: 0px;
15 border-top-left-radius: 0px;
15 border-top-left-radius: 0px;
16 }
16 }
17
17
18 .text_cell .ctb_prompt {
18 .text_cell .ctb_prompt {
19 display: none;
19 display: none;
20 }
20 }
21
21
22 .code_cell .ctb_prompt {
22 .code_cell .ctb_prompt {
23 display: block;
23 display: block;
24 }
24 }
25
25
26 .ctb_wrapper{
26 .ctb_hideshow {
27 display: none;
27 display: none;
28 }
28 }
29
29
30 .toolbaron .ctb_wrapper{
30 .ctb_show.ctb_hideshow {
31 display: block;
31 display: block;
32 display: -webkit-box;
33 }
32 }
34
33
35 .toolbaron .ctb_wrapper + div > div.input_area,
34 .ctb_show .ctb_hideshow + div > div.input_area,
36 .toolbaron .ctb_wrapper + div.text_cell_input{
35 .ctb_show .ctb_hideshow + div.text_cell_input {
37 border-top-right-radius: 0px;
36 border-top-right-radius: 0px;
38 border-top-left-radius: 0px;
37 border-top-left-radius: 0px;
39 }
38 }
40
39
41 .toolbaron > .celltoolbar {
40 .ctb_show > .celltoolbar {
42 border-bottom-right-radius: 0px;
41 border-bottom-right-radius: 0px;
43 border-bottom-left-radius: 0px;
42 border-bottom-left-radius: 0px;
44 }
43 }
45
44
46
47 .button_container {
45 .button_container {
48 float: right;
46 float: right;
49 }
47 }
50
48
51 .button_container .ui-state-default, .button_container .ui-state-hover, .button_container .ui-state-hover span{
49 .button_container .ui-state-default, .button_container .ui-state-hover, .button_container .ui-state-hover span{
52 border-radius : 0 0 0 0;
50 border-radius : 0 0 0 0;
53 border : none;
51 border : none;
54 }
52 }
55
53
56 .celltoolbar .button_container select {
54 .celltoolbar .button_container select {
57 margin: 10px;
55 margin: 10px;
58 margin-top: 0px;
56 margin-top: 0px;
59 margin-bottom: 0px;
57 margin-bottom: 0px;
60 font-size: 77%;
58 font-size: 77%;
61 }
59 }
62
60
63 .celltoolbar label span {
61 .celltoolbar label span {
64 font-size: 77%;
62 font-size: 77%;
65 }
63 }
66
64
67 .celltoolbar input[type=checkbox] {
65 .celltoolbar input[type=checkbox] {
68 margin-bottom: 1px;
66 margin-bottom: 1px;
69 }
67 }
70
68
71 .celltoolbar ui-button {
69 .celltoolbar ui-button {
72 border: none;
70 border: none;
73 }
71 }
74
72
@@ -1,386 +1,388
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')
39 .append(this.inner_element);
39 .append(this.inner_element);
40 this.element = $('<div/>').addClass('ctb_wrapper hbox');
41 ctb_element.addClass('box-flex1');
40 ctb_element.addClass('box-flex1');
41 var ctb_area = $('<div/>').addClass('ctb_area hbox');
42 var ctb_prompt = $('<div/>').addClass('ctb_prompt prompt');
42 var ctb_prompt = $('<div/>').addClass('ctb_prompt prompt');
43 this.element.append(ctb_prompt).append(ctb_element);
43 ctb_area.append(ctb_prompt).append(ctb_element);
44 this.element = $('<div/>').addClass('ctb_hideshow')
45 .append(ctb_area);
44 };
46 };
45
47
46
48
47 CellToolbar.dropdown_preset_element = $('<select/>')
49 CellToolbar.dropdown_preset_element = $('<select/>')
48 .addClass('ui-widget ui-widget-content')
50 .addClass('ui-widget ui-widget-content')
49 .attr('id', 'celltoolbar_selector')
51 .attr('id', 'celltoolbar_selector')
50 .append($('<option/>').attr('value', '').text('None'))
52 .append($('<option/>').attr('value', '').text('None'))
51
53
52
54
53 CellToolbar.dropdown_preset_element.change(function() {
55 CellToolbar.dropdown_preset_element.change(function() {
54 var val = CellToolbar.dropdown_preset_element.val()
56 var val = CellToolbar.dropdown_preset_element.val()
55 if(val ==''){
57 if(val ==''){
56 CellToolbar.global_hide();
58 CellToolbar.global_hide();
57 } else {
59 } else {
58 CellToolbar.global_show();
60 CellToolbar.global_show();
59 CellToolbar.activate_preset(val);
61 CellToolbar.activate_preset(val);
60 }
62 }
61 })
63 })
62
64
63
65
64 CellToolbar.global_hide = function () {
66 CellToolbar.global_hide = function () {
65 $('body').removeClass('toolbaron');
67 $('body').removeClass('ctb_show');
66 }
68 }
67
69
68
70
69 CellToolbar.global_show = function () {
71 CellToolbar.global_show = function () {
70 $('body').addClass('toolbaron');
72 $('body').addClass('ctb_show');
71 }
73 }
72
74
73 CellToolbar.prototype.hide = function () {
75 CellToolbar.prototype.hide = function () {
74 this.element.removeClass('toolbaron');
76 this.element.removeClass('ctb_show');
75 }
77 }
76
78
77
79
78 CellToolbar.prototype.show = function () {
80 CellToolbar.prototype.show = function () {
79 this.element.addClass('toolbaron');
81 this.element.addClass('ctb_show');
80 }
82 }
81
83
82
84
83 /**
85 /**
84 * Class variable that should contain a dict of all availlable callback
86 * Class variable that should contain a dict of all availlable callback
85 * we need to think of wether or not we allow nested namespace
87 * we need to think of wether or not we allow nested namespace
86 * @property _callback_dict
88 * @property _callback_dict
87 * @private
89 * @private
88 * @static
90 * @static
89 * @type Dict
91 * @type Dict
90 */
92 */
91 CellToolbar._callback_dict = {};
93 CellToolbar._callback_dict = {};
92
94
93 /**
95 /**
94 * Class variable that should contain the reverse order list of the button
96 * Class variable that should contain the reverse order list of the button
95 * to add to the toolbar of each cell
97 * to add to the toolbar of each cell
96 * @property _ui_controls_list
98 * @property _ui_controls_list
97 * @private
99 * @private
98 * @static
100 * @static
99 * @type List
101 * @type List
100 */
102 */
101 CellToolbar._ui_controls_list = [];
103 CellToolbar._ui_controls_list = [];
102
104
103 /**
105 /**
104 * Class variable that should contains the CellToolbar instances for each
106 * Class variable that should contains the CellToolbar instances for each
105 * cell of the notebook
107 * cell of the notebook
106 *
108 *
107 * @private
109 * @private
108 * @property _instances
110 * @property _instances
109 * @static
111 * @static
110 * @type List
112 * @type List
111 */
113 */
112 CellToolbar._instances =[]
114 CellToolbar._instances =[]
113
115
114 /**
116 /**
115 * keep a list of all the availlabel presets for the toolbar
117 * keep a list of all the availlabel presets for the toolbar
116 * @private
118 * @private
117 * @property _presets
119 * @property _presets
118 * @static
120 * @static
119 * @type Dict
121 * @type Dict
120 */
122 */
121 CellToolbar._presets ={}
123 CellToolbar._presets ={}
122
124
123 // this is by design not a prototype.
125 // this is by design not a prototype.
124 /**
126 /**
125 * Register a callback to create an UI element in a cell toolbar.
127 * Register a callback to create an UI element in a cell toolbar.
126 * @method register_callback
128 * @method register_callback
127 * @param name {String} name to use to refer to the callback. It is advised to use a prefix with the name
129 * @param name {String} name to use to refer to the callback. It is advised to use a prefix with the name
128 * for easier sorting and avoid collision
130 * for easier sorting and avoid collision
129 * @param callback {function(div, cell)} callback that will be called to generate the ui element
131 * @param callback {function(div, cell)} callback that will be called to generate the ui element
130 *
132 *
131 *
133 *
132 * The callback will receive the following element :
134 * The callback will receive the following element :
133 *
135 *
134 * * a div in which to add element.
136 * * a div in which to add element.
135 * * the cell it is responsible from
137 * * the cell it is responsible from
136 *
138 *
137 * @example
139 * @example
138 *
140 *
139 * Example that create callback for a button that toggle between `true` and `false` label,
141 * Example that create callback for a button that toggle between `true` and `false` label,
140 * with the metadata under the key 'foo' to reflect the status of the button.
142 * with the metadata under the key 'foo' to reflect the status of the button.
141 *
143 *
142 * // first param reference to a DOM div
144 * // first param reference to a DOM div
143 * // second param reference to the cell.
145 * // second param reference to the cell.
144 * var toggle = function(div, cell) {
146 * var toggle = function(div, cell) {
145 * var button_container = $(div)
147 * var button_container = $(div)
146 *
148 *
147 * // let's create a button that show the current value of the metadata
149 * // let's create a button that show the current value of the metadata
148 * var button = $('<div/>').button({label:String(cell.metadata.foo)});
150 * var button = $('<div/>').button({label:String(cell.metadata.foo)});
149 *
151 *
150 * // On click, change the metadata value and update the button label
152 * // On click, change the metadata value and update the button label
151 * button.click(function(){
153 * button.click(function(){
152 * var v = cell.metadata.foo;
154 * var v = cell.metadata.foo;
153 * cell.metadata.foo = !v;
155 * cell.metadata.foo = !v;
154 * button.button("option", "label", String(!v));
156 * button.button("option", "label", String(!v));
155 * })
157 * })
156 *
158 *
157 * // add the button to the DOM div.
159 * // add the button to the DOM div.
158 * button_container.append(button);
160 * button_container.append(button);
159 * }
161 * }
160 *
162 *
161 * // now we register the callback under the name `foo` to give the
163 * // now we register the callback under the name `foo` to give the
162 * // user the ability to use it later
164 * // user the ability to use it later
163 * CellToolbar.register_callback('foo', toggle);
165 * CellToolbar.register_callback('foo', toggle);
164 */
166 */
165 CellToolbar.register_callback = function(name, callback){
167 CellToolbar.register_callback = function(name, callback){
166 // Overwrite if it already exists.
168 // Overwrite if it already exists.
167 CellToolbar._callback_dict[name] = callback;
169 CellToolbar._callback_dict[name] = callback;
168 };
170 };
169
171
170 /**
172 /**
171 * Register a preset of UI element in a cell toolbar.
173 * Register a preset of UI element in a cell toolbar.
172 * Not supported Yet.
174 * Not supported Yet.
173 * @method register_preset
175 * @method register_preset
174 * @param name {String} name to use to refer to the preset. It is advised to use a prefix with the name
176 * @param name {String} name to use to refer to the preset. It is advised to use a prefix with the name
175 * for easier sorting and avoid collision
177 * for easier sorting and avoid collision
176 * @param preset_list {List of String} reverse order of the button in the toolbar. Each String of the list
178 * @param preset_list {List of String} reverse order of the button in the toolbar. Each String of the list
177 * should correspond to a name of a registerd callback.
179 * should correspond to a name of a registerd callback.
178 *
180 *
179 * @private
181 * @private
180 * @example
182 * @example
181 *
183 *
182 * CellToolbar.register_callback('foo.c1', function(div, cell){...});
184 * CellToolbar.register_callback('foo.c1', function(div, cell){...});
183 * CellToolbar.register_callback('foo.c2', function(div, cell){...});
185 * CellToolbar.register_callback('foo.c2', function(div, cell){...});
184 * CellToolbar.register_callback('foo.c3', function(div, cell){...});
186 * CellToolbar.register_callback('foo.c3', function(div, cell){...});
185 * CellToolbar.register_callback('foo.c4', function(div, cell){...});
187 * CellToolbar.register_callback('foo.c4', function(div, cell){...});
186 * CellToolbar.register_callback('foo.c5', function(div, cell){...});
188 * CellToolbar.register_callback('foo.c5', function(div, cell){...});
187 *
189 *
188 * CellToolbar.register_preset('foo.foo_preset1', ['foo.c1', 'foo.c2', 'foo.c5'])
190 * CellToolbar.register_preset('foo.foo_preset1', ['foo.c1', 'foo.c2', 'foo.c5'])
189 * CellToolbar.register_preset('foo.foo_preset2', ['foo.c4', 'foo.c5'])
191 * CellToolbar.register_preset('foo.foo_preset2', ['foo.c4', 'foo.c5'])
190 */
192 */
191 CellToolbar.register_preset = function(name, preset_list){
193 CellToolbar.register_preset = function(name, preset_list){
192 CellToolbar._presets[name] = preset_list
194 CellToolbar._presets[name] = preset_list
193 CellToolbar.dropdown_preset_element.append(
195 CellToolbar.dropdown_preset_element.append(
194 $('<option/>').attr('value', name).text(name)
196 $('<option/>').attr('value', name).text(name)
195 )
197 )
196 }
198 }
197 /**
199 /**
198 * Activate an UI preset from `register_preset`
200 * Activate an UI preset from `register_preset`
199 *
201 *
200 * This does not update the selection UI.
202 * This does not update the selection UI.
201 *
203 *
202 * @method activate_preset
204 * @method activate_preset
203 * @param preset_name {String} string corresponding to the preset name
205 * @param preset_name {String} string corresponding to the preset name
204 *
206 *
205 * @static
207 * @static
206 * @private
208 * @private
207 * @example
209 * @example
208 *
210 *
209 * CellToolbar.activate_preset('foo.foo_preset1');
211 * CellToolbar.activate_preset('foo.foo_preset1');
210 */
212 */
211 CellToolbar.activate_preset= function(preset_name){
213 CellToolbar.activate_preset= function(preset_name){
212 var preset = CellToolbar._presets[preset_name];
214 var preset = CellToolbar._presets[preset_name];
213
215
214 if(preset != undefined){
216 if(preset != undefined){
215 CellToolbar._ui_controls_list = preset;
217 CellToolbar._ui_controls_list = preset;
216 CellToolbar.rebuild_all();
218 CellToolbar.rebuild_all();
217 }
219 }
218 }
220 }
219
221
220
222
221 // this is by design not a prototype.
223 // this is by design not a prototype.
222 /**
224 /**
223 * This should be called on the class and not on a instance as it will trigger
225 * This should be called on the class and not on a instance as it will trigger
224 * rebuild of all the instances.
226 * rebuild of all the instances.
225 * @method rebuild_all
227 * @method rebuild_all
226 * @static
228 * @static
227 *
229 *
228 */
230 */
229 CellToolbar.rebuild_all = function(){
231 CellToolbar.rebuild_all = function(){
230 for(var i in CellToolbar._instances){
232 for(var i in CellToolbar._instances){
231 CellToolbar._instances[i].rebuild();
233 CellToolbar._instances[i].rebuild();
232 }
234 }
233 }
235 }
234
236
235 /**
237 /**
236 * Rebuild all the button on the toolbar to update it's state.
238 * Rebuild all the button on the toolbar to update it's state.
237 * @method rebuild
239 * @method rebuild
238 */
240 */
239 CellToolbar.prototype.rebuild = function(){
241 CellToolbar.prototype.rebuild = function(){
240 // strip evrything from the div
242 // strip evrything from the div
241 // which is probabli metainner.
243 // which is probabli metainner.
242 // or this.element.
244 // or this.element.
243 this.inner_element.empty();
245 this.inner_element.empty();
244
246
245 var cdict = CellToolbar._callback_dict;
247 var cdict = CellToolbar._callback_dict;
246 var preset = CellToolbar._ui_controls_list;
248 var preset = CellToolbar._ui_controls_list;
247 // Yes we iterate on the class varaible, not the instance one.
249 // Yes we iterate on the class varaible, not the instance one.
248 for ( var index in CellToolbar._ui_controls_list){
250 for ( var index in CellToolbar._ui_controls_list){
249 var local_div = $('<div/>').addClass('button_container');
251 var local_div = $('<div/>').addClass('button_container');
250 // Note,
252 // Note,
251 // do this the other way, wrap in try/catch and don't append if any errors.
253 // do this the other way, wrap in try/catch and don't append if any errors.
252 this.inner_element.append(local_div)
254 this.inner_element.append(local_div)
253 cdict[preset[index]](local_div, this.cell)
255 cdict[preset[index]](local_div, this.cell)
254 }
256 }
255
257
256 }
258 }
257
259
258
260
259 /**
261 /**
260 */
262 */
261 CellToolbar.utils = {};
263 CellToolbar.utils = {};
262
264
263 /**
265 /**
264 * A utility function to generate bindings between a checkbox and cell/metadata
266 * A utility function to generate bindings between a checkbox and cell/metadata
265 * @method utils.checkbox_ui_generator
267 * @method utils.checkbox_ui_generator
266 * @static
268 * @static
267 *
269 *
268 * @param name {string} Label in front of the checkbox
270 * @param name {string} Label in front of the checkbox
269 * @param setter {function( cell, newValue )}
271 * @param setter {function( cell, newValue )}
270 * A setter method to set the newValue
272 * A setter method to set the newValue
271 * @param getter {function( cell )}
273 * @param getter {function( cell )}
272 * A getter methods which return the current value.
274 * A getter methods which return the current value.
273 *
275 *
274 * @return callback {function( div, cell )} Callback to be passed to `register_callback`
276 * @return callback {function( div, cell )} Callback to be passed to `register_callback`
275 *
277 *
276 * @example
278 * @example
277 *
279 *
278 * An exmple that bind the subkey `slideshow.isSectionStart` to a checkbox with a `New Slide` label
280 * An exmple that bind the subkey `slideshow.isSectionStart` to a checkbox with a `New Slide` label
279 *
281 *
280 * var newSlide = CellToolbar.utils.checkbox_ui_generator('New Slide',
282 * var newSlide = CellToolbar.utils.checkbox_ui_generator('New Slide',
281 * // setter
283 * // setter
282 * function(cell, value){
284 * function(cell, value){
283 * // we check that the slideshow namespace exist and create it if needed
285 * // we check that the slideshow namespace exist and create it if needed
284 * if (cell.metadata.slideshow == undefined){cell.metadata.slideshow = {}}
286 * if (cell.metadata.slideshow == undefined){cell.metadata.slideshow = {}}
285 * // set the value
287 * // set the value
286 * cell.metadata.slideshow.isSectionStart = value
288 * cell.metadata.slideshow.isSectionStart = value
287 * },
289 * },
288 * //geter
290 * //geter
289 * function(cell){ var ns = cell.metadata.slideshow;
291 * function(cell){ var ns = cell.metadata.slideshow;
290 * // if the slideshow namespace does not exist return `undefined`
292 * // if the slideshow namespace does not exist return `undefined`
291 * // (will be interpreted as `false` by checkbox) otherwise
293 * // (will be interpreted as `false` by checkbox) otherwise
292 * // return the value
294 * // return the value
293 * return (ns == undefined)? undefined: ns.isSectionStart
295 * return (ns == undefined)? undefined: ns.isSectionStart
294 * }
296 * }
295 * );
297 * );
296 *
298 *
297 * CellToolbar.register_callback('newSlide', newSlide);
299 * CellToolbar.register_callback('newSlide', newSlide);
298 *
300 *
299 */
301 */
300 CellToolbar.utils.checkbox_ui_generator = function(name, setter, getter){
302 CellToolbar.utils.checkbox_ui_generator = function(name, setter, getter){
301 return function(div, cell) {
303 return function(div, cell) {
302 var button_container = $(div)
304 var button_container = $(div)
303
305
304 var chkb = $('<input/>').attr('type', 'checkbox');
306 var chkb = $('<input/>').attr('type', 'checkbox');
305 var lbl = $('<label/>').append($('<span/>').text(name));
307 var lbl = $('<label/>').append($('<span/>').text(name));
306 lbl.append(chkb);
308 lbl.append(chkb);
307 chkb.attr("checked", getter(cell));
309 chkb.attr("checked", getter(cell));
308
310
309 chkb.click(function(){
311 chkb.click(function(){
310 var v = getter(cell);
312 var v = getter(cell);
311 setter(cell, !v);
313 setter(cell, !v);
312 chkb.attr("checked", !v);
314 chkb.attr("checked", !v);
313 })
315 })
314 button_container.append($('<div/>').append(lbl));
316 button_container.append($('<div/>').append(lbl));
315
317
316 }
318 }
317 }
319 }
318
320
319 /**
321 /**
320 * A utility function to generate bindings between a dropdown list cell
322 * A utility function to generate bindings between a dropdown list cell
321 * @method utils.select_ui_generator
323 * @method utils.select_ui_generator
322 * @static
324 * @static
323 *
325 *
324 * @param list_list {list of sublist} List of sublist of metadata value and name in the dropdown list.
326 * @param list_list {list of sublist} List of sublist of metadata value and name in the dropdown list.
325 * subslit shoud contain 2 element each, first a string that woul be displayed in the dropdown list,
327 * subslit shoud contain 2 element each, first a string that woul be displayed in the dropdown list,
326 * and second the corresponding value to be passed to setter/return by getter.
328 * and second the corresponding value to be passed to setter/return by getter.
327 * @param setter {function( cell, newValue )}
329 * @param setter {function( cell, newValue )}
328 * A setter method to set the newValue
330 * A setter method to set the newValue
329 * @param getter {function( cell )}
331 * @param getter {function( cell )}
330 * A getter methods which return the current value of the metadata.
332 * A getter methods which return the current value of the metadata.
331 * @param [label=""] {String} optionnal label for the dropdown menu
333 * @param [label=""] {String} optionnal label for the dropdown menu
332 *
334 *
333 * @return callback {function( div, cell )} Callback to be passed to `register_callback`
335 * @return callback {function( div, cell )} Callback to be passed to `register_callback`
334 *
336 *
335 * @example
337 * @example
336 *
338 *
337 * var select_type = CellToolbar.utils.select_ui_generator([
339 * var select_type = CellToolbar.utils.select_ui_generator([
338 * ["<None>" , undefined ],
340 * ["<None>" , undefined ],
339 * ["Header Slide" , "header_slide" ],
341 * ["Header Slide" , "header_slide" ],
340 * ["Slide" , "slide" ],
342 * ["Slide" , "slide" ],
341 * ["Fragment" , "fragment" ],
343 * ["Fragment" , "fragment" ],
342 * ["Skip" , "skip" ],
344 * ["Skip" , "skip" ],
343 * ],
345 * ],
344 * // setter
346 * // setter
345 * function(cell, value){
347 * function(cell, value){
346 * // we check that the slideshow namespace exist and create it if needed
348 * // we check that the slideshow namespace exist and create it if needed
347 * if (cell.metadata.slideshow == undefined){cell.metadata.slideshow = {}}
349 * if (cell.metadata.slideshow == undefined){cell.metadata.slideshow = {}}
348 * // set the value
350 * // set the value
349 * cell.metadata.slideshow.slide_type = value
351 * cell.metadata.slideshow.slide_type = value
350 * },
352 * },
351 * //geter
353 * //geter
352 * function(cell){ var ns = cell.metadata.slideshow;
354 * function(cell){ var ns = cell.metadata.slideshow;
353 * // if the slideshow namespace does not exist return `undefined`
355 * // if the slideshow namespace does not exist return `undefined`
354 * // (will be interpreted as `false` by checkbox) otherwise
356 * // (will be interpreted as `false` by checkbox) otherwise
355 * // return the value
357 * // return the value
356 * return (ns == undefined)? undefined: ns.slide_type
358 * return (ns == undefined)? undefined: ns.slide_type
357 * }
359 * }
358 * CellToolbar.register_callback('slideshow.select', select_type);
360 * CellToolbar.register_callback('slideshow.select', select_type);
359 *
361 *
360 */
362 */
361 CellToolbar.utils.select_ui_generator = function(list_list, setter, getter, label){
363 CellToolbar.utils.select_ui_generator = function(list_list, setter, getter, label){
362 label= label? label: "";
364 label= label? label: "";
363 return function(div, cell) {
365 return function(div, cell) {
364 var button_container = $(div)
366 var button_container = $(div)
365 var lbl = $("<label/>").append($('<span/>').text(label));
367 var lbl = $("<label/>").append($('<span/>').text(label));
366 var select = $('<select/>').addClass('ui-widget ui-widget-content');
368 var select = $('<select/>').addClass('ui-widget ui-widget-content');
367 for(var itemn in list_list){
369 for(var itemn in list_list){
368 var opt = $('<option/>');
370 var opt = $('<option/>');
369 opt.attr('value', list_list[itemn][1])
371 opt.attr('value', list_list[itemn][1])
370 opt.text(list_list[itemn][0])
372 opt.text(list_list[itemn][0])
371 select.append(opt);
373 select.append(opt);
372 }
374 }
373 select.val(getter(cell));
375 select.val(getter(cell));
374 select.change(function(){
376 select.change(function(){
375 setter(cell, select.val());
377 setter(cell, select.val());
376 });
378 });
377 button_container.append($('<div/>').append(lbl).append(select));
379 button_container.append($('<div/>').append(lbl).append(select));
378
380
379 }
381 }
380 };
382 };
381
383
382
384
383 IPython.CellToolbar = CellToolbar;
385 IPython.CellToolbar = CellToolbar;
384
386
385 return IPython;
387 return IPython;
386 }(IPython));
388 }(IPython));
@@ -1,534 +1,536
1 //----------------------------------------------------------------------------
1 //----------------------------------------------------------------------------
2 // Copyright (C) 2008-2012 The IPython Development Team
2 // Copyright (C) 2008-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 // TextCell
9 // TextCell
10 //============================================================================
10 //============================================================================
11
11
12 /**
12 /**
13 A module that allow to create different type of Text Cell
13 A module that allow to create different type of Text Cell
14 @module IPython
14 @module IPython
15 @namespace IPython
15 @namespace IPython
16 */
16 */
17 var IPython = (function (IPython) {
17 var IPython = (function (IPython) {
18
18
19 // TextCell base class
19 // TextCell base class
20 var key = IPython.utils.keycodes;
20 var key = IPython.utils.keycodes;
21
21
22 /**
22 /**
23 * Construct a new TextCell, codemirror mode is by default 'htmlmixed', and cell type is 'text'
23 * Construct a new TextCell, codemirror mode is by default 'htmlmixed', and cell type is 'text'
24 * cell start as not redered.
24 * cell start as not redered.
25 *
25 *
26 * @class TextCell
26 * @class TextCell
27 * @constructor TextCell
27 * @constructor TextCell
28 * @extend Ipython.Cell
28 * @extend Ipython.Cell
29 */
29 */
30 var TextCell = function () {
30 var TextCell = function () {
31 this.code_mirror_mode = this.code_mirror_mode || 'htmlmixed';
31 this.code_mirror_mode = this.code_mirror_mode || 'htmlmixed';
32 IPython.Cell.apply(this, arguments);
32 IPython.Cell.apply(this, arguments);
33 this.rendered = false;
33 this.rendered = false;
34 this.cell_type = this.cell_type || 'text';
34 this.cell_type = this.cell_type || 'text';
35 };
35 };
36
36
37 TextCell.prototype = new IPython.Cell();
37 TextCell.prototype = new IPython.Cell();
38
38
39 /**
39 /**
40 * Create the DOM element of the TextCell
40 * Create the DOM element of the TextCell
41 * @method create_element
41 * @method create_element
42 * @private
42 * @private
43 */
43 */
44 TextCell.prototype.create_element = function () {
44 TextCell.prototype.create_element = function () {
45 IPython.Cell.prototype.create_element.apply(this, arguments);
45 IPython.Cell.prototype.create_element.apply(this, arguments);
46 var cell = $("<div>").addClass('cell text_cell border-box-sizing vbox');
46 var cell = $("<div>").addClass('cell text_cell border-box-sizing vbox');
47 cell.attr('tabindex','2');
47 cell.attr('tabindex','2');
48
48 this.celltoolbar = new IPython.CellToolbar(this);
49 this.celltoolbar = new IPython.CellToolbar(this);
49 cell.append(this.celltoolbar.element);
50 cell.append(this.celltoolbar.element);
51
50 var input_area = $('<div/>').addClass('text_cell_input border-box-sizing');
52 var input_area = $('<div/>').addClass('text_cell_input border-box-sizing');
51 this.code_mirror = CodeMirror(input_area.get(0), {
53 this.code_mirror = CodeMirror(input_area.get(0), {
52 indentUnit : 4,
54 indentUnit : 4,
53 mode: this.code_mirror_mode,
55 mode: this.code_mirror_mode,
54 theme: 'default',
56 theme: 'default',
55 value: this.placeholder,
57 value: this.placeholder,
56 readOnly: this.read_only,
58 readOnly: this.read_only,
57 lineWrapping : true,
59 lineWrapping : true,
58 extraKeys: {"Tab": "indentMore","Shift-Tab" : "indentLess"},
60 extraKeys: {"Tab": "indentMore","Shift-Tab" : "indentLess"},
59 onKeyEvent: $.proxy(this.handle_codemirror_keyevent,this)
61 onKeyEvent: $.proxy(this.handle_codemirror_keyevent,this)
60 });
62 });
61 // The tabindex=-1 makes this div focusable.
63 // The tabindex=-1 makes this div focusable.
62 var render_area = $('<div/>').addClass('text_cell_render border-box-sizing').
64 var render_area = $('<div/>').addClass('text_cell_render border-box-sizing').
63 addClass('rendered_html').attr('tabindex','-1');
65 addClass('rendered_html').attr('tabindex','-1');
64 cell.append(input_area).append(render_area);
66 cell.append(input_area).append(render_area);
65 this.element = cell;
67 this.element = cell;
66 };
68 };
67
69
68
70
69 /**
71 /**
70 * Bind the DOM evet to cell actions
72 * Bind the DOM evet to cell actions
71 * Need to be called after TextCell.create_element
73 * Need to be called after TextCell.create_element
72 * @private
74 * @private
73 * @method bind_event
75 * @method bind_event
74 */
76 */
75 TextCell.prototype.bind_events = function () {
77 TextCell.prototype.bind_events = function () {
76 IPython.Cell.prototype.bind_events.apply(this);
78 IPython.Cell.prototype.bind_events.apply(this);
77 var that = this;
79 var that = this;
78 this.element.keydown(function (event) {
80 this.element.keydown(function (event) {
79 if (event.which === 13 && !event.shiftKey) {
81 if (event.which === 13 && !event.shiftKey) {
80 if (that.rendered) {
82 if (that.rendered) {
81 that.edit();
83 that.edit();
82 return false;
84 return false;
83 };
85 };
84 };
86 };
85 });
87 });
86 this.element.dblclick(function () {
88 this.element.dblclick(function () {
87 that.edit();
89 that.edit();
88 });
90 });
89 };
91 };
90
92
91 /**
93 /**
92 * This method gets called in CodeMirror's onKeyDown/onKeyPress
94 * This method gets called in CodeMirror's onKeyDown/onKeyPress
93 * handlers and is used to provide custom key handling.
95 * handlers and is used to provide custom key handling.
94 *
96 *
95 * Subclass should override this method to have custom handeling
97 * Subclass should override this method to have custom handeling
96 *
98 *
97 * @method handle_codemirror_keyevent
99 * @method handle_codemirror_keyevent
98 * @param {CodeMirror} editor - The codemirror instance bound to the cell
100 * @param {CodeMirror} editor - The codemirror instance bound to the cell
99 * @param {event} event -
101 * @param {event} event -
100 * @return {Boolean} `true` if CodeMirror should ignore the event, `false` Otherwise
102 * @return {Boolean} `true` if CodeMirror should ignore the event, `false` Otherwise
101 */
103 */
102 TextCell.prototype.handle_codemirror_keyevent = function (editor, event) {
104 TextCell.prototype.handle_codemirror_keyevent = function (editor, event) {
103
105
104 if (event.keyCode === 13 && (event.shiftKey || event.ctrlKey)) {
106 if (event.keyCode === 13 && (event.shiftKey || event.ctrlKey)) {
105 // Always ignore shift-enter in CodeMirror as we handle it.
107 // Always ignore shift-enter in CodeMirror as we handle it.
106 return true;
108 return true;
107 }
109 }
108 return false;
110 return false;
109 };
111 };
110
112
111 /**
113 /**
112 * Select the current cell and trigger 'focus'
114 * Select the current cell and trigger 'focus'
113 * @method select
115 * @method select
114 */
116 */
115 TextCell.prototype.select = function () {
117 TextCell.prototype.select = function () {
116 IPython.Cell.prototype.select.apply(this);
118 IPython.Cell.prototype.select.apply(this);
117 var output = this.element.find("div.text_cell_render");
119 var output = this.element.find("div.text_cell_render");
118 output.trigger('focus');
120 output.trigger('focus');
119 };
121 };
120
122
121 /**
123 /**
122 * unselect the current cell and `render` it
124 * unselect the current cell and `render` it
123 * @method unselect
125 * @method unselect
124 */
126 */
125 TextCell.prototype.unselect = function() {
127 TextCell.prototype.unselect = function() {
126 // render on selection of another cell
128 // render on selection of another cell
127 this.render();
129 this.render();
128 IPython.Cell.prototype.unselect.apply(this);
130 IPython.Cell.prototype.unselect.apply(this);
129 };
131 };
130
132
131 /**
133 /**
132 *
134 *
133 * put the current cell in edition mode
135 * put the current cell in edition mode
134 * @method edit
136 * @method edit
135 */
137 */
136 TextCell.prototype.edit = function () {
138 TextCell.prototype.edit = function () {
137 if ( this.read_only ) return;
139 if ( this.read_only ) return;
138 if (this.rendered === true) {
140 if (this.rendered === true) {
139 var text_cell = this.element;
141 var text_cell = this.element;
140 var output = text_cell.find("div.text_cell_render");
142 var output = text_cell.find("div.text_cell_render");
141 output.hide();
143 output.hide();
142 text_cell.find('div.text_cell_input').show();
144 text_cell.find('div.text_cell_input').show();
143 this.code_mirror.refresh();
145 this.code_mirror.refresh();
144 this.code_mirror.focus();
146 this.code_mirror.focus();
145 // We used to need an additional refresh() after the focus, but
147 // We used to need an additional refresh() after the focus, but
146 // it appears that this has been fixed in CM. This bug would show
148 // it appears that this has been fixed in CM. This bug would show
147 // up on FF when a newly loaded markdown cell was edited.
149 // up on FF when a newly loaded markdown cell was edited.
148 this.rendered = false;
150 this.rendered = false;
149 if (this.get_text() === this.placeholder) {
151 if (this.get_text() === this.placeholder) {
150 this.set_text('');
152 this.set_text('');
151 this.refresh();
153 this.refresh();
152 }
154 }
153 }
155 }
154 };
156 };
155
157
156
158
157 /**
159 /**
158 * Empty, Subclasses must define render.
160 * Empty, Subclasses must define render.
159 * @method render
161 * @method render
160 */
162 */
161 TextCell.prototype.render = function () {};
163 TextCell.prototype.render = function () {};
162
164
163
165
164 /**
166 /**
165 * setter: {{#crossLink "TextCell/set_text"}}{{/crossLink}}
167 * setter: {{#crossLink "TextCell/set_text"}}{{/crossLink}}
166 * @method get_text
168 * @method get_text
167 * @retrun {string} CodeMirror current text value
169 * @retrun {string} CodeMirror current text value
168 */
170 */
169 TextCell.prototype.get_text = function() {
171 TextCell.prototype.get_text = function() {
170 return this.code_mirror.getValue();
172 return this.code_mirror.getValue();
171 };
173 };
172
174
173 /**
175 /**
174 * @param {string} text - Codemiror text value
176 * @param {string} text - Codemiror text value
175 * @see TextCell#get_text
177 * @see TextCell#get_text
176 * @method set_text
178 * @method set_text
177 * */
179 * */
178 TextCell.prototype.set_text = function(text) {
180 TextCell.prototype.set_text = function(text) {
179 this.code_mirror.setValue(text);
181 this.code_mirror.setValue(text);
180 this.code_mirror.refresh();
182 this.code_mirror.refresh();
181 };
183 };
182
184
183 /**
185 /**
184 * setter :{{#crossLink "TextCell/set_rendered"}}{{/crossLink}}
186 * setter :{{#crossLink "TextCell/set_rendered"}}{{/crossLink}}
185 * @method get_rendered
187 * @method get_rendered
186 * @return {html} html of rendered element
188 * @return {html} html of rendered element
187 * */
189 * */
188 TextCell.prototype.get_rendered = function() {
190 TextCell.prototype.get_rendered = function() {
189 return this.element.find('div.text_cell_render').html();
191 return this.element.find('div.text_cell_render').html();
190 };
192 };
191
193
192 /**
194 /**
193 * @method set_rendered
195 * @method set_rendered
194 */
196 */
195 TextCell.prototype.set_rendered = function(text) {
197 TextCell.prototype.set_rendered = function(text) {
196 this.element.find('div.text_cell_render').html(text);
198 this.element.find('div.text_cell_render').html(text);
197 };
199 };
198
200
199 /**
201 /**
200 * not deprecated, but implementation wrong
202 * not deprecated, but implementation wrong
201 * @method at_top
203 * @method at_top
202 * @deprecated
204 * @deprecated
203 * @return {Boolean} true is cell rendered, false otherwise
205 * @return {Boolean} true is cell rendered, false otherwise
204 * I doubt this is what it is supposed to do
206 * I doubt this is what it is supposed to do
205 * this implementation is completly false
207 * this implementation is completly false
206 */
208 */
207 TextCell.prototype.at_top = function () {
209 TextCell.prototype.at_top = function () {
208 if (this.rendered) {
210 if (this.rendered) {
209 return true;
211 return true;
210 } else {
212 } else {
211 return false;
213 return false;
212 }
214 }
213 };
215 };
214
216
215
217
216 /**
218 /**
217 * not deprecated, but implementation wrong
219 * not deprecated, but implementation wrong
218 * @method at_bottom
220 * @method at_bottom
219 * @deprecated
221 * @deprecated
220 * @return {Boolean} true is cell rendered, false otherwise
222 * @return {Boolean} true is cell rendered, false otherwise
221 * I doubt this is what it is supposed to do
223 * I doubt this is what it is supposed to do
222 * this implementation is completly false
224 * this implementation is completly false
223 * */
225 * */
224 TextCell.prototype.at_bottom = function () {
226 TextCell.prototype.at_bottom = function () {
225 if (this.rendered) {
227 if (this.rendered) {
226 return true;
228 return true;
227 } else {
229 } else {
228 return false;
230 return false;
229 }
231 }
230 };
232 };
231
233
232 /**
234 /**
233 * Create Text cell from JSON
235 * Create Text cell from JSON
234 * @param {json} data - JSON serialized text-cell
236 * @param {json} data - JSON serialized text-cell
235 * @method fromJSON
237 * @method fromJSON
236 */
238 */
237 TextCell.prototype.fromJSON = function (data) {
239 TextCell.prototype.fromJSON = function (data) {
238 IPython.Cell.prototype.fromJSON.apply(this, arguments);
240 IPython.Cell.prototype.fromJSON.apply(this, arguments);
239 if (data.cell_type === this.cell_type) {
241 if (data.cell_type === this.cell_type) {
240 if (data.source !== undefined) {
242 if (data.source !== undefined) {
241 this.set_text(data.source);
243 this.set_text(data.source);
242 // make this value the starting point, so that we can only undo
244 // make this value the starting point, so that we can only undo
243 // to this state, instead of a blank cell
245 // to this state, instead of a blank cell
244 this.code_mirror.clearHistory();
246 this.code_mirror.clearHistory();
245 this.set_rendered(data.rendered || '');
247 this.set_rendered(data.rendered || '');
246 this.rendered = false;
248 this.rendered = false;
247 this.render();
249 this.render();
248 }
250 }
249 }
251 }
250 };
252 };
251
253
252 /** Generate JSON from cell
254 /** Generate JSON from cell
253 * @return {object} cell data serialised to json
255 * @return {object} cell data serialised to json
254 */
256 */
255 TextCell.prototype.toJSON = function () {
257 TextCell.prototype.toJSON = function () {
256 var data = IPython.Cell.prototype.toJSON.apply(this);
258 var data = IPython.Cell.prototype.toJSON.apply(this);
257 data.cell_type = this.cell_type;
259 data.cell_type = this.cell_type;
258 data.source = this.get_text();
260 data.source = this.get_text();
259 return data;
261 return data;
260 };
262 };
261
263
262
264
263 /**
265 /**
264 * @constructor HtmlCell
266 * @constructor HtmlCell
265 * @class HtmlCell
267 * @class HtmlCell
266 * @extends Ipython.TextCell
268 * @extends Ipython.TextCell
267 */
269 */
268 var HTMLCell = function () {
270 var HTMLCell = function () {
269 this.placeholder = "Type <strong>HTML</strong> and LaTeX: $\\alpha^2$";
271 this.placeholder = "Type <strong>HTML</strong> and LaTeX: $\\alpha^2$";
270 IPython.TextCell.apply(this, arguments);
272 IPython.TextCell.apply(this, arguments);
271 this.cell_type = 'html';
273 this.cell_type = 'html';
272 };
274 };
273
275
274
276
275 HTMLCell.prototype = new TextCell();
277 HTMLCell.prototype = new TextCell();
276
278
277 /**
279 /**
278 * @method render
280 * @method render
279 */
281 */
280 HTMLCell.prototype.render = function () {
282 HTMLCell.prototype.render = function () {
281 if (this.rendered === false) {
283 if (this.rendered === false) {
282 var text = this.get_text();
284 var text = this.get_text();
283 if (text === "") { text = this.placeholder; }
285 if (text === "") { text = this.placeholder; }
284 this.set_rendered(text);
286 this.set_rendered(text);
285 this.typeset();
287 this.typeset();
286 this.element.find('div.text_cell_input').hide();
288 this.element.find('div.text_cell_input').hide();
287 this.element.find("div.text_cell_render").show();
289 this.element.find("div.text_cell_render").show();
288 this.rendered = true;
290 this.rendered = true;
289 }
291 }
290 };
292 };
291
293
292
294
293 /**
295 /**
294 * @class MarkdownCell
296 * @class MarkdownCell
295 * @constructor MarkdownCell
297 * @constructor MarkdownCell
296 * @extends Ipython.HtmlCell
298 * @extends Ipython.HtmlCell
297 */
299 */
298 var MarkdownCell = function () {
300 var MarkdownCell = function () {
299 this.placeholder = "Type *Markdown* and LaTeX: $\\alpha^2$";
301 this.placeholder = "Type *Markdown* and LaTeX: $\\alpha^2$";
300 IPython.TextCell.apply(this, arguments);
302 IPython.TextCell.apply(this, arguments);
301 this.cell_type = 'markdown';
303 this.cell_type = 'markdown';
302 };
304 };
303
305
304
306
305 MarkdownCell.prototype = new TextCell();
307 MarkdownCell.prototype = new TextCell();
306
308
307 /**
309 /**
308 * @method render
310 * @method render
309 */
311 */
310 MarkdownCell.prototype.render = function () {
312 MarkdownCell.prototype.render = function () {
311 if (this.rendered === false) {
313 if (this.rendered === false) {
312 var text = this.get_text();
314 var text = this.get_text();
313 if (text === "") { text = this.placeholder; }
315 if (text === "") { text = this.placeholder; }
314 text = IPython.mathjaxutils.remove_math(text)
316 text = IPython.mathjaxutils.remove_math(text)
315 var html = IPython.markdown_converter.makeHtml(text);
317 var html = IPython.markdown_converter.makeHtml(text);
316 html = IPython.mathjaxutils.replace_math(html)
318 html = IPython.mathjaxutils.replace_math(html)
317 try {
319 try {
318 this.set_rendered(html);
320 this.set_rendered(html);
319 } catch (e) {
321 } catch (e) {
320 console.log("Error running Javascript in Markdown:");
322 console.log("Error running Javascript in Markdown:");
321 console.log(e);
323 console.log(e);
322 this.set_rendered($("<div/>").addClass("js-error").html(
324 this.set_rendered($("<div/>").addClass("js-error").html(
323 "Error rendering Markdown!<br/>" + e.toString())
325 "Error rendering Markdown!<br/>" + e.toString())
324 );
326 );
325 }
327 }
326 this.element.find('div.text_cell_input').hide();
328 this.element.find('div.text_cell_input').hide();
327 this.element.find("div.text_cell_render").show();
329 this.element.find("div.text_cell_render").show();
328 var code_snippets = this.element.find("pre > code");
330 var code_snippets = this.element.find("pre > code");
329 code_snippets.replaceWith(function () {
331 code_snippets.replaceWith(function () {
330 var code = $(this).html();
332 var code = $(this).html();
331 /* Substitute br for newlines and &nbsp; for spaces
333 /* Substitute br for newlines and &nbsp; for spaces
332 before highlighting, since prettify doesn't
334 before highlighting, since prettify doesn't
333 preserve those on all browsers */
335 preserve those on all browsers */
334 code = code.replace(/(\r\n|\n|\r)/gm, "<br/>");
336 code = code.replace(/(\r\n|\n|\r)/gm, "<br/>");
335 code = code.replace(/ /gm, '&nbsp;');
337 code = code.replace(/ /gm, '&nbsp;');
336 code = prettyPrintOne(code);
338 code = prettyPrintOne(code);
337
339
338 return '<code class="prettyprint">' + code + '</code>';
340 return '<code class="prettyprint">' + code + '</code>';
339 });
341 });
340 this.typeset()
342 this.typeset()
341 this.rendered = true;
343 this.rendered = true;
342 }
344 }
343 };
345 };
344
346
345
347
346 // RawCell
348 // RawCell
347
349
348 /**
350 /**
349 * @class RawCell
351 * @class RawCell
350 * @constructor RawCell
352 * @constructor RawCell
351 * @extends Ipython.TextCell
353 * @extends Ipython.TextCell
352 */
354 */
353 var RawCell = function () {
355 var RawCell = function () {
354 this.placeholder = "Type plain text and LaTeX: $\\alpha^2$";
356 this.placeholder = "Type plain text and LaTeX: $\\alpha^2$";
355 this.code_mirror_mode = 'rst';
357 this.code_mirror_mode = 'rst';
356 IPython.TextCell.apply(this, arguments);
358 IPython.TextCell.apply(this, arguments);
357 this.cell_type = 'raw';
359 this.cell_type = 'raw';
358 var that = this
360 var that = this
359
361
360 this.element.focusout(
362 this.element.focusout(
361 function() { that.auto_highlight(); }
363 function() { that.auto_highlight(); }
362 );
364 );
363 };
365 };
364
366
365
367
366 RawCell.prototype = new TextCell();
368 RawCell.prototype = new TextCell();
367
369
368 /**
370 /**
369 * Trigger autodetection of highlight scheme for current cell
371 * Trigger autodetection of highlight scheme for current cell
370 * @method auto_highlight
372 * @method auto_highlight
371 */
373 */
372 RawCell.prototype.auto_highlight = function () {
374 RawCell.prototype.auto_highlight = function () {
373 this._auto_highlight(IPython.config.raw_cell_highlight);
375 this._auto_highlight(IPython.config.raw_cell_highlight);
374 };
376 };
375
377
376 /** @method render **/
378 /** @method render **/
377 RawCell.prototype.render = function () {
379 RawCell.prototype.render = function () {
378 this.rendered = true;
380 this.rendered = true;
379 this.edit();
381 this.edit();
380 };
382 };
381
383
382
384
383 /** @method handle_codemirror_keyevent **/
385 /** @method handle_codemirror_keyevent **/
384 RawCell.prototype.handle_codemirror_keyevent = function (editor, event) {
386 RawCell.prototype.handle_codemirror_keyevent = function (editor, event) {
385
387
386 var that = this;
388 var that = this;
387 if (event.which === key.UPARROW && event.type === 'keydown') {
389 if (event.which === key.UPARROW && event.type === 'keydown') {
388 // If we are not at the top, let CM handle the up arrow and
390 // If we are not at the top, let CM handle the up arrow and
389 // prevent the global keydown handler from handling it.
391 // prevent the global keydown handler from handling it.
390 if (!that.at_top()) {
392 if (!that.at_top()) {
391 event.stop();
393 event.stop();
392 return false;
394 return false;
393 } else {
395 } else {
394 return true;
396 return true;
395 };
397 };
396 } else if (event.which === key.DOWNARROW && event.type === 'keydown') {
398 } else if (event.which === key.DOWNARROW && event.type === 'keydown') {
397 // If we are not at the bottom, let CM handle the down arrow and
399 // If we are not at the bottom, let CM handle the down arrow and
398 // prevent the global keydown handler from handling it.
400 // prevent the global keydown handler from handling it.
399 if (!that.at_bottom()) {
401 if (!that.at_bottom()) {
400 event.stop();
402 event.stop();
401 return false;
403 return false;
402 } else {
404 } else {
403 return true;
405 return true;
404 };
406 };
405 };
407 };
406 return false;
408 return false;
407 };
409 };
408
410
409 /** @method select **/
411 /** @method select **/
410 RawCell.prototype.select = function () {
412 RawCell.prototype.select = function () {
411 IPython.Cell.prototype.select.apply(this);
413 IPython.Cell.prototype.select.apply(this);
412 this.code_mirror.refresh();
414 this.code_mirror.refresh();
413 this.code_mirror.focus();
415 this.code_mirror.focus();
414 };
416 };
415
417
416 /** @method at_top **/
418 /** @method at_top **/
417 RawCell.prototype.at_top = function () {
419 RawCell.prototype.at_top = function () {
418 var cursor = this.code_mirror.getCursor();
420 var cursor = this.code_mirror.getCursor();
419 if (cursor.line === 0 && cursor.ch === 0) {
421 if (cursor.line === 0 && cursor.ch === 0) {
420 return true;
422 return true;
421 } else {
423 } else {
422 return false;
424 return false;
423 }
425 }
424 };
426 };
425
427
426
428
427 /** @method at_bottom **/
429 /** @method at_bottom **/
428 RawCell.prototype.at_bottom = function () {
430 RawCell.prototype.at_bottom = function () {
429 var cursor = this.code_mirror.getCursor();
431 var cursor = this.code_mirror.getCursor();
430 if (cursor.line === (this.code_mirror.lineCount()-1) && cursor.ch === this.code_mirror.getLine(cursor.line).length) {
432 if (cursor.line === (this.code_mirror.lineCount()-1) && cursor.ch === this.code_mirror.getLine(cursor.line).length) {
431 return true;
433 return true;
432 } else {
434 } else {
433 return false;
435 return false;
434 }
436 }
435 };
437 };
436
438
437
439
438 /**
440 /**
439 * @class HeadingCell
441 * @class HeadingCell
440 * @extends Ipython.TextCell
442 * @extends Ipython.TextCell
441 */
443 */
442
444
443 /**
445 /**
444 * @constructor HeadingCell
446 * @constructor HeadingCell
445 * @extends Ipython.TextCell
447 * @extends Ipython.TextCell
446 */
448 */
447 var HeadingCell = function () {
449 var HeadingCell = function () {
448 this.placeholder = "Type Heading Here";
450 this.placeholder = "Type Heading Here";
449 IPython.TextCell.apply(this, arguments);
451 IPython.TextCell.apply(this, arguments);
450 /**
452 /**
451 * heading level of the cell, use getter and setter to access
453 * heading level of the cell, use getter and setter to access
452 * @property level
454 * @property level
453 */
455 */
454 this.level = 1;
456 this.level = 1;
455 this.cell_type = 'heading';
457 this.cell_type = 'heading';
456 };
458 };
457
459
458
460
459 HeadingCell.prototype = new TextCell();
461 HeadingCell.prototype = new TextCell();
460
462
461 /** @method fromJSON */
463 /** @method fromJSON */
462 HeadingCell.prototype.fromJSON = function (data) {
464 HeadingCell.prototype.fromJSON = function (data) {
463 if (data.level != undefined){
465 if (data.level != undefined){
464 this.level = data.level;
466 this.level = data.level;
465 }
467 }
466 IPython.TextCell.prototype.fromJSON.apply(this, arguments);
468 IPython.TextCell.prototype.fromJSON.apply(this, arguments);
467 };
469 };
468
470
469
471
470 /** @method toJSON */
472 /** @method toJSON */
471 HeadingCell.prototype.toJSON = function () {
473 HeadingCell.prototype.toJSON = function () {
472 var data = IPython.TextCell.prototype.toJSON.apply(this);
474 var data = IPython.TextCell.prototype.toJSON.apply(this);
473 data.level = this.get_level();
475 data.level = this.get_level();
474 return data;
476 return data;
475 };
477 };
476
478
477
479
478 /**
480 /**
479 * Change heading level of cell, and re-render
481 * Change heading level of cell, and re-render
480 * @method set_level
482 * @method set_level
481 */
483 */
482 HeadingCell.prototype.set_level = function (level) {
484 HeadingCell.prototype.set_level = function (level) {
483 this.level = level;
485 this.level = level;
484 if (this.rendered) {
486 if (this.rendered) {
485 this.rendered = false;
487 this.rendered = false;
486 this.render();
488 this.render();
487 };
489 };
488 };
490 };
489
491
490 /** The depth of header cell, based on html (h1 to h6)
492 /** The depth of header cell, based on html (h1 to h6)
491 * @method get_level
493 * @method get_level
492 * @return {integer} level - for 1 to 6
494 * @return {integer} level - for 1 to 6
493 */
495 */
494 HeadingCell.prototype.get_level = function () {
496 HeadingCell.prototype.get_level = function () {
495 return this.level;
497 return this.level;
496 };
498 };
497
499
498
500
499 HeadingCell.prototype.set_rendered = function (text) {
501 HeadingCell.prototype.set_rendered = function (text) {
500 var r = this.element.find("div.text_cell_render");
502 var r = this.element.find("div.text_cell_render");
501 r.empty();
503 r.empty();
502 r.append($('<h'+this.level+'/>').html(text));
504 r.append($('<h'+this.level+'/>').html(text));
503 };
505 };
504
506
505
507
506 HeadingCell.prototype.get_rendered = function () {
508 HeadingCell.prototype.get_rendered = function () {
507 var r = this.element.find("div.text_cell_render");
509 var r = this.element.find("div.text_cell_render");
508 return r.children().first().html();
510 return r.children().first().html();
509 };
511 };
510
512
511
513
512 HeadingCell.prototype.render = function () {
514 HeadingCell.prototype.render = function () {
513 if (this.rendered === false) {
515 if (this.rendered === false) {
514 var text = this.get_text();
516 var text = this.get_text();
515 if (text === "") { text = this.placeholder; }
517 if (text === "") { text = this.placeholder; }
516 this.set_rendered(text);
518 this.set_rendered(text);
517 this.typeset();
519 this.typeset();
518 this.element.find('div.text_cell_input').hide();
520 this.element.find('div.text_cell_input').hide();
519 this.element.find("div.text_cell_render").show();
521 this.element.find("div.text_cell_render").show();
520 this.rendered = true;
522 this.rendered = true;
521 };
523 };
522 };
524 };
523
525
524 IPython.TextCell = TextCell;
526 IPython.TextCell = TextCell;
525 IPython.HTMLCell = HTMLCell;
527 IPython.HTMLCell = HTMLCell;
526 IPython.MarkdownCell = MarkdownCell;
528 IPython.MarkdownCell = MarkdownCell;
527 IPython.RawCell = RawCell;
529 IPython.RawCell = RawCell;
528 IPython.HeadingCell = HeadingCell;
530 IPython.HeadingCell = HeadingCell;
529
531
530
532
531 return IPython;
533 return IPython;
532
534
533 }(IPython));
535 }(IPython));
534
536
General Comments 0
You need to be logged in to leave comments. Login now