##// END OF EJS Templates
rename metaui -> celltoolbar
Matthias BUSSONNIER -
Show More
@@ -1,54 +1,54 b''
1 /*Css for the metadata edit area*/
1 /*Css for the metadata edit area*/
2
2
3 .metaedit{
3 .celltoolbar{
4 border:thin solid #DDD;
4 border:thin solid #DDD;
5 margin-left:81px;
5 margin-left:81px;
6 border-bottom:none;
6 border-bottom:none;
7 background : #EEE;
7 background : #EEE;
8 border-top-right-radius: 3px;
8 border-top-right-radius: 3px;
9 border-top-left-radius: 3px;
9 border-top-left-radius: 3px;
10 display:none;
10 display:none;
11 }
11 }
12
12
13 .code_cell .metaedit{
13 .code_cell .celltoolbar{
14 margin-left:81px;
14 margin-left:81px;
15 }
15 }
16
16
17 .text_cell .metaedit{
17 .text_cell .celltoolbar{
18 margin-left:0px;
18 margin-left:0px;
19 }
19 }
20
20
21 .editmetaon div.input_area , .editmetaon div.text_cell_input{
21 .celltoolbar-on div.input_area , .celltoolbar-on div.text_cell_input{
22 border-top-right-radius: 0px;
22 border-top-right-radius: 0px;
23 border-top-left-radius: 0px;
23 border-top-left-radius: 0px;
24 }
24 }
25
25
26 .editmetaon .metaedit {
26 .celltoolbar-on .celltoolbar {
27 display:block;
27 display:block;
28 }
28 }
29
29
30 .metaedit ui-button {
30 .celltoolbar ui-button {
31 border :none;
31 border :none;
32 }
32 }
33
33
34 .button_container {
34 .button_container {
35 float:right;
35 float:right;
36 /*width:60px;*/
36 /*width:60px;*/
37 }
37 }
38
38
39 .button_container .ui-state-default, .button_container .ui-state-hover, .button_container .ui-state-hover span{
39 .button_container .ui-state-default, .button_container .ui-state-hover, .button_container .ui-state-hover span{
40 border-radius : 0 0 0 0;
40 border-radius : 0 0 0 0;
41 border : none;
41 border : none;
42 }
42 }
43
43
44 .metaedit select {
44 .celltoolbar select {
45 margin:10px;
45 margin:10px;
46 margin-top:0px;
46 margin-top:0px;
47 margin-bottom:0px;
47 margin-bottom:0px;
48 }
48 }
49
49
50 .metaedit input[type=checkbox] {
50 .celltoolbar input[type=checkbox] {
51 margin-bottom:1px;
51 margin-bottom:1px;
52
52
53 }
53 }
54
54
@@ -1,313 +1,313 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 // Cell
9 // Cell
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 Cell
15 * @submodule Cell
16 */
16 */
17
17
18 var IPython = (function (IPython) {
18 var IPython = (function (IPython) {
19
19
20 var utils = IPython.utils;
20 var utils = IPython.utils;
21
21
22 /**
22 /**
23 * The Base `Cell` class from which to inherit
23 * The Base `Cell` class from which to inherit
24 * @class Cell
24 * @class Cell
25 */
25 */
26
26
27 /*
27 /*
28 * @constructor
28 * @constructor
29 */
29 */
30 var Cell = function () {
30 var Cell = function () {
31 this.placeholder = this.placeholder || '';
31 this.placeholder = this.placeholder || '';
32 this.read_only = false;
32 this.read_only = false;
33 this.selected = false;
33 this.selected = false;
34 this.element = null;
34 this.element = null;
35 this.metadata = {};
35 this.metadata = {};
36 // load this from metadata later ?
36 // load this from metadata later ?
37 this.user_highlight = 'auto';
37 this.user_highlight = 'auto';
38 this.create_element();
38 this.create_element();
39 if (this.element !== null) {
39 if (this.element !== null) {
40 this.element.data("cell", this);
40 this.element.data("cell", this);
41 this.bind_events();
41 this.bind_events();
42 }
42 }
43 this.cell_id = utils.uuid();
43 this.cell_id = utils.uuid();
44 };
44 };
45
45
46
46
47 /**
47 /**
48 * Empty. Subclasses must implement create_element.
48 * Empty. Subclasses must implement create_element.
49 * This should contain all the code to create the DOM element in notebook
49 * This should contain all the code to create the DOM element in notebook
50 * and will be called by Base Class constructor.
50 * and will be called by Base Class constructor.
51 * @method create_element
51 * @method create_element
52 */
52 */
53 Cell.prototype.create_element = function () {};
53 Cell.prototype.create_element = function () {};
54
54
55
55
56 /**
56 /**
57 * Subclasses can implement override bind_events.
57 * Subclasses can implement override bind_events.
58 * Be carefull to call the parent method when overwriting as it fires event.
58 * Be carefull to call the parent method when overwriting as it fires event.
59 * this will be triggerd after create_element in constructor.
59 * this will be triggerd after create_element in constructor.
60 * @method bind_events
60 * @method bind_events
61 */
61 */
62 Cell.prototype.bind_events = function () {
62 Cell.prototype.bind_events = function () {
63 var that = this;
63 var that = this;
64 // We trigger events so that Cell doesn't have to depend on Notebook.
64 // We trigger events so that Cell doesn't have to depend on Notebook.
65 that.element.click(function (event) {
65 that.element.click(function (event) {
66 if (that.selected === false) {
66 if (that.selected === false) {
67 $([IPython.events]).trigger('select.Cell', {'cell':that});
67 $([IPython.events]).trigger('select.Cell', {'cell':that});
68 }
68 }
69 });
69 });
70 that.element.focusin(function (event) {
70 that.element.focusin(function (event) {
71 if (that.selected === false) {
71 if (that.selected === false) {
72 $([IPython.events]).trigger('select.Cell', {'cell':that});
72 $([IPython.events]).trigger('select.Cell', {'cell':that});
73 }
73 }
74 });
74 });
75 };
75 };
76
76
77 /**
77 /**
78 * Triger typsetting of math by mathjax on current cell element
78 * Triger typsetting of math by mathjax on current cell element
79 * @method typeset
79 * @method typeset
80 */
80 */
81 Cell.prototype.typeset = function () {
81 Cell.prototype.typeset = function () {
82 if (window.MathJax){
82 if (window.MathJax){
83 var cell_math = this.element.get(0);
83 var cell_math = this.element.get(0);
84 MathJax.Hub.Queue(["Typeset",MathJax.Hub,cell_math]);
84 MathJax.Hub.Queue(["Typeset",MathJax.Hub,cell_math]);
85 }
85 }
86 };
86 };
87
87
88 /**
88 /**
89 * should be triggerd when cell is selected
89 * should be triggerd when cell is selected
90 * @method select
90 * @method select
91 */
91 */
92 Cell.prototype.select = function () {
92 Cell.prototype.select = function () {
93 this.element.addClass('ui-widget-content ui-corner-all');
93 this.element.addClass('ui-widget-content ui-corner-all');
94 this.selected = true;
94 this.selected = true;
95 };
95 };
96
96
97
97
98 /**
98 /**
99 * should be triggerd when cell is unselected
99 * should be triggerd when cell is unselected
100 * @method unselect
100 * @method unselect
101 */
101 */
102 Cell.prototype.unselect = function () {
102 Cell.prototype.unselect = function () {
103 this.element.removeClass('ui-widget-content ui-corner-all');
103 this.element.removeClass('ui-widget-content ui-corner-all');
104 this.selected = false;
104 this.selected = false;
105 };
105 };
106
106
107 /**
107 /**
108 * should be overritten by subclass
108 * should be overritten by subclass
109 * @method get_text
109 * @method get_text
110 */
110 */
111 Cell.prototype.get_text = function () {
111 Cell.prototype.get_text = function () {
112 };
112 };
113
113
114 /**
114 /**
115 * should be overritten by subclass
115 * should be overritten by subclass
116 * @method set_text
116 * @method set_text
117 * @param {string} text
117 * @param {string} text
118 */
118 */
119 Cell.prototype.set_text = function (text) {
119 Cell.prototype.set_text = function (text) {
120 };
120 };
121
121
122 /**
122 /**
123 * Refresh codemirror instance
123 * Refresh codemirror instance
124 * @method refresh
124 * @method refresh
125 */
125 */
126 Cell.prototype.refresh = function () {
126 Cell.prototype.refresh = function () {
127 this.code_mirror.refresh();
127 this.code_mirror.refresh();
128 };
128 };
129
129
130
130
131 /**
131 /**
132 * should be overritten by subclass
132 * should be overritten by subclass
133 * @method edit
133 * @method edit
134 **/
134 **/
135 Cell.prototype.edit = function () {
135 Cell.prototype.edit = function () {
136 };
136 };
137
137
138
138
139 /**
139 /**
140 * should be overritten by subclass
140 * should be overritten by subclass
141 * @method render
141 * @method render
142 **/
142 **/
143 Cell.prototype.render = function () {
143 Cell.prototype.render = function () {
144 };
144 };
145
145
146 /**
146 /**
147 * should be overritten by subclass
147 * should be overritten by subclass
148 * serialise cell to json.
148 * serialise cell to json.
149 * @method toJSON
149 * @method toJSON
150 **/
150 **/
151 Cell.prototype.toJSON = function () {
151 Cell.prototype.toJSON = function () {
152 var data = {};
152 var data = {};
153 data.metadata = this.metadata;
153 data.metadata = this.metadata;
154 return data;
154 return data;
155 };
155 };
156
156
157
157
158 /**
158 /**
159 * should be overritten by subclass
159 * should be overritten by subclass
160 * @method fromJSON
160 * @method fromJSON
161 **/
161 **/
162 Cell.prototype.fromJSON = function (data) {
162 Cell.prototype.fromJSON = function (data) {
163 if (data.metadata !== undefined) {
163 if (data.metadata !== undefined) {
164 this.metadata = data.metadata;
164 this.metadata = data.metadata;
165 }
165 }
166 this.metaui.rebuild();
166 this.celltoolbar.rebuild();
167 };
167 };
168
168
169
169
170 /**
170 /**
171 * can the cell be splitted in 2 cells.
171 * can the cell be splitted in 2 cells.
172 * @method is_splittable
172 * @method is_splittable
173 **/
173 **/
174 Cell.prototype.is_splittable = function () {
174 Cell.prototype.is_splittable = function () {
175 return true;
175 return true;
176 };
176 };
177
177
178
178
179 /**
179 /**
180 * @return {String} - the text before the cursor
180 * @return {String} - the text before the cursor
181 * @method get_pre_cursor
181 * @method get_pre_cursor
182 **/
182 **/
183 Cell.prototype.get_pre_cursor = function () {
183 Cell.prototype.get_pre_cursor = function () {
184 var cursor = this.code_mirror.getCursor();
184 var cursor = this.code_mirror.getCursor();
185 var text = this.code_mirror.getRange({line:0,ch:0}, cursor);
185 var text = this.code_mirror.getRange({line:0,ch:0}, cursor);
186 text = text.replace(/^\n+/, '').replace(/\n+$/, '');
186 text = text.replace(/^\n+/, '').replace(/\n+$/, '');
187 return text;
187 return text;
188 }
188 }
189
189
190
190
191 /**
191 /**
192 * @return {String} - the text after the cursor
192 * @return {String} - the text after the cursor
193 * @method get_post_cursor
193 * @method get_post_cursor
194 **/
194 **/
195 Cell.prototype.get_post_cursor = function () {
195 Cell.prototype.get_post_cursor = function () {
196 var cursor = this.code_mirror.getCursor();
196 var cursor = this.code_mirror.getCursor();
197 var last_line_num = this.code_mirror.lineCount()-1;
197 var last_line_num = this.code_mirror.lineCount()-1;
198 var last_line_len = this.code_mirror.getLine(last_line_num).length;
198 var last_line_len = this.code_mirror.getLine(last_line_num).length;
199 var end = {line:last_line_num, ch:last_line_len}
199 var end = {line:last_line_num, ch:last_line_len}
200 var text = this.code_mirror.getRange(cursor, end);
200 var text = this.code_mirror.getRange(cursor, end);
201 text = text.replace(/^\n+/, '').replace(/\n+$/, '');
201 text = text.replace(/^\n+/, '').replace(/\n+$/, '');
202 return text;
202 return text;
203 };
203 };
204
204
205
205
206 /** Grow the cell by hand. This is used upon reloading from JSON, when the
206 /** Grow the cell by hand. This is used upon reloading from JSON, when the
207 * autogrow handler is not called.
207 * autogrow handler is not called.
208 *
208 *
209 * could be made static
209 * could be made static
210 *
210 *
211 * @param {Dom element} - element
211 * @param {Dom element} - element
212 * @method grow
212 * @method grow
213 **/
213 **/
214 Cell.prototype.grow = function(element) {
214 Cell.prototype.grow = function(element) {
215 var dom = element.get(0);
215 var dom = element.get(0);
216 var lines_count = 0;
216 var lines_count = 0;
217 // modified split rule from
217 // modified split rule from
218 // http://stackoverflow.com/questions/2035910/how-to-get-the-number-of-lines-in-a-textarea/2036424#2036424
218 // http://stackoverflow.com/questions/2035910/how-to-get-the-number-of-lines-in-a-textarea/2036424#2036424
219 var lines = dom.value.split(/\r|\r\n|\n/);
219 var lines = dom.value.split(/\r|\r\n|\n/);
220 lines_count = lines.length;
220 lines_count = lines.length;
221 if (lines_count >= 1) {
221 if (lines_count >= 1) {
222 dom.rows = lines_count;
222 dom.rows = lines_count;
223 } else {
223 } else {
224 dom.rows = 1;
224 dom.rows = 1;
225 }
225 }
226 };
226 };
227
227
228 /**
228 /**
229 * Toggle CodeMirror LineNumber
229 * Toggle CodeMirror LineNumber
230 * @method toggle_line_numbers
230 * @method toggle_line_numbers
231 **/
231 **/
232 Cell.prototype.toggle_line_numbers = function () {
232 Cell.prototype.toggle_line_numbers = function () {
233 if (this.code_mirror.getOption('lineNumbers') == false) {
233 if (this.code_mirror.getOption('lineNumbers') == false) {
234 this.code_mirror.setOption('lineNumbers', true);
234 this.code_mirror.setOption('lineNumbers', true);
235 } else {
235 } else {
236 this.code_mirror.setOption('lineNumbers', false);
236 this.code_mirror.setOption('lineNumbers', false);
237 }
237 }
238 this.code_mirror.refresh();
238 this.code_mirror.refresh();
239 };
239 };
240
240
241 /**
241 /**
242 * force codemirror highlight mode
242 * force codemirror highlight mode
243 * @method force_highlight
243 * @method force_highlight
244 * @param {object} - CodeMirror mode
244 * @param {object} - CodeMirror mode
245 **/
245 **/
246 Cell.prototype.force_highlight = function(mode) {
246 Cell.prototype.force_highlight = function(mode) {
247 this.user_highlight = mode;
247 this.user_highlight = mode;
248 this.auto_highlight();
248 this.auto_highlight();
249 };
249 };
250
250
251 /**
251 /**
252 * Try to autodetect cell highlight mode, or use selected mode
252 * Try to autodetect cell highlight mode, or use selected mode
253 * @methods _auto_highlight
253 * @methods _auto_highlight
254 * @private
254 * @private
255 * @param {String|object|undefined} - CodeMirror mode | 'auto'
255 * @param {String|object|undefined} - CodeMirror mode | 'auto'
256 **/
256 **/
257 Cell.prototype._auto_highlight = function (modes) {
257 Cell.prototype._auto_highlight = function (modes) {
258 //Here we handle manually selected modes
258 //Here we handle manually selected modes
259 if( this.user_highlight != undefined && this.user_highlight != 'auto' )
259 if( this.user_highlight != undefined && this.user_highlight != 'auto' )
260 {
260 {
261 var mode = this.user_highlight;
261 var mode = this.user_highlight;
262 CodeMirror.autoLoadMode(this.code_mirror, mode);
262 CodeMirror.autoLoadMode(this.code_mirror, mode);
263 this.code_mirror.setOption('mode', mode);
263 this.code_mirror.setOption('mode', mode);
264 return;
264 return;
265 }
265 }
266 var first_line = this.code_mirror.getLine(0);
266 var first_line = this.code_mirror.getLine(0);
267 // loop on every pairs
267 // loop on every pairs
268 for( var mode in modes) {
268 for( var mode in modes) {
269 var regs = modes[mode]['reg'];
269 var regs = modes[mode]['reg'];
270 // only one key every time but regexp can't be keys...
270 // only one key every time but regexp can't be keys...
271 for(var reg in regs ) {
271 for(var reg in regs ) {
272 // here we handle non magic_modes
272 // here we handle non magic_modes
273 if(first_line.match(regs[reg]) != null) {
273 if(first_line.match(regs[reg]) != null) {
274 if (mode.search('magic_') != 0) {
274 if (mode.search('magic_') != 0) {
275 this.code_mirror.setOption('mode',mode);
275 this.code_mirror.setOption('mode',mode);
276 CodeMirror.autoLoadMode(this.code_mirror, mode);
276 CodeMirror.autoLoadMode(this.code_mirror, mode);
277 return;
277 return;
278 }
278 }
279 var open = modes[mode]['open']|| "%%";
279 var open = modes[mode]['open']|| "%%";
280 var close = modes[mode]['close']|| "%%end";
280 var close = modes[mode]['close']|| "%%end";
281 var mmode = mode;
281 var mmode = mode;
282 mode = mmode.substr(6);
282 mode = mmode.substr(6);
283 CodeMirror.autoLoadMode(this.code_mirror, mode);
283 CodeMirror.autoLoadMode(this.code_mirror, mode);
284 // create on the fly a mode that swhitch between
284 // create on the fly a mode that swhitch between
285 // plain/text and smth else otherwise `%%` is
285 // plain/text and smth else otherwise `%%` is
286 // source of some highlight issues.
286 // source of some highlight issues.
287 // we use patchedGetMode to circumvent a bug in CM
287 // we use patchedGetMode to circumvent a bug in CM
288 CodeMirror.defineMode(mmode , function(config) {
288 CodeMirror.defineMode(mmode , function(config) {
289 return CodeMirror.multiplexingMode(
289 return CodeMirror.multiplexingMode(
290 CodeMirror.patchedGetMode(config, 'text/plain'),
290 CodeMirror.patchedGetMode(config, 'text/plain'),
291 // always set someting on close
291 // always set someting on close
292 {open: open, close: close,
292 {open: open, close: close,
293 mode: CodeMirror.patchedGetMode(config, mode),
293 mode: CodeMirror.patchedGetMode(config, mode),
294 delimStyle: "delimit"
294 delimStyle: "delimit"
295 }
295 }
296 );
296 );
297 });
297 });
298 this.code_mirror.setOption('mode', mmode);
298 this.code_mirror.setOption('mode', mmode);
299 return;
299 return;
300 }
300 }
301 }
301 }
302 }
302 }
303 // fallback on default (python)
303 // fallback on default (python)
304 var default_mode = this.default_mode || 'text/plain';
304 var default_mode = this.default_mode || 'text/plain';
305 this.code_mirror.setOption('mode', default_mode);
305 this.code_mirror.setOption('mode', default_mode);
306 };
306 };
307
307
308 IPython.Cell = Cell;
308 IPython.Cell = Cell;
309
309
310 return IPython;
310 return IPython;
311
311
312 }(IPython));
312 }(IPython));
313
313
@@ -1,381 +1,381 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 this.metaui = new IPython.MetaUI(this);
61 this.celltoolbar = new IPython.CellToolbar(this);
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.append(this.metaui.$element);
64 cell.append(this.celltoolbar.element);
65 cell.attr('tabindex','2');
65 cell.attr('tabindex','2');
66 var input = $('<div></div>').addClass('input hbox');
66 var input = $('<div></div>').addClass('input hbox');
67 input.append($('<div/>').addClass('prompt input_prompt'));
67 input.append($('<div/>').addClass('prompt input_prompt'));
68 var input_area = $('<div/>').addClass('input_area box-flex1');
68 var input_area = $('<div/>').addClass('input_area box-flex1');
69 this.code_mirror = CodeMirror(input_area.get(0), {
69 this.code_mirror = CodeMirror(input_area.get(0), {
70 indentUnit : 4,
70 indentUnit : 4,
71 mode: 'python',
71 mode: 'python',
72 theme: 'ipython',
72 theme: 'ipython',
73 readOnly: this.read_only,
73 readOnly: this.read_only,
74 extraKeys: {"Tab": "indentMore","Shift-Tab" : "indentLess",'Backspace':"delSpaceToPrevTabStop"},
74 extraKeys: {"Tab": "indentMore","Shift-Tab" : "indentLess",'Backspace':"delSpaceToPrevTabStop"},
75 onKeyEvent: $.proxy(this.handle_codemirror_keyevent,this),
75 onKeyEvent: $.proxy(this.handle_codemirror_keyevent,this),
76 matchBrackets: true
76 matchBrackets: true
77 });
77 });
78 input.append(input_area);
78 input.append(input_area);
79 var output = $('<div></div>');
79 var output = $('<div></div>');
80 cell.append(input).append(output);
80 cell.append(input).append(output);
81 this.element = cell;
81 this.element = cell;
82 this.output_area = new IPython.OutputArea(output, true);
82 this.output_area = new IPython.OutputArea(output, true);
83
83
84 // construct a completer only if class exist
84 // construct a completer only if class exist
85 // otherwise no print view
85 // otherwise no print view
86 if (IPython.Completer !== undefined)
86 if (IPython.Completer !== undefined)
87 {
87 {
88 this.completer = new IPython.Completer(this);
88 this.completer = new IPython.Completer(this);
89 }
89 }
90 };
90 };
91
91
92 /**
92 /**
93 * This method gets called in CodeMirror's onKeyDown/onKeyPress
93 * This method gets called in CodeMirror's onKeyDown/onKeyPress
94 * handlers and is used to provide custom key handling. Its return
94 * handlers and is used to provide custom key handling. Its return
95 * value is used to determine if CodeMirror should ignore the event:
95 * value is used to determine if CodeMirror should ignore the event:
96 * true = ignore, false = don't ignore.
96 * true = ignore, false = don't ignore.
97 * @method handle_codemirror_keyevent
97 * @method handle_codemirror_keyevent
98 */
98 */
99 CodeCell.prototype.handle_codemirror_keyevent = function (editor, event) {
99 CodeCell.prototype.handle_codemirror_keyevent = function (editor, event) {
100
100
101 if (this.read_only){
101 if (this.read_only){
102 return false;
102 return false;
103 }
103 }
104
104
105 var that = this;
105 var that = this;
106 // whatever key is pressed, first, cancel the tooltip request before
106 // whatever key is pressed, first, cancel the tooltip request before
107 // they are sent, and remove tooltip if any, except for tab again
107 // they are sent, and remove tooltip if any, except for tab again
108 if (event.type === 'keydown' && event.which != key.TAB ) {
108 if (event.type === 'keydown' && event.which != key.TAB ) {
109 IPython.tooltip.remove_and_cancel_tooltip();
109 IPython.tooltip.remove_and_cancel_tooltip();
110 };
110 };
111
111
112 var cur = editor.getCursor();
112 var cur = editor.getCursor();
113 if (event.keyCode === key.ENTER){
113 if (event.keyCode === key.ENTER){
114 this.auto_highlight();
114 this.auto_highlight();
115 }
115 }
116
116
117 if (event.keyCode === key.ENTER && (event.shiftKey || event.ctrlKey)) {
117 if (event.keyCode === key.ENTER && (event.shiftKey || event.ctrlKey)) {
118 // Always ignore shift-enter in CodeMirror as we handle it.
118 // Always ignore shift-enter in CodeMirror as we handle it.
119 return true;
119 return true;
120 } else if (event.which === 40 && event.type === 'keypress' && IPython.tooltip.time_before_tooltip >= 0) {
120 } else if (event.which === 40 && event.type === 'keypress' && IPython.tooltip.time_before_tooltip >= 0) {
121 // triger on keypress (!) otherwise inconsistent event.which depending on plateform
121 // triger on keypress (!) otherwise inconsistent event.which depending on plateform
122 // browser and keyboard layout !
122 // browser and keyboard layout !
123 // Pressing '(' , request tooltip, don't forget to reappend it
123 // Pressing '(' , request tooltip, don't forget to reappend it
124 IPython.tooltip.pending(that);
124 IPython.tooltip.pending(that);
125 } else if (event.which === key.UPARROW && event.type === 'keydown') {
125 } else if (event.which === key.UPARROW && event.type === 'keydown') {
126 // If we are not at the top, let CM handle the up arrow and
126 // If we are not at the top, let CM handle the up arrow and
127 // prevent the global keydown handler from handling it.
127 // prevent the global keydown handler from handling it.
128 if (!that.at_top()) {
128 if (!that.at_top()) {
129 event.stop();
129 event.stop();
130 return false;
130 return false;
131 } else {
131 } else {
132 return true;
132 return true;
133 };
133 };
134 } else if (event.which === key.ESC) {
134 } else if (event.which === key.ESC) {
135 IPython.tooltip.remove_and_cancel_tooltip(true);
135 IPython.tooltip.remove_and_cancel_tooltip(true);
136 return true;
136 return true;
137 } else if (event.which === key.DOWNARROW && event.type === 'keydown') {
137 } else if (event.which === key.DOWNARROW && event.type === 'keydown') {
138 // If we are not at the bottom, let CM handle the down arrow and
138 // If we are not at the bottom, let CM handle the down arrow and
139 // prevent the global keydown handler from handling it.
139 // prevent the global keydown handler from handling it.
140 if (!that.at_bottom()) {
140 if (!that.at_bottom()) {
141 event.stop();
141 event.stop();
142 return false;
142 return false;
143 } else {
143 } else {
144 return true;
144 return true;
145 };
145 };
146 } else if (event.keyCode === key.TAB && event.type == 'keydown' && event.shiftKey) {
146 } else if (event.keyCode === key.TAB && event.type == 'keydown' && event.shiftKey) {
147 if (editor.somethingSelected()){
147 if (editor.somethingSelected()){
148 var anchor = editor.getCursor("anchor");
148 var anchor = editor.getCursor("anchor");
149 var head = editor.getCursor("head");
149 var head = editor.getCursor("head");
150 if( anchor.line != head.line){
150 if( anchor.line != head.line){
151 return false;
151 return false;
152 }
152 }
153 }
153 }
154 IPython.tooltip.request(that);
154 IPython.tooltip.request(that);
155 event.stop();
155 event.stop();
156 return true;
156 return true;
157 } else if (event.keyCode === key.TAB && event.type == 'keydown') {
157 } else if (event.keyCode === key.TAB && event.type == 'keydown') {
158 // Tab completion.
158 // Tab completion.
159 //Do not trim here because of tooltip
159 //Do not trim here because of tooltip
160 if (editor.somethingSelected()){return false}
160 if (editor.somethingSelected()){return false}
161 var pre_cursor = editor.getRange({line:cur.line,ch:0},cur);
161 var pre_cursor = editor.getRange({line:cur.line,ch:0},cur);
162 if (pre_cursor.trim() === "") {
162 if (pre_cursor.trim() === "") {
163 // Don't autocomplete if the part of the line before the cursor
163 // Don't autocomplete if the part of the line before the cursor
164 // is empty. In this case, let CodeMirror handle indentation.
164 // is empty. In this case, let CodeMirror handle indentation.
165 return false;
165 return false;
166 } else if ((pre_cursor.substr(-1) === "("|| pre_cursor.substr(-1) === " ") && IPython.config.tooltip_on_tab ) {
166 } else if ((pre_cursor.substr(-1) === "("|| pre_cursor.substr(-1) === " ") && IPython.config.tooltip_on_tab ) {
167 IPython.tooltip.request(that);
167 IPython.tooltip.request(that);
168 // Prevent the event from bubbling up.
168 // Prevent the event from bubbling up.
169 event.stop();
169 event.stop();
170 // Prevent CodeMirror from handling the tab.
170 // Prevent CodeMirror from handling the tab.
171 return true;
171 return true;
172 } else {
172 } else {
173 event.stop();
173 event.stop();
174 this.completer.startCompletion();
174 this.completer.startCompletion();
175 return true;
175 return true;
176 };
176 };
177 } else {
177 } else {
178 // keypress/keyup also trigger on TAB press, and we don't want to
178 // keypress/keyup also trigger on TAB press, and we don't want to
179 // use those to disable tab completion.
179 // use those to disable tab completion.
180 return false;
180 return false;
181 };
181 };
182 return false;
182 return false;
183 };
183 };
184
184
185
185
186 // Kernel related calls.
186 // Kernel related calls.
187
187
188 CodeCell.prototype.set_kernel = function (kernel) {
188 CodeCell.prototype.set_kernel = function (kernel) {
189 this.kernel = kernel;
189 this.kernel = kernel;
190 }
190 }
191
191
192 /**
192 /**
193 * Execute current code cell to the kernel
193 * Execute current code cell to the kernel
194 * @method execute
194 * @method execute
195 */
195 */
196 CodeCell.prototype.execute = function () {
196 CodeCell.prototype.execute = function () {
197 this.output_area.clear_output(true, true, true);
197 this.output_area.clear_output(true, true, true);
198 this.set_input_prompt('*');
198 this.set_input_prompt('*');
199 this.element.addClass("running");
199 this.element.addClass("running");
200 var callbacks = {
200 var callbacks = {
201 'execute_reply': $.proxy(this._handle_execute_reply, this),
201 'execute_reply': $.proxy(this._handle_execute_reply, this),
202 'output': $.proxy(this.output_area.handle_output, this.output_area),
202 'output': $.proxy(this.output_area.handle_output, this.output_area),
203 'clear_output': $.proxy(this.output_area.handle_clear_output, this.output_area),
203 'clear_output': $.proxy(this.output_area.handle_clear_output, this.output_area),
204 'set_next_input': $.proxy(this._handle_set_next_input, this)
204 'set_next_input': $.proxy(this._handle_set_next_input, this)
205 };
205 };
206 var msg_id = this.kernel.execute(this.get_text(), callbacks, {silent: false});
206 var msg_id = this.kernel.execute(this.get_text(), callbacks, {silent: false});
207 };
207 };
208
208
209 /**
209 /**
210 * @method _handle_execute_reply
210 * @method _handle_execute_reply
211 * @private
211 * @private
212 */
212 */
213 CodeCell.prototype._handle_execute_reply = function (content) {
213 CodeCell.prototype._handle_execute_reply = function (content) {
214 this.set_input_prompt(content.execution_count);
214 this.set_input_prompt(content.execution_count);
215 this.element.removeClass("running");
215 this.element.removeClass("running");
216 $([IPython.events]).trigger('set_dirty.Notebook', {'value': true});
216 $([IPython.events]).trigger('set_dirty.Notebook', {'value': true});
217 }
217 }
218
218
219 CodeCell.prototype._handle_set_next_input = function (text) {
219 CodeCell.prototype._handle_set_next_input = function (text) {
220 var data = {'cell': this, 'text': text}
220 var data = {'cell': this, 'text': text}
221 $([IPython.events]).trigger('set_next_input.Notebook', data);
221 $([IPython.events]).trigger('set_next_input.Notebook', data);
222 }
222 }
223
223
224 // Basic cell manipulation.
224 // Basic cell manipulation.
225
225
226 CodeCell.prototype.select = function () {
226 CodeCell.prototype.select = function () {
227 IPython.Cell.prototype.select.apply(this);
227 IPython.Cell.prototype.select.apply(this);
228 this.code_mirror.refresh();
228 this.code_mirror.refresh();
229 this.code_mirror.focus();
229 this.code_mirror.focus();
230 this.auto_highlight();
230 this.auto_highlight();
231 // We used to need an additional refresh() after the focus, but
231 // We used to need an additional refresh() after the focus, but
232 // it appears that this has been fixed in CM. This bug would show
232 // it appears that this has been fixed in CM. This bug would show
233 // up on FF when a newly loaded markdown cell was edited.
233 // up on FF when a newly loaded markdown cell was edited.
234 };
234 };
235
235
236
236
237 CodeCell.prototype.select_all = function () {
237 CodeCell.prototype.select_all = function () {
238 var start = {line: 0, ch: 0};
238 var start = {line: 0, ch: 0};
239 var nlines = this.code_mirror.lineCount();
239 var nlines = this.code_mirror.lineCount();
240 var last_line = this.code_mirror.getLine(nlines-1);
240 var last_line = this.code_mirror.getLine(nlines-1);
241 var end = {line: nlines-1, ch: last_line.length};
241 var end = {line: nlines-1, ch: last_line.length};
242 this.code_mirror.setSelection(start, end);
242 this.code_mirror.setSelection(start, end);
243 };
243 };
244
244
245
245
246 CodeCell.prototype.collapse = function () {
246 CodeCell.prototype.collapse = function () {
247 this.collapsed = true;
247 this.collapsed = true;
248 this.output_area.collapse();
248 this.output_area.collapse();
249 };
249 };
250
250
251
251
252 CodeCell.prototype.expand = function () {
252 CodeCell.prototype.expand = function () {
253 this.collapsed = false;
253 this.collapsed = false;
254 this.output_area.expand();
254 this.output_area.expand();
255 };
255 };
256
256
257
257
258 CodeCell.prototype.toggle_output = function () {
258 CodeCell.prototype.toggle_output = function () {
259 this.collapsed = Boolean(1 - this.collapsed);
259 this.collapsed = Boolean(1 - this.collapsed);
260 this.output_area.toggle_output();
260 this.output_area.toggle_output();
261 };
261 };
262
262
263
263
264 CodeCell.prototype.toggle_output_scroll = function () {
264 CodeCell.prototype.toggle_output_scroll = function () {
265 this.output_area.toggle_scroll();
265 this.output_area.toggle_scroll();
266 };
266 };
267
267
268
268
269 CodeCell.input_prompt_classical = function (prompt_value, lines_number) {
269 CodeCell.input_prompt_classical = function (prompt_value, lines_number) {
270 var ns = prompt_value || "&nbsp;";
270 var ns = prompt_value || "&nbsp;";
271 return 'In&nbsp;[' + ns + ']:'
271 return 'In&nbsp;[' + ns + ']:'
272 };
272 };
273
273
274 CodeCell.input_prompt_continuation = function (prompt_value, lines_number) {
274 CodeCell.input_prompt_continuation = function (prompt_value, lines_number) {
275 var html = [CodeCell.input_prompt_classical(prompt_value, lines_number)];
275 var html = [CodeCell.input_prompt_classical(prompt_value, lines_number)];
276 for(var i=1; i < lines_number; i++){html.push(['...:'])};
276 for(var i=1; i < lines_number; i++){html.push(['...:'])};
277 return html.join('</br>')
277 return html.join('</br>')
278 };
278 };
279
279
280 CodeCell.input_prompt_function = CodeCell.input_prompt_classical;
280 CodeCell.input_prompt_function = CodeCell.input_prompt_classical;
281
281
282
282
283 CodeCell.prototype.set_input_prompt = function (number) {
283 CodeCell.prototype.set_input_prompt = function (number) {
284 var nline = 1
284 var nline = 1
285 if( this.code_mirror != undefined) {
285 if( this.code_mirror != undefined) {
286 nline = this.code_mirror.lineCount();
286 nline = this.code_mirror.lineCount();
287 }
287 }
288 this.input_prompt_number = number;
288 this.input_prompt_number = number;
289 var prompt_html = CodeCell.input_prompt_function(this.input_prompt_number, nline);
289 var prompt_html = CodeCell.input_prompt_function(this.input_prompt_number, nline);
290 this.element.find('div.input_prompt').html(prompt_html);
290 this.element.find('div.input_prompt').html(prompt_html);
291 };
291 };
292
292
293
293
294 CodeCell.prototype.clear_input = function () {
294 CodeCell.prototype.clear_input = function () {
295 this.code_mirror.setValue('');
295 this.code_mirror.setValue('');
296 };
296 };
297
297
298
298
299 CodeCell.prototype.get_text = function () {
299 CodeCell.prototype.get_text = function () {
300 return this.code_mirror.getValue();
300 return this.code_mirror.getValue();
301 };
301 };
302
302
303
303
304 CodeCell.prototype.set_text = function (code) {
304 CodeCell.prototype.set_text = function (code) {
305 return this.code_mirror.setValue(code);
305 return this.code_mirror.setValue(code);
306 };
306 };
307
307
308
308
309 CodeCell.prototype.at_top = function () {
309 CodeCell.prototype.at_top = function () {
310 var cursor = this.code_mirror.getCursor();
310 var cursor = this.code_mirror.getCursor();
311 if (cursor.line === 0 && cursor.ch === 0) {
311 if (cursor.line === 0 && cursor.ch === 0) {
312 return true;
312 return true;
313 } else {
313 } else {
314 return false;
314 return false;
315 }
315 }
316 };
316 };
317
317
318
318
319 CodeCell.prototype.at_bottom = function () {
319 CodeCell.prototype.at_bottom = function () {
320 var cursor = this.code_mirror.getCursor();
320 var cursor = this.code_mirror.getCursor();
321 if (cursor.line === (this.code_mirror.lineCount()-1) && cursor.ch === this.code_mirror.getLine(cursor.line).length) {
321 if (cursor.line === (this.code_mirror.lineCount()-1) && cursor.ch === this.code_mirror.getLine(cursor.line).length) {
322 return true;
322 return true;
323 } else {
323 } else {
324 return false;
324 return false;
325 }
325 }
326 };
326 };
327
327
328
328
329 CodeCell.prototype.clear_output = function (stdout, stderr, other) {
329 CodeCell.prototype.clear_output = function (stdout, stderr, other) {
330 this.output_area.clear_output(stdout, stderr, other);
330 this.output_area.clear_output(stdout, stderr, other);
331 };
331 };
332
332
333
333
334 // JSON serialization
334 // JSON serialization
335
335
336 CodeCell.prototype.fromJSON = function (data) {
336 CodeCell.prototype.fromJSON = function (data) {
337 IPython.Cell.prototype.fromJSON.apply(this, arguments);
337 IPython.Cell.prototype.fromJSON.apply(this, arguments);
338 if (data.cell_type === 'code') {
338 if (data.cell_type === 'code') {
339 if (data.input !== undefined) {
339 if (data.input !== undefined) {
340 this.set_text(data.input);
340 this.set_text(data.input);
341 // make this value the starting point, so that we can only undo
341 // make this value the starting point, so that we can only undo
342 // to this state, instead of a blank cell
342 // to this state, instead of a blank cell
343 this.code_mirror.clearHistory();
343 this.code_mirror.clearHistory();
344 this.auto_highlight();
344 this.auto_highlight();
345 }
345 }
346 if (data.prompt_number !== undefined) {
346 if (data.prompt_number !== undefined) {
347 this.set_input_prompt(data.prompt_number);
347 this.set_input_prompt(data.prompt_number);
348 } else {
348 } else {
349 this.set_input_prompt();
349 this.set_input_prompt();
350 };
350 };
351 this.output_area.fromJSON(data.outputs);
351 this.output_area.fromJSON(data.outputs);
352 if (data.collapsed !== undefined) {
352 if (data.collapsed !== undefined) {
353 if (data.collapsed) {
353 if (data.collapsed) {
354 this.collapse();
354 this.collapse();
355 } else {
355 } else {
356 this.expand();
356 this.expand();
357 };
357 };
358 };
358 };
359 };
359 };
360 };
360 };
361
361
362
362
363 CodeCell.prototype.toJSON = function () {
363 CodeCell.prototype.toJSON = function () {
364 var data = IPython.Cell.prototype.toJSON.apply(this);
364 var data = IPython.Cell.prototype.toJSON.apply(this);
365 data.input = this.get_text();
365 data.input = this.get_text();
366 data.cell_type = 'code';
366 data.cell_type = 'code';
367 if (this.input_prompt_number) {
367 if (this.input_prompt_number) {
368 data.prompt_number = this.input_prompt_number;
368 data.prompt_number = this.input_prompt_number;
369 };
369 };
370 var outputs = this.output_area.toJSON();
370 var outputs = this.output_area.toJSON();
371 data.outputs = outputs;
371 data.outputs = outputs;
372 data.language = 'python';
372 data.language = 'python';
373 data.collapsed = this.collapsed;
373 data.collapsed = this.collapsed;
374 return data;
374 return data;
375 };
375 };
376
376
377
377
378 IPython.CodeCell = CodeCell;
378 IPython.CodeCell = CodeCell;
379
379
380 return IPython;
380 return IPython;
381 }(IPython));
381 }(IPython));
@@ -1,47 +1,47 b''
1 // leave at least 2 line with only a star on it below, or doc generation fails
1 // leave at least 2 line with only a star on it below, or doc generation fails
2 /**
2 /**
3 *
3 *
4 *
4 *
5 * Placeholder for custom user javascript
5 * Placeholder for custom user javascript
6 * mainly to be overridden in profile/static/js/custom.js
6 * mainly to be overridden in profile/static/js/custom.js
7 * This will always be an empty file in IPython
7 * This will always be an empty file in IPython
8 *
8 *
9 * User could add any javascript in the `profile/static/js/custom.js` file
9 * User could add any javascript in the `profile/static/js/custom.js` file
10 * (and should create it if it does not exist).
10 * (and should create it if it does not exist).
11 * It will be executed by the ipython notebook at load time.
11 * It will be executed by the ipython notebook at load time.
12 *
12 *
13 * Same thing with `profile/static/css/custom.css` to inject custom css into the notebook.
13 * Same thing with `profile/static/css/custom.css` to inject custom css into the notebook.
14 *
14 *
15 * Example :
15 * Example :
16 *
16 *
17 * Create a custom button in toolbar that execute `%qtconsole` in kernel
17 * Create a custom button in toolbar that execute `%qtconsole` in kernel
18 * and hence open a qtconsole attached to the same kernel as the current notebook
18 * and hence open a qtconsole attached to the same kernel as the current notebook
19 *
19 *
20 * $([IPython.events]).on('notebook_loaded.Notebook', function(){
20 * $([IPython.events]).on('notebook_loaded.Notebook', function(){
21 * IPython.toolbar.add_buttons_group([
21 * IPython.toolbar.add_buttons_group([
22 * {
22 * {
23 * 'label' : 'run qtconsole',
23 * 'label' : 'run qtconsole',
24 * 'icon' : 'ui-icon-calculator', // select your icon from http://jqueryui.com/themeroller/
24 * 'icon' : 'ui-icon-calculator', // select your icon from http://jqueryui.com/themeroller/
25 * 'callback': function(){IPython.notebook.kernel.execute('%qtconsole')}
25 * 'callback': function(){IPython.notebook.kernel.execute('%qtconsole')}
26 * }
26 * }
27 * // add more button here if needed.
27 * // add more button here if needed.
28 * ]);
28 * ]);
29 * });
29 * });
30 *
30 *
31 * Example :
31 * Example :
32 *
32 *
33 * Use `jQuery.getScript(url [, success(script, textStatus, jqXHR)] );`
33 * Use `jQuery.getScript(url [, success(script, textStatus, jqXHR)] );`
34 * to load custom script into the notebook.
34 * to load custom script into the notebook.
35 *
35 *
36 * // to load the metadata ui extension example.
36 * // to load the metadata ui extension example.
37 * $.getScript('/static/js/examples/metaui.example.js');
37 * $.getScript('/static/js/examples/celltoolbar.example.js');
38 * // or
38 * // or
39 * // to load the metadata ui extension to control slideshow mode / reveal js for nbconvert
39 * // to load the metadata ui extension to control slideshow mode / reveal js for nbconvert
40 * $.getScript('/static/js/examples/metaui.slideshow.js');
40 * $.getScript('/static/js/examples/celltoolbar.slideshow.js');
41 *
41 *
42 *
42 *
43 * @module IPython
43 * @module IPython
44 * @namespace IPython
44 * @namespace IPython
45 * @class customjs
45 * @class customjs
46 * @static
46 * @static
47 */
47 */
@@ -1,184 +1,184 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 // MetaUI Example
9 // CellToolbar Example
10 //============================================================================
10 //============================================================================
11
11
12 /**
12 /**
13 * Example Use for the MetaUI library
13 * Example Use for the CellToolbar library
14 * add the following to your custom.js to load
14 * add the following to your custom.js to load
15 * metadata UI for slideshow
15 * Celltoolbar UI for slideshow
16 *
16 *
17 * ```
17 * ```
18 * $.getScript('/static/js/examples/metaui.example.js');
18 * $.getScript('/static/js/examples/celltoolbar.example.js');
19 * ```
19 * ```
20 */
20 */
21 // IIFE without asignement, we don't modifiy the IPython namespace
21 // IIFE without asignement, we don't modifiy the IPython namespace
22 (function (IPython) {
22 (function (IPython) {
23 "use strict";
23 "use strict";
24
24
25 var MetaUI = IPython.MetaUI;
25 var CellToolbar = IPython.CellToolbar;
26
26
27
27
28 var raw_edit = function(cell){
28 var raw_edit = function(cell){
29
29
30 var md = cell.metadata
30 var md = cell.metadata
31
31
32 var textarea = $('<textarea/>')
32 var textarea = $('<textarea/>')
33 .attr('rows','13')
33 .attr('rows','13')
34 .attr('cols','75')
34 .attr('cols','75')
35 .attr('name','metadata')
35 .attr('name','metadata')
36 .text(JSON.stringify(md, null,4)||'');
36 .text(JSON.stringify(md, null,4)||'');
37 var dialogform = $('<div/>').attr('title','Edit the metadata')
37 var dialogform = $('<div/>').attr('title','Edit the metadata')
38 .append(
38 .append(
39 $('<form/>').append(
39 $('<form/>').append(
40 $('<fieldset/>').append(
40 $('<fieldset/>').append(
41 $('<label/>')
41 $('<label/>')
42 .attr('for','metadata')
42 .attr('for','metadata')
43 .text("Metadata (I know what I'm dooing and I won't complain if it breaks my notebook)")
43 .text("Metadata (I know what I'm dooing and I won't complain if it breaks my notebook)")
44 )
44 )
45 .append($('<br/>'))
45 .append($('<br/>'))
46 .append(
46 .append(
47 textarea
47 textarea
48 )
48 )
49 )
49 )
50 );
50 );
51 var editor = CodeMirror.fromTextArea(textarea[0], {
51 var editor = CodeMirror.fromTextArea(textarea[0], {
52 lineNumbers: true,
52 lineNumbers: true,
53 matchBrackets: true,
53 matchBrackets: true,
54 });
54 });
55 $(dialogform).dialog({
55 $(dialogform).dialog({
56 autoOpen: true,
56 autoOpen: true,
57 height: 300,
57 height: 300,
58 width: 650,
58 width: 650,
59 modal: true,
59 modal: true,
60 buttons: {
60 buttons: {
61 "Ok": function() {
61 "Ok": function() {
62 //validate json and set it
62 //validate json and set it
63 try {
63 try {
64 var json = JSON.parse(editor.getValue());
64 var json = JSON.parse(editor.getValue());
65 cell.metadata = json;
65 cell.metadata = json;
66 $( this ).dialog( "close" );
66 $( this ).dialog( "close" );
67 }
67 }
68 catch(e)
68 catch(e)
69 {
69 {
70 alert('invalid json');
70 alert('invalid json');
71 }
71 }
72 },
72 },
73 Cancel: function() {
73 Cancel: function() {
74 $( this ).dialog( "close" );
74 $( this ).dialog( "close" );
75 }
75 }
76 },
76 },
77 close: function() {
77 close: function() {
78 //cleanup on close
78 //cleanup on close
79 $(this).remove();
79 $(this).remove();
80 }
80 }
81 });
81 });
82 editor.refresh();
82 editor.refresh();
83 }
83 }
84
84
85 var add_raw_edit_button = function(div, cell) {
85 var add_raw_edit_button = function(div, cell) {
86 var button_container = $(div)
86 var button_container = $(div)
87 var button = $('<div/>').button({label:'Raw Edit'})
87 var button = $('<div/>').button({label:'Raw Edit'})
88 .click(function(){raw_edit(cell); return false;})
88 .click(function(){raw_edit(cell); return false;})
89 button_container.append(button);
89 button_container.append(button);
90 }
90 }
91
91
92 MetaUI.register_callback('example.rawedit',add_raw_edit_button);
92 CellToolbar.register_callback('example.rawedit',add_raw_edit_button);
93 var example_preset = []
93 var example_preset = []
94 example_preset.push('example.rawedit');
94 example_preset.push('example.rawedit');
95
95
96
96
97 var simple_button = function(div, cell) {
97 var simple_button = function(div, cell) {
98 var button_container = $(div);
98 var button_container = $(div);
99 var button = $('<div/>').button({icons:{primary:'ui-icon-locked'}});
99 var button = $('<div/>').button({icons:{primary:'ui-icon-locked'}});
100 var fun = function(value){
100 var fun = function(value){
101 try{
101 try{
102 if(value){
102 if(value){
103 cell.code_mirror.setOption('readOnly','nocursor')
103 cell.code_mirror.setOption('readOnly','nocursor')
104 button.button('option','icons',{primary:'ui-icon-locked'})
104 button.button('option','icons',{primary:'ui-icon-locked'})
105 } else {
105 } else {
106 cell.code_mirror.setOption('readOnly','false')
106 cell.code_mirror.setOption('readOnly','false')
107 button.button('option','icons',{primary:'ui-icon-unlocked'})
107 button.button('option','icons',{primary:'ui-icon-unlocked'})
108 }
108 }
109 } catch(e){}
109 } catch(e){}
110
110
111 }
111 }
112 fun(cell.metadata.ro)
112 fun(cell.metadata.ro)
113 button.click(function(){
113 button.click(function(){
114 var v = cell.metadata.ro;
114 var v = cell.metadata.ro;
115 var locked = !v;
115 var locked = !v;
116 cell.metadata.ro = locked;
116 cell.metadata.ro = locked;
117 fun(locked)
117 fun(locked)
118 })
118 })
119 .css('height','16px')
119 .css('height','16px')
120 .css('width','35px');
120 .css('width','35px');
121 button_container.append(button);
121 button_container.append(button);
122 }
122 }
123
123
124 MetaUI.register_callback('example.lock',simple_button);
124 CellToolbar.register_callback('example.lock',simple_button);
125 example_preset.push('example.lock');
125 example_preset.push('example.lock');
126
126
127 var toggle_test = function(div, cell) {
127 var toggle_test = function(div, cell) {
128 var button_container = $(div)
128 var button_container = $(div)
129 var button = $('<div/>').button({label:String(cell.metadata.foo)});
129 var button = $('<div/>').button({label:String(cell.metadata.foo)});
130 button.click(function(){
130 button.click(function(){
131 var v = cell.metadata.foo;
131 var v = cell.metadata.foo;
132 cell.metadata.foo = !v;
132 cell.metadata.foo = !v;
133 button.button("option","label",String(!v));
133 button.button("option","label",String(!v));
134 })
134 })
135 button_container.append(button);
135 button_container.append(button);
136 }
136 }
137
137
138 MetaUI.register_callback('example.toggle',toggle_test);
138 CellToolbar.register_callback('example.toggle',toggle_test);
139 example_preset.push('example.toggle');
139 example_preset.push('example.toggle');
140
140
141 var checkbox_test = function(div, cell) {
141 var checkbox_test = function(div, cell) {
142 var button_container = $(div)
142 var button_container = $(div)
143
143
144 var chkb = $('<input/>').attr('type','checkbox');
144 var chkb = $('<input/>').attr('type','checkbox');
145 var lbl = $('<label/>').append($('<span/>').text('bar :').css('font-size','77%'));
145 var lbl = $('<label/>').append($('<span/>').text('bar :').css('font-size','77%'));
146 lbl.append(chkb);
146 lbl.append(chkb);
147 chkb.attr("checked",cell.metadata.bar);
147 chkb.attr("checked",cell.metadata.bar);
148 chkb.click(function(){
148 chkb.click(function(){
149 var v = cell.metadata.bar;
149 var v = cell.metadata.bar;
150 cell.metadata.bar = !v;
150 cell.metadata.bar = !v;
151 chkb.attr("checked",!v);
151 chkb.attr("checked",!v);
152 })
152 })
153 button_container.append($('<div/>').append(lbl));
153 button_container.append($('<div/>').append(lbl));
154
154
155 }
155 }
156
156
157 MetaUI.register_callback('example.checkbox',checkbox_test);
157 CellToolbar.register_callback('example.checkbox',checkbox_test);
158 example_preset.push('example.checkbox');
158 example_preset.push('example.checkbox');
159
159
160 var select_test = function(div, cell) {
160 var select_test = function(div, cell) {
161 var button_container = $(div)
161 var button_container = $(div)
162
162
163 var select = $('<select/>');
163 var select = $('<select/>');
164
164
165 select.append($('<option/>').attr('value','foo').text('foo'));
165 select.append($('<option/>').attr('value','foo').text('foo'));
166 select.append($('<option/>').attr('value','bar').text('bar'));
166 select.append($('<option/>').attr('value','bar').text('bar'));
167 select.append($('<option/>').attr('value','qux').text('qux'));
167 select.append($('<option/>').attr('value','qux').text('qux'));
168 select.append($('<option/>').attr('value','zip').text('zip'));
168 select.append($('<option/>').attr('value','zip').text('zip'));
169 select.val(cell.metadata.option);
169 select.val(cell.metadata.option);
170 select.change(function(){
170 select.change(function(){
171 cell.metadata.option = select.val();
171 cell.metadata.option = select.val();
172 });
172 });
173 button_container.append($('<div/>').append(select));
173 button_container.append($('<div/>').append(select));
174
174
175 }
175 }
176
176
177 MetaUI.register_callback('example.select',select_test);
177 CellToolbar.register_callback('example.select',select_test);
178 example_preset.push('example.select');
178 example_preset.push('example.select');
179
179
180 MetaUI.register_preset('example',example_preset);
180 CellToolbar.register_preset('example',example_preset);
181 MetaUI.set_preset('example');
181 CellToolbar.set_preset('example');
182 console.log('Example extension for metadata editting loaded.');
182 console.log('Example extension for metadata editting loaded.');
183
183
184 }(IPython));
184 }(IPython));
@@ -1,178 +1,178 b''
1 //----------------------------------------------------------------------------
1 //----------------------------------------------------------------------------
2 // Copyright (C) 2011 The IPython Development Team
2 // Copyright (C) 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 // ToolBar
9 // ToolBar
10 //============================================================================
10 //============================================================================
11
11
12 var IPython = (function (IPython) {
12 var IPython = (function (IPython) {
13
13
14 var MainToolBar = function (selector) {
14 var MainToolBar = function (selector) {
15 this.selector = selector;
15 this.selector = selector;
16 IPython.ToolBar.apply(this, arguments);
16 IPython.ToolBar.apply(this, arguments);
17 this.construct();
17 this.construct();
18 this.add_drop_down_list();
18 this.add_drop_down_list();
19 this.bind_events();
19 this.bind_events();
20 $(this.selector)
20 $(this.selector)
21 .append($('<label/>').text('MetaUI'))
21 .append($('<label/>').text('CellToolbar'))
22 .append(IPython.MetaUI.$dropdown_preset_selector)
22 .append(IPython.CellToolbar.dropdown_preset_element)
23 };
23 };
24
24
25 MainToolBar.prototype = new IPython.ToolBar();
25 MainToolBar.prototype = new IPython.ToolBar();
26
26
27 MainToolBar.prototype.construct = function () {
27 MainToolBar.prototype.construct = function () {
28 this.add_buttons_group([
28 this.add_buttons_group([
29 {
29 {
30 id : 'save_b',
30 id : 'save_b',
31 label : 'Save',
31 label : 'Save',
32 icon : 'ui-icon-disk',
32 icon : 'ui-icon-disk',
33 callback : function () {
33 callback : function () {
34 IPython.notebook.save_notebook();
34 IPython.notebook.save_notebook();
35 }
35 }
36 }
36 }
37 ]);
37 ]);
38 this.add_buttons_group([
38 this.add_buttons_group([
39 {
39 {
40 id : 'cut_b',
40 id : 'cut_b',
41 label : 'Cut Cell',
41 label : 'Cut Cell',
42 icon : 'ui-icon-scissors',
42 icon : 'ui-icon-scissors',
43 callback : function () {
43 callback : function () {
44 IPython.notebook.cut_cell();
44 IPython.notebook.cut_cell();
45 }
45 }
46 },
46 },
47 {
47 {
48 id : 'copy_b',
48 id : 'copy_b',
49 label : 'Copy Cell',
49 label : 'Copy Cell',
50 icon : 'ui-icon-copy',
50 icon : 'ui-icon-copy',
51 callback : function () {
51 callback : function () {
52 IPython.notebook.copy_cell();
52 IPython.notebook.copy_cell();
53 }
53 }
54 },
54 },
55 {
55 {
56 id : 'paste_b',
56 id : 'paste_b',
57 label : 'Paste Cell Below',
57 label : 'Paste Cell Below',
58 icon : 'ui-icon-clipboard',
58 icon : 'ui-icon-clipboard',
59 callback : function () {
59 callback : function () {
60 IPython.notebook.paste_cell_below();
60 IPython.notebook.paste_cell_below();
61 }
61 }
62 }
62 }
63 ],'cut_copy_paste');
63 ],'cut_copy_paste');
64
64
65 this.add_buttons_group([
65 this.add_buttons_group([
66 {
66 {
67 id : 'move_up_b',
67 id : 'move_up_b',
68 label : 'Move Cell Up',
68 label : 'Move Cell Up',
69 icon : 'ui-icon-arrowthick-1-n',
69 icon : 'ui-icon-arrowthick-1-n',
70 callback : function () {
70 callback : function () {
71 IPython.notebook.move_cell_up();
71 IPython.notebook.move_cell_up();
72 }
72 }
73 },
73 },
74 {
74 {
75 id : 'move_down_b',
75 id : 'move_down_b',
76 label : 'Move Cell Down',
76 label : 'Move Cell Down',
77 icon : 'ui-icon-arrowthick-1-s',
77 icon : 'ui-icon-arrowthick-1-s',
78 callback : function () {
78 callback : function () {
79 IPython.notebook.move_cell_down();
79 IPython.notebook.move_cell_down();
80 }
80 }
81 }
81 }
82 ],'move_up_down');
82 ],'move_up_down');
83
83
84 this.add_buttons_group([
84 this.add_buttons_group([
85 {
85 {
86 id : 'insert_above_b',
86 id : 'insert_above_b',
87 label : 'Insert Cell Above',
87 label : 'Insert Cell Above',
88 icon : 'ui-icon-arrowthickstop-1-n',
88 icon : 'ui-icon-arrowthickstop-1-n',
89 callback : function () {
89 callback : function () {
90 IPython.notebook.insert_cell_above('code');
90 IPython.notebook.insert_cell_above('code');
91 }
91 }
92 },
92 },
93 {
93 {
94 id : 'insert_below_b',
94 id : 'insert_below_b',
95 label : 'Insert Cell Below',
95 label : 'Insert Cell Below',
96 icon : 'ui-icon-arrowthickstop-1-s',
96 icon : 'ui-icon-arrowthickstop-1-s',
97 callback : function () {
97 callback : function () {
98 IPython.notebook.insert_cell_below('code');
98 IPython.notebook.insert_cell_below('code');
99 }
99 }
100 }
100 }
101 ],'insert_above_below');
101 ],'insert_above_below');
102
102
103 this.add_buttons_group([
103 this.add_buttons_group([
104 {
104 {
105 id : 'run_b',
105 id : 'run_b',
106 label : 'Run Cell',
106 label : 'Run Cell',
107 icon : 'ui-icon-play',
107 icon : 'ui-icon-play',
108 callback : function () {
108 callback : function () {
109 IPython.notebook.execute_selected_cell();
109 IPython.notebook.execute_selected_cell();
110 }
110 }
111 },
111 },
112 {
112 {
113 id : 'interrupt_b',
113 id : 'interrupt_b',
114 label : 'Interrupt',
114 label : 'Interrupt',
115 icon : 'ui-icon-stop',
115 icon : 'ui-icon-stop',
116 callback : function () {
116 callback : function () {
117 IPython.notebook.kernel.interrupt();
117 IPython.notebook.kernel.interrupt();
118 }
118 }
119 }
119 }
120 ],'run_int');
120 ],'run_int');
121 };
121 };
122
122
123 MainToolBar.prototype.add_drop_down_list = function () {
123 MainToolBar.prototype.add_drop_down_list = function () {
124 var select = $(this.selector)
124 var select = $(this.selector)
125 .append($('<select/>')
125 .append($('<select/>')
126 .attr('id','cell_type')
126 .attr('id','cell_type')
127 .addClass('ui-widget ui-widget-content')
127 .addClass('ui-widget ui-widget-content')
128 .append($('<option/>').attr('value','code').text('Code'))
128 .append($('<option/>').attr('value','code').text('Code'))
129 .append($('<option/>').attr('value','markdown').text('Markdown'))
129 .append($('<option/>').attr('value','markdown').text('Markdown'))
130 .append($('<option/>').attr('value','raw').text('Raw Text'))
130 .append($('<option/>').attr('value','raw').text('Raw Text'))
131 .append($('<option/>').attr('value','heading1').text('Heading 1'))
131 .append($('<option/>').attr('value','heading1').text('Heading 1'))
132 .append($('<option/>').attr('value','heading2').text('Heading 2'))
132 .append($('<option/>').attr('value','heading2').text('Heading 2'))
133 .append($('<option/>').attr('value','heading3').text('Heading 3'))
133 .append($('<option/>').attr('value','heading3').text('Heading 3'))
134 .append($('<option/>').attr('value','heading4').text('Heading 4'))
134 .append($('<option/>').attr('value','heading4').text('Heading 4'))
135 .append($('<option/>').attr('value','heading5').text('Heading 5'))
135 .append($('<option/>').attr('value','heading5').text('Heading 5'))
136 .append($('<option/>').attr('value','heading6').text('Heading 6'))
136 .append($('<option/>').attr('value','heading6').text('Heading 6'))
137 );
137 );
138 };
138 };
139
139
140 MainToolBar.prototype.bind_events = function () {
140 MainToolBar.prototype.bind_events = function () {
141 var that = this;
141 var that = this;
142
142
143 this.element.find('#cell_type').change(function () {
143 this.element.find('#cell_type').change(function () {
144 var cell_type = $(this).val();
144 var cell_type = $(this).val();
145 if (cell_type === 'code') {
145 if (cell_type === 'code') {
146 IPython.notebook.to_code();
146 IPython.notebook.to_code();
147 } else if (cell_type === 'markdown') {
147 } else if (cell_type === 'markdown') {
148 IPython.notebook.to_markdown();
148 IPython.notebook.to_markdown();
149 } else if (cell_type === 'raw') {
149 } else if (cell_type === 'raw') {
150 IPython.notebook.to_raw();
150 IPython.notebook.to_raw();
151 } else if (cell_type === 'heading1') {
151 } else if (cell_type === 'heading1') {
152 IPython.notebook.to_heading(undefined, 1);
152 IPython.notebook.to_heading(undefined, 1);
153 } else if (cell_type === 'heading2') {
153 } else if (cell_type === 'heading2') {
154 IPython.notebook.to_heading(undefined, 2);
154 IPython.notebook.to_heading(undefined, 2);
155 } else if (cell_type === 'heading3') {
155 } else if (cell_type === 'heading3') {
156 IPython.notebook.to_heading(undefined, 3);
156 IPython.notebook.to_heading(undefined, 3);
157 } else if (cell_type === 'heading4') {
157 } else if (cell_type === 'heading4') {
158 IPython.notebook.to_heading(undefined, 4);
158 IPython.notebook.to_heading(undefined, 4);
159 } else if (cell_type === 'heading5') {
159 } else if (cell_type === 'heading5') {
160 IPython.notebook.to_heading(undefined, 5);
160 IPython.notebook.to_heading(undefined, 5);
161 } else if (cell_type === 'heading6') {
161 } else if (cell_type === 'heading6') {
162 IPython.notebook.to_heading(undefined, 6);
162 IPython.notebook.to_heading(undefined, 6);
163 }
163 }
164 });
164 });
165 $([IPython.events]).on('selected_cell_type_changed.Notebook', function (event, data) {
165 $([IPython.events]).on('selected_cell_type_changed.Notebook', function (event, data) {
166 if (data.cell_type === 'heading') {
166 if (data.cell_type === 'heading') {
167 that.element.find('#cell_type').val(data.cell_type+data.level);
167 that.element.find('#cell_type').val(data.cell_type+data.level);
168 } else {
168 } else {
169 that.element.find('#cell_type').val(data.cell_type);
169 that.element.find('#cell_type').val(data.cell_type);
170 }
170 }
171 });
171 });
172 };
172 };
173
173
174 IPython.MainToolBar = MainToolBar;
174 IPython.MainToolBar = MainToolBar;
175
175
176 return IPython;
176 return IPython;
177
177
178 }(IPython));
178 }(IPython));
@@ -1,496 +1,496 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 // MetaUI
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 MetaUI
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 /**
23 /**
24 * @constructor
24 * @constructor
25 * @class MetaUI
25 * @class CellToolbar
26 * @param {The cell to attach the metadata UI to} cell
26 * @param {The cell to attach the metadata UI to} cell
27 */
27 */
28 var MetaUI = function (cell) {
28 var CellToolbar = function (cell) {
29 MetaUI._instances.push(this);
29 CellToolbar._instances.push(this);
30 this.$metainner = $('<div/>');
30 this.inner_element = $('<div/>');
31 this.cell = cell;
31 this.cell = cell;
32 this.$element = $('<div/>').addClass('metaedit')
32 this.element = $('<div/>').addClass('celltoolbar')
33 .append(this.$metainner)
33 .append(this.inner_element)
34 this.rebuild();
34 this.rebuild();
35 return this;
35 return this;
36 };
36 };
37
37
38 MetaUI.$dropdown_preset_selector = $('<select/>')
38 CellToolbar.dropdown_preset_element = $('<select/>')
39 .attr('id','metaui_selector')
39 .attr('id','celltoolbar_selector')
40 .append($('<option/>').attr('value','').text('-'))
40 .append($('<option/>').attr('value','').text('-'))
41
41
42 MetaUI.$dropdown_preset_selector.change(function(){
42 CellToolbar.dropdown_preset_element.change(function(){
43 var val = MetaUI.$dropdown_preset_selector.val()
43 var val = CellToolbar.dropdown_preset_element.val()
44 if(val ==''){
44 if(val ==''){
45 $('body').removeClass('editmetaon')
45 $('body').removeClass('celltoolbar-on')
46 } else {
46 } else {
47 $('body').addClass('editmetaon')
47 $('body').addClass('celltoolbar-on')
48 MetaUI.set_preset(val)
48 CellToolbar.set_preset(val)
49 }
49 }
50 })
50 })
51
51
52
52
53
53
54 /**
54 /**
55 * Class variable that should contain a dict of all availlable callback
55 * Class variable that should contain a dict of all availlable callback
56 * we need to think of wether or not we allow nested namespace
56 * we need to think of wether or not we allow nested namespace
57 * @property _callback_dict
57 * @property _callback_dict
58 * @private
58 * @private
59 */
59 */
60 MetaUI._callback_dict = {};
60 CellToolbar._callback_dict = {};
61
61
62 /**
62 /**
63 * Class variable that should contain the reverse order list of the button
63 * Class variable that should contain the reverse order list of the button
64 * to add to the toolbar of each cell
64 * to add to the toolbar of each cell
65 * @property _button_list
65 * @property _button_list
66 * @private
66 * @private
67 */
67 */
68 MetaUI._button_list = [];
68 CellToolbar._button_list = [];
69
69
70 /**
70 /**
71 * keep a list of all instances to
71 * keep a list of all instances to
72 * be able to llop over them...
72 * be able to llop over them...
73 * but how to 'destroy' them ?
73 * but how to 'destroy' them ?
74 * have to think about it...
74 * have to think about it...
75 * or loop over the cells, and find their MetaUI instances.
75 * or loop over the cells, and find their CellToolbar instances.
76 * @private
76 * @private
77 * @property _instances
77 * @property _instances
78 */
78 */
79 MetaUI._instances =[]
79 CellToolbar._instances =[]
80
80
81 /**
81 /**
82 * keep a list of all the availlabel presets for the toolbar
82 * keep a list of all the availlabel presets for the toolbar
83 * @private
83 * @private
84 * @property _presets
84 * @property _presets
85 */
85 */
86 MetaUI._presets ={}
86 CellToolbar._presets ={}
87
87
88 // this is by design not a prototype.
88 // this is by design not a prototype.
89 /**
89 /**
90 * Register a callback to create an UI element in a cell toolbar.
90 * Register a callback to create an UI element in a cell toolbar.
91 * @method register_callback
91 * @method register_callback
92 * @param name {String} name to use to refer to the callback. It is advised to use a prefix with the name
92 * @param name {String} name to use to refer to the callback. It is advised to use a prefix with the name
93 * for easier sorting and avoid collision
93 * for easier sorting and avoid collision
94 * @param callback {function(div, cell)} callback that will be called to generate the ui element
94 * @param callback {function(div, cell)} callback that will be called to generate the ui element
95 *
95 *
96 *
96 *
97 * The callback will receive the following element :
97 * The callback will receive the following element :
98 *
98 *
99 * * a div in which to add element.
99 * * a div in which to add element.
100 * * the cell it is responsable from
100 * * the cell it is responsable from
101 *
101 *
102 * @example
102 * @example
103 *
103 *
104 * Example that create callback for a button that toggle between `true` and `false` label,
104 * Example that create callback for a button that toggle between `true` and `false` label,
105 * with the metadata under the key 'foo' to reflect the status of the button.
105 * with the metadata under the key 'foo' to reflect the status of the button.
106 *
106 *
107 * // first param reference to a DOM div
107 * // first param reference to a DOM div
108 * // second param reference to the cell.
108 * // second param reference to the cell.
109 * var toggle = function(div, cell) {
109 * var toggle = function(div, cell) {
110 * var button_container = $(div)
110 * var button_container = $(div)
111 *
111 *
112 * // let's create a button that show the current value of the metadata
112 * // let's create a button that show the current value of the metadata
113 * var button = $('<div/>').button({label:String(cell.metadata.foo)});
113 * var button = $('<div/>').button({label:String(cell.metadata.foo)});
114 *
114 *
115 * // On click, change the metadata value and update the button label
115 * // On click, change the metadata value and update the button label
116 * button.click(function(){
116 * button.click(function(){
117 * var v = cell.metadata.foo;
117 * var v = cell.metadata.foo;
118 * cell.metadata.foo = !v;
118 * cell.metadata.foo = !v;
119 * button.button("option","label",String(!v));
119 * button.button("option","label",String(!v));
120 * })
120 * })
121 *
121 *
122 * // add the button to the DOM div.
122 * // add the button to the DOM div.
123 * button_container.append(button);
123 * button_container.append(button);
124 * }
124 * }
125 *
125 *
126 * // now we register the callback under the name `foo` to give the
126 * // now we register the callback under the name `foo` to give the
127 * // user the ability to use it later
127 * // user the ability to use it later
128 * MetaUI.register_callback('foo',toggle);
128 * CellToolbar.register_callback('foo',toggle);
129 */
129 */
130 MetaUI.register_callback = function(name, callback){
130 CellToolbar.register_callback = function(name, callback){
131 // what do we do if name already exist ?
131 // what do we do if name already exist ?
132 MetaUI._callback_dict[name] = callback;
132 CellToolbar._callback_dict[name] = callback;
133 };
133 };
134
134
135 /**
135 /**
136 * Register a preset of UI element in a cell toolbar.
136 * Register a preset of UI element in a cell toolbar.
137 * Not supported Yet.
137 * Not supported Yet.
138 * @method register_preset
138 * @method register_preset
139 * @param name {String} name to use to refer to the preset. It is advised to use a prefix with the name
139 * @param name {String} name to use to refer to the preset. It is advised to use a prefix with the name
140 * for easier sorting and avoid collision
140 * for easier sorting and avoid collision
141 * @param preset_list {List of String} reverse order of the button in the toolbar. Each String of the list
141 * @param preset_list {List of String} reverse order of the button in the toolbar. Each String of the list
142 * should correspond to a name of a registerd callback.
142 * should correspond to a name of a registerd callback.
143 *
143 *
144 * @private
144 * @private
145 * @example
145 * @example
146 *
146 *
147 * MetaUI.register_callback('foo.c1',function(div,cell){...});
147 * CellToolbar.register_callback('foo.c1',function(div,cell){...});
148 * MetaUI.register_callback('foo.c2',function(div,cell){...});
148 * CellToolbar.register_callback('foo.c2',function(div,cell){...});
149 * MetaUI.register_callback('foo.c3',function(div,cell){...});
149 * CellToolbar.register_callback('foo.c3',function(div,cell){...});
150 * MetaUI.register_callback('foo.c4',function(div,cell){...});
150 * CellToolbar.register_callback('foo.c4',function(div,cell){...});
151 * MetaUI.register_callback('foo.c5',function(div,cell){...});
151 * CellToolbar.register_callback('foo.c5',function(div,cell){...});
152 *
152 *
153 * MetaUI.register_preset('foo.foo_preset1',['foo.c1','foo.c2','foo.c5'])
153 * CellToolbar.register_preset('foo.foo_preset1',['foo.c1','foo.c2','foo.c5'])
154 * MetaUI.register_preset('foo.foo_preset2',['foo.c4','foo.c5'])
154 * CellToolbar.register_preset('foo.foo_preset2',['foo.c4','foo.c5'])
155 */
155 */
156 MetaUI.register_preset = function(name, preset_list){
156 CellToolbar.register_preset = function(name, preset_list){
157 MetaUI._presets[name] = preset_list
157 CellToolbar._presets[name] = preset_list
158 MetaUI.$dropdown_preset_selector.append(
158 CellToolbar.dropdown_preset_element.append(
159 $('<option/>').attr('value',name).text(name)
159 $('<option/>').attr('value',name).text(name)
160 )
160 )
161 }
161 }
162 /**
162 /**
163 * set an UI preset from `register_preset`
163 * set an UI preset from `register_preset`
164 * @method set_preset
164 * @method set_preset
165 * @param preset_name {String} string corresponding to the preset name
165 * @param preset_name {String} string corresponding to the preset name
166 *
166 *
167 * @static
167 * @static
168 * @private
168 * @private
169 * @example
169 * @example
170 *
170 *
171 * MetaUI.set_preset('foo.foo_preset1');
171 * CellToolbar.set_preset('foo.foo_preset1');
172 */
172 */
173 MetaUI.set_preset= function(preset_name){
173 CellToolbar.set_preset= function(preset_name){
174 var preset = MetaUI._presets[preset_name];
174 var preset = CellToolbar._presets[preset_name];
175
175
176 if(preset != undefined){
176 if(preset != undefined){
177 MetaUI._button_list = preset;
177 CellToolbar._button_list = preset;
178 MetaUI.rebuild_all();
178 CellToolbar.rebuild_all();
179 }
179 }
180 }
180 }
181
181
182
182
183 // this is by design not a prototype.
183 // this is by design not a prototype.
184 /**
184 /**
185 * This should be called on the class and not on a instance as it will trigger
185 * This should be called on the class and not on a instance as it will trigger
186 * rebuild of all the instances.
186 * rebuild of all the instances.
187 * @method rebuild_all
187 * @method rebuild_all
188 * @static
188 * @static
189 *
189 *
190 */
190 */
191 MetaUI.rebuild_all = function(){
191 CellToolbar.rebuild_all = function(){
192 for(var i in MetaUI._instances){
192 for(var i in CellToolbar._instances){
193 MetaUI._instances[i].rebuild();
193 CellToolbar._instances[i].rebuild();
194 }
194 }
195 }
195 }
196
196
197 /**
197 /**
198 * Rebuild all the button on the toolbar to update it's state.
198 * Rebuild all the button on the toolbar to update it's state.
199 * @method rebuild
199 * @method rebuild
200 */
200 */
201 MetaUI.prototype.rebuild = function(){
201 CellToolbar.prototype.rebuild = function(){
202 // strip evrything from the div
202 // strip evrything from the div
203 // which is probabli metainner.
203 // which is probabli metainner.
204 // or this.$element.
204 // or this.element.
205 this.$metainner.empty();
205 this.inner_element.empty();
206 //this.add_raw_edit_button()
206 //this.add_raw_edit_button()
207
207
208
208
209 var cdict = MetaUI._callback_dict;
209 var cdict = CellToolbar._callback_dict;
210 var preset = MetaUI._button_list;
210 var preset = CellToolbar._button_list;
211 // Yes we iterate on the class varaible, not the instance one.
211 // Yes we iterate on the class varaible, not the instance one.
212 for ( var index in MetaUI._button_list){
212 for ( var index in CellToolbar._button_list){
213 var local_div = $('<div/>').addClass('button_container');
213 var local_div = $('<div/>').addClass('button_container');
214 // Note,
214 // Note,
215 // do this the other way, wrap in try/catch and don't append if any errors.
215 // do this the other way, wrap in try/catch and don't append if any errors.
216 this.$metainner.append(local_div)
216 this.inner_element.append(local_div)
217 cdict[preset[index]](local_div,this.cell)
217 cdict[preset[index]](local_div,this.cell)
218 }
218 }
219
219
220 }
220 }
221
221
222 var raw_edit = function(cell){
222 var raw_edit = function(cell){
223
223
224 var md = cell.metadata
224 var md = cell.metadata
225
225
226 var textarea = $('<textarea/>')
226 var textarea = $('<textarea/>')
227 .attr('rows','13')
227 .attr('rows','13')
228 .attr('cols','75')
228 .attr('cols','75')
229 .attr('name','metadata')
229 .attr('name','metadata')
230 .text(JSON.stringify(md, null,4)||'');
230 .text(JSON.stringify(md, null,4)||'');
231 var dialogform = $('<div/>').attr('title','Edit the metadata')
231 var dialogform = $('<div/>').attr('title','Edit the metadata')
232 .append(
232 .append(
233 $('<form/>').append(
233 $('<form/>').append(
234 $('<fieldset/>').append(
234 $('<fieldset/>').append(
235 $('<label/>')
235 $('<label/>')
236 .attr('for','metadata')
236 .attr('for','metadata')
237 .text("Metadata (I know what I'm dooing and I won't complain if it breaks my notebook)")
237 .text("Metadata (I know what I'm dooing and I won't complain if it breaks my notebook)")
238 )
238 )
239 .append($('<br/>'))
239 .append($('<br/>'))
240 .append(
240 .append(
241 textarea
241 textarea
242 )
242 )
243 )
243 )
244 );
244 );
245 var editor = CodeMirror.fromTextArea(textarea[0], {
245 var editor = CodeMirror.fromTextArea(textarea[0], {
246 lineNumbers: true,
246 lineNumbers: true,
247 matchBrackets: true,
247 matchBrackets: true,
248 });
248 });
249 $(dialogform).dialog({
249 $(dialogform).dialog({
250 autoOpen: true,
250 autoOpen: true,
251 height: 300,
251 height: 300,
252 width: 650,
252 width: 650,
253 modal: true,
253 modal: true,
254 buttons: {
254 buttons: {
255 "Ok": function() {
255 "Ok": function() {
256 //validate json and set it
256 //validate json and set it
257 try {
257 try {
258 var json = JSON.parse(editor.getValue());
258 var json = JSON.parse(editor.getValue());
259 cell.metadata = json;
259 cell.metadata = json;
260 $( this ).dialog( "close" );
260 $( this ).dialog( "close" );
261 }
261 }
262 catch(e)
262 catch(e)
263 {
263 {
264 alert('invalid json');
264 alert('invalid json');
265 }
265 }
266 },
266 },
267 Cancel: function() {
267 Cancel: function() {
268 $( this ).dialog( "close" );
268 $( this ).dialog( "close" );
269 }
269 }
270 },
270 },
271 close: function() {
271 close: function() {
272 //cleanup on close
272 //cleanup on close
273 $(this).remove();
273 $(this).remove();
274 }
274 }
275 });
275 });
276 editor.refresh();
276 editor.refresh();
277 }
277 }
278
278
279
279
280 var add_raw_edit_button = function(div, cell) {
280 var add_raw_edit_button = function(div, cell) {
281 var button_container = $(div)
281 var button_container = $(div)
282 var button = $('<div/>').button({label:'Raw Edit'})
282 var button = $('<div/>').button({label:'Raw Edit'})
283 .click(function(){raw_edit(cell); return false;})
283 .click(function(){raw_edit(cell); return false;})
284 button_container.append(button);
284 button_container.append(button);
285 }
285 }
286
286
287 MetaUI.register_callback('example.rawedit',add_raw_edit_button);
287 CellToolbar.register_callback('example.rawedit',add_raw_edit_button);
288 var example_preset = []
288 var example_preset = []
289 example_preset.push('example.rawedit');
289 example_preset.push('example.rawedit');
290
290
291 var simple_dialog = function(title,text){
291 var simple_dialog = function(title,text){
292 var dlg = $('<div/>').attr('title',title)
292 var dlg = $('<div/>').attr('title',title)
293 .append($('<p/>').text(text))
293 .append($('<p/>').text(text))
294 $(dlg).dialog({
294 $(dlg).dialog({
295 autoOpen: true,
295 autoOpen: true,
296 height: 300,
296 height: 300,
297 width: 650,
297 width: 650,
298 modal: true,
298 modal: true,
299 close: function() {
299 close: function() {
300 //cleanup on close
300 //cleanup on close
301 $(this).remove();
301 $(this).remove();
302 }
302 }
303 });
303 });
304 }
304 }
305
305
306 var add_simple_dialog_button = function(div, cell) {
306 var add_simple_dialog_button = function(div, cell) {
307 var help_text = ["This is the Metadata editting UI.",
307 var help_text = ["This is the Metadata editting UI.",
308 "It heavily rely on plugin to work ",
308 "It heavily rely on plugin to work ",
309 "and is still under developpement. You shouldn't wait too long before",
309 "and is still under developpement. You shouldn't wait too long before",
310 " seeing some customisable buttons in those toolbar."
310 " seeing some customisable buttons in those toolbar."
311 ].join('\n')
311 ].join('\n')
312 var button_container = $(div)
312 var button_container = $(div)
313 var button = $('<div/>').button({label:'?'})
313 var button = $('<div/>').button({label:'?'})
314 .click(function(){simple_dialog('help',help_text); return false;})
314 .click(function(){simple_dialog('help',help_text); return false;})
315 button_container.append(button);
315 button_container.append(button);
316 }
316 }
317
317
318 MetaUI.register_callback('default.help',add_simple_dialog_button)
318 CellToolbar.register_callback('default.help',add_simple_dialog_button)
319 var default_preset = []
319 var default_preset = []
320 default_preset.push('default.help')
320 default_preset.push('default.help')
321 MetaUI.register_preset('default',default_preset)
321 CellToolbar.register_preset('default',default_preset)
322 MetaUI.set_preset('default')
322 CellToolbar.set_preset('default')
323
323
324 var simple_button = function(div, cell) {
324 var simple_button = function(div, cell) {
325 var button_container = $(div);
325 var button_container = $(div);
326 var button = $('<div/>').button({icons:{primary:'ui-icon-locked'}});
326 var button = $('<div/>').button({icons:{primary:'ui-icon-locked'}});
327 var fun = function(value){
327 var fun = function(value){
328 try{
328 try{
329 if(value){
329 if(value){
330 cell.code_mirror.setOption('readOnly','nocursor')
330 cell.code_mirror.setOption('readOnly','nocursor')
331 button.button('option','icons',{primary:'ui-icon-locked'})
331 button.button('option','icons',{primary:'ui-icon-locked'})
332 } else {
332 } else {
333 cell.code_mirror.setOption('readOnly','false')
333 cell.code_mirror.setOption('readOnly','false')
334 button.button('option','icons',{primary:'ui-icon-unlocked'})
334 button.button('option','icons',{primary:'ui-icon-unlocked'})
335 }
335 }
336 } catch(e){}
336 } catch(e){}
337
337
338 }
338 }
339 fun(cell.metadata.ro)
339 fun(cell.metadata.ro)
340 button.click(function(){
340 button.click(function(){
341 var v = cell.metadata.ro;
341 var v = cell.metadata.ro;
342 var locked = !v;
342 var locked = !v;
343 cell.metadata.ro = locked;
343 cell.metadata.ro = locked;
344 fun(locked)
344 fun(locked)
345 })
345 })
346 .css('height','16px')
346 .css('height','16px')
347 .css('width','35px');
347 .css('width','35px');
348 button_container.append(button);
348 button_container.append(button);
349 }
349 }
350
350
351 MetaUI.register_callback('example.lock',simple_button);
351 CellToolbar.register_callback('example.lock',simple_button);
352 example_preset.push('example.lock');
352 example_preset.push('example.lock');
353
353
354 var toggle_test = function(div, cell) {
354 var toggle_test = function(div, cell) {
355 var button_container = $(div)
355 var button_container = $(div)
356 var button = $('<div/>').button({label:String(cell.metadata.foo)});
356 var button = $('<div/>').button({label:String(cell.metadata.foo)});
357 button.click(function(){
357 button.click(function(){
358 var v = cell.metadata.foo;
358 var v = cell.metadata.foo;
359 cell.metadata.foo = !v;
359 cell.metadata.foo = !v;
360 button.button("option","label",String(!v));
360 button.button("option","label",String(!v));
361 })
361 })
362 button_container.append(button);
362 button_container.append(button);
363 }
363 }
364
364
365 MetaUI.register_callback('example.toggle',toggle_test);
365 CellToolbar.register_callback('example.toggle',toggle_test);
366 example_preset.push('example.toggle');
366 example_preset.push('example.toggle');
367
367
368 /**
368 /**
369 */
369 */
370 MetaUI.utils = {};
370 CellToolbar.utils = {};
371
371
372 /**
372 /**
373 * A utility function to generate bindings between a checkbox and metadata
373 * A utility function to generate bindings between a checkbox and metadata
374 * @method utils.checkbox_ui_generator
374 * @method utils.checkbox_ui_generator
375 * @static
375 * @static
376 *
376 *
377 * @param name {string} Label in front of the checkbox
377 * @param name {string} Label in front of the checkbox
378 * @param setter {function( metadata_dict, newValue )}
378 * @param setter {function( metadata_dict, newValue )}
379 * A setter method to set the newValue of the metadata dictionnary
379 * A setter method to set the newValue of the metadata dictionnary
380 * @param getter {function( metadata )}
380 * @param getter {function( metadata )}
381 * A getter methods which return the current value of the metadata.
381 * A getter methods which return the current value of the metadata.
382 *
382 *
383 * @return callback {function( div, cell )} Callback to be passed to `register_callback`
383 * @return callback {function( div, cell )} Callback to be passed to `register_callback`
384 *
384 *
385 * @example
385 * @example
386 *
386 *
387 * An exmple that bind the subkey `slideshow.isSectionStart` to a checkbox with a `New Slide` label
387 * An exmple that bind the subkey `slideshow.isSectionStart` to a checkbox with a `New Slide` label
388 *
388 *
389 * var newSlide = MetaUI.utils.checkbox_ui_generator('New Slide',
389 * var newSlide = CellToolbar.utils.checkbox_ui_generator('New Slide',
390 * // setter
390 * // setter
391 * function(metadata,value){
391 * function(metadata,value){
392 * // we check that the slideshow namespace exist and create it if needed
392 * // we check that the slideshow namespace exist and create it if needed
393 * if (metadata.slideshow == undefined){metadata.slideshow = {}}
393 * if (metadata.slideshow == undefined){metadata.slideshow = {}}
394 * // set the value
394 * // set the value
395 * metadata.slideshow.isSectionStart = value
395 * metadata.slideshow.isSectionStart = value
396 * },
396 * },
397 * //geter
397 * //geter
398 * function(metadata){ var ns = metadata.slideshow;
398 * function(metadata){ var ns = metadata.slideshow;
399 * // if the slideshow namespace does not exist return `undefined`
399 * // if the slideshow namespace does not exist return `undefined`
400 * // (will be interpreted as `false` by checkbox) otherwise
400 * // (will be interpreted as `false` by checkbox) otherwise
401 * // return the value
401 * // return the value
402 * return (ns == undefined)? undefined: ns.isSectionStart
402 * return (ns == undefined)? undefined: ns.isSectionStart
403 * }
403 * }
404 * );
404 * );
405 *
405 *
406 * MetaUI.register_callback('newSlide', newSlide);
406 * CellToolbar.register_callback('newSlide', newSlide);
407 *
407 *
408 */
408 */
409 MetaUI.utils.checkbox_ui_generator = function(name,setter,getter){
409 CellToolbar.utils.checkbox_ui_generator = function(name,setter,getter){
410 return function(div, cell) {
410 return function(div, cell) {
411 var button_container = $(div)
411 var button_container = $(div)
412
412
413 var chkb = $('<input/>').attr('type','checkbox');
413 var chkb = $('<input/>').attr('type','checkbox');
414 var lbl = $('<label/>').append($('<span/>').text(name).css('font-size','77%'));
414 var lbl = $('<label/>').append($('<span/>').text(name).css('font-size','77%'));
415 lbl.append(chkb);
415 lbl.append(chkb);
416 chkb.attr("checked",getter(cell.metadata));
416 chkb.attr("checked",getter(cell.metadata));
417
417
418 chkb.click(function(){
418 chkb.click(function(){
419 var v = getter(cell.metadata);
419 var v = getter(cell.metadata);
420 setter(cell.metadata,!v);
420 setter(cell.metadata,!v);
421 chkb.attr("checked",!v);
421 chkb.attr("checked",!v);
422 })
422 })
423 button_container.append($('<div/>').append(lbl));
423 button_container.append($('<div/>').append(lbl));
424
424
425 }
425 }
426 }
426 }
427
427
428 /**
428 /**
429 * A utility function to generate bindings between a dropdown list and metadata
429 * A utility function to generate bindings between a dropdown list and metadata
430 * @method utils.select_ui_generator
430 * @method utils.select_ui_generator
431 * @static
431 * @static
432 *
432 *
433 * @param list_list {list of sublist} List of sublist of metadata value and name in the dropdown list.
433 * @param list_list {list of sublist} List of sublist of metadata value and name in the dropdown list.
434 * subslit shoud contain 2 element each, first a string that woul be displayed in the dropdown list,
434 * subslit shoud contain 2 element each, first a string that woul be displayed in the dropdown list,
435 * and second the corresponding value for the metadata to be passed to setter/return by getter.
435 * and second the corresponding value for the metadata to be passed to setter/return by getter.
436 * @param setter {function( metadata_dict, newValue )}
436 * @param setter {function( metadata_dict, newValue )}
437 * A setter method to set the newValue of the metadata dictionnary
437 * A setter method to set the newValue of the metadata dictionnary
438 * @param getter {function( metadata )}
438 * @param getter {function( metadata )}
439 * A getter methods which return the current value of the metadata.
439 * A getter methods which return the current value of the metadata.
440 * @param [label=""] {String} optionnal label for the dropdown menu
440 * @param [label=""] {String} optionnal label for the dropdown menu
441 *
441 *
442 * @return callback {function( div, cell )} Callback to be passed to `register_callback`
442 * @return callback {function( div, cell )} Callback to be passed to `register_callback`
443 *
443 *
444 * @example
444 * @example
445 *
445 *
446 * var select_type = MetaUI.utils.select_ui_generator([
446 * var select_type = CellToolbar.utils.select_ui_generator([
447 * ["-" ,undefined ],
447 * ["-" ,undefined ],
448 * ["Header Slide" ,"header_slide" ],
448 * ["Header Slide" ,"header_slide" ],
449 * ["Slide" ,"slide" ],
449 * ["Slide" ,"slide" ],
450 * ["Fragment" ,"fragment" ],
450 * ["Fragment" ,"fragment" ],
451 * ["Skip" ,"skip" ],
451 * ["Skip" ,"skip" ],
452 * ],
452 * ],
453 * // setter
453 * // setter
454 * function(metadata,value){
454 * function(metadata,value){
455 * // we check that the slideshow namespace exist and create it if needed
455 * // we check that the slideshow namespace exist and create it if needed
456 * if (metadata.slideshow == undefined){metadata.slideshow = {}}
456 * if (metadata.slideshow == undefined){metadata.slideshow = {}}
457 * // set the value
457 * // set the value
458 * metadata.slideshow.slide_type = value
458 * metadata.slideshow.slide_type = value
459 * },
459 * },
460 * //geter
460 * //geter
461 * function(metadata){ var ns = metadata.slideshow;
461 * function(metadata){ var ns = metadata.slideshow;
462 * // if the slideshow namespace does not exist return `undefined`
462 * // if the slideshow namespace does not exist return `undefined`
463 * // (will be interpreted as `false` by checkbox) otherwise
463 * // (will be interpreted as `false` by checkbox) otherwise
464 * // return the value
464 * // return the value
465 * return (ns == undefined)? undefined: ns.slide_type
465 * return (ns == undefined)? undefined: ns.slide_type
466 * }
466 * }
467 * MetaUI.register_callback('slideshow.select',select_type);
467 * CellToolbar.register_callback('slideshow.select',select_type);
468 *
468 *
469 */
469 */
470 MetaUI.utils.select_ui_generator = function(list_list,setter, getter, label){
470 CellToolbar.utils.select_ui_generator = function(list_list,setter, getter, label){
471 label= label? label: "";
471 label= label? label: "";
472 return function(div, cell) {
472 return function(div, cell) {
473 var button_container = $(div)
473 var button_container = $(div)
474 var lbl = $("<label/>").append($('<span/>').text(label).css('font-size','77%'));
474 var lbl = $("<label/>").append($('<span/>').text(label).css('font-size','77%'));
475 var select = $('<select/>');
475 var select = $('<select/>');
476 for(var itemn in list_list){
476 for(var itemn in list_list){
477 var opt = $('<option/>');
477 var opt = $('<option/>');
478 opt.attr('value',list_list[itemn][1])
478 opt.attr('value',list_list[itemn][1])
479 opt.text(list_list[itemn][0])
479 opt.text(list_list[itemn][0])
480 select.append(opt);
480 select.append(opt);
481 }
481 }
482 select.val(getter(cell.metadata));
482 select.val(getter(cell.metadata));
483
483
484 select.change(function(){
484 select.change(function(){
485 setter(cell.metadata,select.val());
485 setter(cell.metadata,select.val());
486 });
486 });
487 button_container.append($('<div/>').append(lbl).append(select));
487 button_container.append($('<div/>').append(lbl).append(select));
488
488
489 }
489 }
490 };
490 };
491
491
492
492
493 IPython.MetaUI = MetaUI;
493 IPython.CellToolbar = CellToolbar;
494
494
495 return IPython;
495 return IPython;
496 }(IPython));
496 }(IPython));
@@ -1,533 +1,533 b''
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 var cell = $("<div>").addClass('cell text_cell border-box-sizing vbox');
45 var cell = $("<div>").addClass('cell text_cell border-box-sizing vbox');
46 this.metaui = new IPython.MetaUI(this);
46 this.celltoolbar = new IPython.CellToolbar(this);
47 cell.append(this.metaui.$element);
47 cell.append(this.celltoolbar.element);
48 cell.attr('tabindex','2');
48 cell.attr('tabindex','2');
49 var input_area = $('<div/>').addClass('text_cell_input border-box-sizing');
49 var input_area = $('<div/>').addClass('text_cell_input border-box-sizing');
50 this.code_mirror = CodeMirror(input_area.get(0), {
50 this.code_mirror = CodeMirror(input_area.get(0), {
51 indentUnit : 4,
51 indentUnit : 4,
52 mode: this.code_mirror_mode,
52 mode: this.code_mirror_mode,
53 theme: 'default',
53 theme: 'default',
54 value: this.placeholder,
54 value: this.placeholder,
55 readOnly: this.read_only,
55 readOnly: this.read_only,
56 lineWrapping : true,
56 lineWrapping : true,
57 extraKeys: {"Tab": "indentMore","Shift-Tab" : "indentLess"},
57 extraKeys: {"Tab": "indentMore","Shift-Tab" : "indentLess"},
58 onKeyEvent: $.proxy(this.handle_codemirror_keyevent,this)
58 onKeyEvent: $.proxy(this.handle_codemirror_keyevent,this)
59 });
59 });
60 // The tabindex=-1 makes this div focusable.
60 // The tabindex=-1 makes this div focusable.
61 var render_area = $('<div/>').addClass('text_cell_render border-box-sizing').
61 var render_area = $('<div/>').addClass('text_cell_render border-box-sizing').
62 addClass('rendered_html').attr('tabindex','-1');
62 addClass('rendered_html').attr('tabindex','-1');
63 cell.append(input_area).append(render_area);
63 cell.append(input_area).append(render_area);
64 this.element = cell;
64 this.element = cell;
65 };
65 };
66
66
67
67
68 /**
68 /**
69 * Bind the DOM evet to cell actions
69 * Bind the DOM evet to cell actions
70 * Need to be called after TextCell.create_element
70 * Need to be called after TextCell.create_element
71 * @private
71 * @private
72 * @method bind_event
72 * @method bind_event
73 */
73 */
74 TextCell.prototype.bind_events = function () {
74 TextCell.prototype.bind_events = function () {
75 IPython.Cell.prototype.bind_events.apply(this);
75 IPython.Cell.prototype.bind_events.apply(this);
76 var that = this;
76 var that = this;
77 this.element.keydown(function (event) {
77 this.element.keydown(function (event) {
78 if (event.which === 13 && !event.shiftKey) {
78 if (event.which === 13 && !event.shiftKey) {
79 if (that.rendered) {
79 if (that.rendered) {
80 that.edit();
80 that.edit();
81 return false;
81 return false;
82 };
82 };
83 };
83 };
84 });
84 });
85 this.element.dblclick(function () {
85 this.element.dblclick(function () {
86 that.edit();
86 that.edit();
87 });
87 });
88 };
88 };
89
89
90 /**
90 /**
91 * This method gets called in CodeMirror's onKeyDown/onKeyPress
91 * This method gets called in CodeMirror's onKeyDown/onKeyPress
92 * handlers and is used to provide custom key handling.
92 * handlers and is used to provide custom key handling.
93 *
93 *
94 * Subclass should override this method to have custom handeling
94 * Subclass should override this method to have custom handeling
95 *
95 *
96 * @method handle_codemirror_keyevent
96 * @method handle_codemirror_keyevent
97 * @param {CodeMirror} editor - The codemirror instance bound to the cell
97 * @param {CodeMirror} editor - The codemirror instance bound to the cell
98 * @param {event} event -
98 * @param {event} event -
99 * @return {Boolean} `true` if CodeMirror should ignore the event, `false` Otherwise
99 * @return {Boolean} `true` if CodeMirror should ignore the event, `false` Otherwise
100 */
100 */
101 TextCell.prototype.handle_codemirror_keyevent = function (editor, event) {
101 TextCell.prototype.handle_codemirror_keyevent = function (editor, event) {
102
102
103 if (event.keyCode === 13 && (event.shiftKey || event.ctrlKey)) {
103 if (event.keyCode === 13 && (event.shiftKey || event.ctrlKey)) {
104 // Always ignore shift-enter in CodeMirror as we handle it.
104 // Always ignore shift-enter in CodeMirror as we handle it.
105 return true;
105 return true;
106 }
106 }
107 return false;
107 return false;
108 };
108 };
109
109
110 /**
110 /**
111 * Select the current cell and trigger 'focus'
111 * Select the current cell and trigger 'focus'
112 * @method select
112 * @method select
113 */
113 */
114 TextCell.prototype.select = function () {
114 TextCell.prototype.select = function () {
115 IPython.Cell.prototype.select.apply(this);
115 IPython.Cell.prototype.select.apply(this);
116 var output = this.element.find("div.text_cell_render");
116 var output = this.element.find("div.text_cell_render");
117 output.trigger('focus');
117 output.trigger('focus');
118 };
118 };
119
119
120 /**
120 /**
121 * unselect the current cell and `render` it
121 * unselect the current cell and `render` it
122 * @method unselect
122 * @method unselect
123 */
123 */
124 TextCell.prototype.unselect = function() {
124 TextCell.prototype.unselect = function() {
125 // render on selection of another cell
125 // render on selection of another cell
126 this.render();
126 this.render();
127 IPython.Cell.prototype.unselect.apply(this);
127 IPython.Cell.prototype.unselect.apply(this);
128 };
128 };
129
129
130 /**
130 /**
131 *
131 *
132 * put the current cell in edition mode
132 * put the current cell in edition mode
133 * @method edit
133 * @method edit
134 */
134 */
135 TextCell.prototype.edit = function () {
135 TextCell.prototype.edit = function () {
136 if ( this.read_only ) return;
136 if ( this.read_only ) return;
137 if (this.rendered === true) {
137 if (this.rendered === true) {
138 var text_cell = this.element;
138 var text_cell = this.element;
139 var output = text_cell.find("div.text_cell_render");
139 var output = text_cell.find("div.text_cell_render");
140 output.hide();
140 output.hide();
141 text_cell.find('div.text_cell_input').show();
141 text_cell.find('div.text_cell_input').show();
142 this.code_mirror.refresh();
142 this.code_mirror.refresh();
143 this.code_mirror.focus();
143 this.code_mirror.focus();
144 // We used to need an additional refresh() after the focus, but
144 // We used to need an additional refresh() after the focus, but
145 // it appears that this has been fixed in CM. This bug would show
145 // it appears that this has been fixed in CM. This bug would show
146 // up on FF when a newly loaded markdown cell was edited.
146 // up on FF when a newly loaded markdown cell was edited.
147 this.rendered = false;
147 this.rendered = false;
148 if (this.get_text() === this.placeholder) {
148 if (this.get_text() === this.placeholder) {
149 this.set_text('');
149 this.set_text('');
150 this.refresh();
150 this.refresh();
151 }
151 }
152 }
152 }
153 };
153 };
154
154
155
155
156 /**
156 /**
157 * Empty, Subclasses must define render.
157 * Empty, Subclasses must define render.
158 * @method render
158 * @method render
159 */
159 */
160 TextCell.prototype.render = function () {};
160 TextCell.prototype.render = function () {};
161
161
162
162
163 /**
163 /**
164 * setter: {{#crossLink "TextCell/set_text"}}{{/crossLink}}
164 * setter: {{#crossLink "TextCell/set_text"}}{{/crossLink}}
165 * @method get_text
165 * @method get_text
166 * @retrun {string} CodeMirror current text value
166 * @retrun {string} CodeMirror current text value
167 */
167 */
168 TextCell.prototype.get_text = function() {
168 TextCell.prototype.get_text = function() {
169 return this.code_mirror.getValue();
169 return this.code_mirror.getValue();
170 };
170 };
171
171
172 /**
172 /**
173 * @param {string} text - Codemiror text value
173 * @param {string} text - Codemiror text value
174 * @see TextCell#get_text
174 * @see TextCell#get_text
175 * @method set_text
175 * @method set_text
176 * */
176 * */
177 TextCell.prototype.set_text = function(text) {
177 TextCell.prototype.set_text = function(text) {
178 this.code_mirror.setValue(text);
178 this.code_mirror.setValue(text);
179 this.code_mirror.refresh();
179 this.code_mirror.refresh();
180 };
180 };
181
181
182 /**
182 /**
183 * setter :{{#crossLink "TextCell/set_rendered"}}{{/crossLink}}
183 * setter :{{#crossLink "TextCell/set_rendered"}}{{/crossLink}}
184 * @method get_rendered
184 * @method get_rendered
185 * @return {html} html of rendered element
185 * @return {html} html of rendered element
186 * */
186 * */
187 TextCell.prototype.get_rendered = function() {
187 TextCell.prototype.get_rendered = function() {
188 return this.element.find('div.text_cell_render').html();
188 return this.element.find('div.text_cell_render').html();
189 };
189 };
190
190
191 /**
191 /**
192 * @method set_rendered
192 * @method set_rendered
193 */
193 */
194 TextCell.prototype.set_rendered = function(text) {
194 TextCell.prototype.set_rendered = function(text) {
195 this.element.find('div.text_cell_render').html(text);
195 this.element.find('div.text_cell_render').html(text);
196 };
196 };
197
197
198 /**
198 /**
199 * not deprecated, but implementation wrong
199 * not deprecated, but implementation wrong
200 * @method at_top
200 * @method at_top
201 * @deprecated
201 * @deprecated
202 * @return {Boolean} true is cell rendered, false otherwise
202 * @return {Boolean} true is cell rendered, false otherwise
203 * I doubt this is what it is supposed to do
203 * I doubt this is what it is supposed to do
204 * this implementation is completly false
204 * this implementation is completly false
205 */
205 */
206 TextCell.prototype.at_top = function () {
206 TextCell.prototype.at_top = function () {
207 if (this.rendered) {
207 if (this.rendered) {
208 return true;
208 return true;
209 } else {
209 } else {
210 return false;
210 return false;
211 }
211 }
212 };
212 };
213
213
214
214
215 /**
215 /**
216 * not deprecated, but implementation wrong
216 * not deprecated, but implementation wrong
217 * @method at_bottom
217 * @method at_bottom
218 * @deprecated
218 * @deprecated
219 * @return {Boolean} true is cell rendered, false otherwise
219 * @return {Boolean} true is cell rendered, false otherwise
220 * I doubt this is what it is supposed to do
220 * I doubt this is what it is supposed to do
221 * this implementation is completly false
221 * this implementation is completly false
222 * */
222 * */
223 TextCell.prototype.at_bottom = function () {
223 TextCell.prototype.at_bottom = function () {
224 if (this.rendered) {
224 if (this.rendered) {
225 return true;
225 return true;
226 } else {
226 } else {
227 return false;
227 return false;
228 }
228 }
229 };
229 };
230
230
231 /**
231 /**
232 * Create Text cell from JSON
232 * Create Text cell from JSON
233 * @param {json} data - JSON serialized text-cell
233 * @param {json} data - JSON serialized text-cell
234 * @method fromJSON
234 * @method fromJSON
235 */
235 */
236 TextCell.prototype.fromJSON = function (data) {
236 TextCell.prototype.fromJSON = function (data) {
237 IPython.Cell.prototype.fromJSON.apply(this, arguments);
237 IPython.Cell.prototype.fromJSON.apply(this, arguments);
238 if (data.cell_type === this.cell_type) {
238 if (data.cell_type === this.cell_type) {
239 if (data.source !== undefined) {
239 if (data.source !== undefined) {
240 this.set_text(data.source);
240 this.set_text(data.source);
241 // make this value the starting point, so that we can only undo
241 // make this value the starting point, so that we can only undo
242 // to this state, instead of a blank cell
242 // to this state, instead of a blank cell
243 this.code_mirror.clearHistory();
243 this.code_mirror.clearHistory();
244 this.set_rendered(data.rendered || '');
244 this.set_rendered(data.rendered || '');
245 this.rendered = false;
245 this.rendered = false;
246 this.render();
246 this.render();
247 }
247 }
248 }
248 }
249 };
249 };
250
250
251 /** Generate JSON from cell
251 /** Generate JSON from cell
252 * @return {object} cell data serialised to json
252 * @return {object} cell data serialised to json
253 */
253 */
254 TextCell.prototype.toJSON = function () {
254 TextCell.prototype.toJSON = function () {
255 var data = IPython.Cell.prototype.toJSON.apply(this);
255 var data = IPython.Cell.prototype.toJSON.apply(this);
256 data.cell_type = this.cell_type;
256 data.cell_type = this.cell_type;
257 data.source = this.get_text();
257 data.source = this.get_text();
258 return data;
258 return data;
259 };
259 };
260
260
261
261
262 /**
262 /**
263 * @constructor HtmlCell
263 * @constructor HtmlCell
264 * @class HtmlCell
264 * @class HtmlCell
265 * @extends Ipython.TextCell
265 * @extends Ipython.TextCell
266 */
266 */
267 var HTMLCell = function () {
267 var HTMLCell = function () {
268 this.placeholder = "Type <strong>HTML</strong> and LaTeX: $\\alpha^2$";
268 this.placeholder = "Type <strong>HTML</strong> and LaTeX: $\\alpha^2$";
269 IPython.TextCell.apply(this, arguments);
269 IPython.TextCell.apply(this, arguments);
270 this.cell_type = 'html';
270 this.cell_type = 'html';
271 };
271 };
272
272
273
273
274 HTMLCell.prototype = new TextCell();
274 HTMLCell.prototype = new TextCell();
275
275
276 /**
276 /**
277 * @method render
277 * @method render
278 */
278 */
279 HTMLCell.prototype.render = function () {
279 HTMLCell.prototype.render = function () {
280 if (this.rendered === false) {
280 if (this.rendered === false) {
281 var text = this.get_text();
281 var text = this.get_text();
282 if (text === "") { text = this.placeholder; }
282 if (text === "") { text = this.placeholder; }
283 this.set_rendered(text);
283 this.set_rendered(text);
284 this.typeset();
284 this.typeset();
285 this.element.find('div.text_cell_input').hide();
285 this.element.find('div.text_cell_input').hide();
286 this.element.find("div.text_cell_render").show();
286 this.element.find("div.text_cell_render").show();
287 this.rendered = true;
287 this.rendered = true;
288 }
288 }
289 };
289 };
290
290
291
291
292 /**
292 /**
293 * @class MarkdownCell
293 * @class MarkdownCell
294 * @constructor MarkdownCell
294 * @constructor MarkdownCell
295 * @extends Ipython.HtmlCell
295 * @extends Ipython.HtmlCell
296 */
296 */
297 var MarkdownCell = function () {
297 var MarkdownCell = function () {
298 this.placeholder = "Type *Markdown* and LaTeX: $\\alpha^2$";
298 this.placeholder = "Type *Markdown* and LaTeX: $\\alpha^2$";
299 IPython.TextCell.apply(this, arguments);
299 IPython.TextCell.apply(this, arguments);
300 this.cell_type = 'markdown';
300 this.cell_type = 'markdown';
301 };
301 };
302
302
303
303
304 MarkdownCell.prototype = new TextCell();
304 MarkdownCell.prototype = new TextCell();
305
305
306 /**
306 /**
307 * @method render
307 * @method render
308 */
308 */
309 MarkdownCell.prototype.render = function () {
309 MarkdownCell.prototype.render = function () {
310 if (this.rendered === false) {
310 if (this.rendered === false) {
311 var text = this.get_text();
311 var text = this.get_text();
312 if (text === "") { text = this.placeholder; }
312 if (text === "") { text = this.placeholder; }
313 text = IPython.mathjaxutils.remove_math(text)
313 text = IPython.mathjaxutils.remove_math(text)
314 var html = IPython.markdown_converter.makeHtml(text);
314 var html = IPython.markdown_converter.makeHtml(text);
315 html = IPython.mathjaxutils.replace_math(html)
315 html = IPython.mathjaxutils.replace_math(html)
316 try {
316 try {
317 this.set_rendered(html);
317 this.set_rendered(html);
318 } catch (e) {
318 } catch (e) {
319 console.log("Error running Javascript in Markdown:");
319 console.log("Error running Javascript in Markdown:");
320 console.log(e);
320 console.log(e);
321 this.set_rendered($("<div/>").addClass("js-error").html(
321 this.set_rendered($("<div/>").addClass("js-error").html(
322 "Error rendering Markdown!<br/>" + e.toString())
322 "Error rendering Markdown!<br/>" + e.toString())
323 );
323 );
324 }
324 }
325 this.element.find('div.text_cell_input').hide();
325 this.element.find('div.text_cell_input').hide();
326 this.element.find("div.text_cell_render").show();
326 this.element.find("div.text_cell_render").show();
327 var code_snippets = this.element.find("pre > code");
327 var code_snippets = this.element.find("pre > code");
328 code_snippets.replaceWith(function () {
328 code_snippets.replaceWith(function () {
329 var code = $(this).html();
329 var code = $(this).html();
330 /* Substitute br for newlines and &nbsp; for spaces
330 /* Substitute br for newlines and &nbsp; for spaces
331 before highlighting, since prettify doesn't
331 before highlighting, since prettify doesn't
332 preserve those on all browsers */
332 preserve those on all browsers */
333 code = code.replace(/(\r\n|\n|\r)/gm, "<br/>");
333 code = code.replace(/(\r\n|\n|\r)/gm, "<br/>");
334 code = code.replace(/ /gm, '&nbsp;');
334 code = code.replace(/ /gm, '&nbsp;');
335 code = prettyPrintOne(code);
335 code = prettyPrintOne(code);
336
336
337 return '<code class="prettyprint">' + code + '</code>';
337 return '<code class="prettyprint">' + code + '</code>';
338 });
338 });
339 this.typeset()
339 this.typeset()
340 this.rendered = true;
340 this.rendered = true;
341 }
341 }
342 };
342 };
343
343
344
344
345 // RawCell
345 // RawCell
346
346
347 /**
347 /**
348 * @class RawCell
348 * @class RawCell
349 * @constructor RawCell
349 * @constructor RawCell
350 * @extends Ipython.TextCell
350 * @extends Ipython.TextCell
351 */
351 */
352 var RawCell = function () {
352 var RawCell = function () {
353 this.placeholder = "Type plain text and LaTeX: $\\alpha^2$";
353 this.placeholder = "Type plain text and LaTeX: $\\alpha^2$";
354 this.code_mirror_mode = 'rst';
354 this.code_mirror_mode = 'rst';
355 IPython.TextCell.apply(this, arguments);
355 IPython.TextCell.apply(this, arguments);
356 this.cell_type = 'raw';
356 this.cell_type = 'raw';
357 var that = this
357 var that = this
358
358
359 this.element.focusout(
359 this.element.focusout(
360 function() { that.auto_highlight(); }
360 function() { that.auto_highlight(); }
361 );
361 );
362 };
362 };
363
363
364
364
365 RawCell.prototype = new TextCell();
365 RawCell.prototype = new TextCell();
366
366
367 /**
367 /**
368 * Trigger autodetection of highlight scheme for current cell
368 * Trigger autodetection of highlight scheme for current cell
369 * @method auto_highlight
369 * @method auto_highlight
370 */
370 */
371 RawCell.prototype.auto_highlight = function () {
371 RawCell.prototype.auto_highlight = function () {
372 this._auto_highlight(IPython.config.raw_cell_highlight);
372 this._auto_highlight(IPython.config.raw_cell_highlight);
373 };
373 };
374
374
375 /** @method render **/
375 /** @method render **/
376 RawCell.prototype.render = function () {
376 RawCell.prototype.render = function () {
377 this.rendered = true;
377 this.rendered = true;
378 this.edit();
378 this.edit();
379 };
379 };
380
380
381
381
382 /** @method handle_codemirror_keyevent **/
382 /** @method handle_codemirror_keyevent **/
383 RawCell.prototype.handle_codemirror_keyevent = function (editor, event) {
383 RawCell.prototype.handle_codemirror_keyevent = function (editor, event) {
384
384
385 var that = this;
385 var that = this;
386 if (event.which === key.UPARROW && event.type === 'keydown') {
386 if (event.which === key.UPARROW && event.type === 'keydown') {
387 // If we are not at the top, let CM handle the up arrow and
387 // If we are not at the top, let CM handle the up arrow and
388 // prevent the global keydown handler from handling it.
388 // prevent the global keydown handler from handling it.
389 if (!that.at_top()) {
389 if (!that.at_top()) {
390 event.stop();
390 event.stop();
391 return false;
391 return false;
392 } else {
392 } else {
393 return true;
393 return true;
394 };
394 };
395 } else if (event.which === key.DOWNARROW && event.type === 'keydown') {
395 } else if (event.which === key.DOWNARROW && event.type === 'keydown') {
396 // If we are not at the bottom, let CM handle the down arrow and
396 // If we are not at the bottom, let CM handle the down arrow and
397 // prevent the global keydown handler from handling it.
397 // prevent the global keydown handler from handling it.
398 if (!that.at_bottom()) {
398 if (!that.at_bottom()) {
399 event.stop();
399 event.stop();
400 return false;
400 return false;
401 } else {
401 } else {
402 return true;
402 return true;
403 };
403 };
404 };
404 };
405 return false;
405 return false;
406 };
406 };
407
407
408 /** @method select **/
408 /** @method select **/
409 RawCell.prototype.select = function () {
409 RawCell.prototype.select = function () {
410 IPython.Cell.prototype.select.apply(this);
410 IPython.Cell.prototype.select.apply(this);
411 this.code_mirror.refresh();
411 this.code_mirror.refresh();
412 this.code_mirror.focus();
412 this.code_mirror.focus();
413 };
413 };
414
414
415 /** @method at_top **/
415 /** @method at_top **/
416 RawCell.prototype.at_top = function () {
416 RawCell.prototype.at_top = function () {
417 var cursor = this.code_mirror.getCursor();
417 var cursor = this.code_mirror.getCursor();
418 if (cursor.line === 0 && cursor.ch === 0) {
418 if (cursor.line === 0 && cursor.ch === 0) {
419 return true;
419 return true;
420 } else {
420 } else {
421 return false;
421 return false;
422 }
422 }
423 };
423 };
424
424
425
425
426 /** @method at_bottom **/
426 /** @method at_bottom **/
427 RawCell.prototype.at_bottom = function () {
427 RawCell.prototype.at_bottom = function () {
428 var cursor = this.code_mirror.getCursor();
428 var cursor = this.code_mirror.getCursor();
429 if (cursor.line === (this.code_mirror.lineCount()-1) && cursor.ch === this.code_mirror.getLine(cursor.line).length) {
429 if (cursor.line === (this.code_mirror.lineCount()-1) && cursor.ch === this.code_mirror.getLine(cursor.line).length) {
430 return true;
430 return true;
431 } else {
431 } else {
432 return false;
432 return false;
433 }
433 }
434 };
434 };
435
435
436
436
437 /**
437 /**
438 * @class HeadingCell
438 * @class HeadingCell
439 * @extends Ipython.TextCell
439 * @extends Ipython.TextCell
440 */
440 */
441
441
442 /**
442 /**
443 * @constructor HeadingCell
443 * @constructor HeadingCell
444 * @extends Ipython.TextCell
444 * @extends Ipython.TextCell
445 */
445 */
446 var HeadingCell = function () {
446 var HeadingCell = function () {
447 this.placeholder = "Type Heading Here";
447 this.placeholder = "Type Heading Here";
448 IPython.TextCell.apply(this, arguments);
448 IPython.TextCell.apply(this, arguments);
449 /**
449 /**
450 * heading level of the cell, use getter and setter to access
450 * heading level of the cell, use getter and setter to access
451 * @property level
451 * @property level
452 */
452 */
453 this.level = 1;
453 this.level = 1;
454 this.cell_type = 'heading';
454 this.cell_type = 'heading';
455 };
455 };
456
456
457
457
458 HeadingCell.prototype = new TextCell();
458 HeadingCell.prototype = new TextCell();
459
459
460 /** @method fromJSON */
460 /** @method fromJSON */
461 HeadingCell.prototype.fromJSON = function (data) {
461 HeadingCell.prototype.fromJSON = function (data) {
462 if (data.level != undefined){
462 if (data.level != undefined){
463 this.level = data.level;
463 this.level = data.level;
464 }
464 }
465 IPython.TextCell.prototype.fromJSON.apply(this, arguments);
465 IPython.TextCell.prototype.fromJSON.apply(this, arguments);
466 };
466 };
467
467
468
468
469 /** @method toJSON */
469 /** @method toJSON */
470 HeadingCell.prototype.toJSON = function () {
470 HeadingCell.prototype.toJSON = function () {
471 var data = IPython.TextCell.prototype.toJSON.apply(this);
471 var data = IPython.TextCell.prototype.toJSON.apply(this);
472 data.level = this.get_level();
472 data.level = this.get_level();
473 return data;
473 return data;
474 };
474 };
475
475
476
476
477 /**
477 /**
478 * Change heading level of cell, and re-render
478 * Change heading level of cell, and re-render
479 * @method set_level
479 * @method set_level
480 */
480 */
481 HeadingCell.prototype.set_level = function (level) {
481 HeadingCell.prototype.set_level = function (level) {
482 this.level = level;
482 this.level = level;
483 if (this.rendered) {
483 if (this.rendered) {
484 this.rendered = false;
484 this.rendered = false;
485 this.render();
485 this.render();
486 };
486 };
487 };
487 };
488
488
489 /** The depth of header cell, based on html (h1 to h6)
489 /** The depth of header cell, based on html (h1 to h6)
490 * @method get_level
490 * @method get_level
491 * @return {integer} level - for 1 to 6
491 * @return {integer} level - for 1 to 6
492 */
492 */
493 HeadingCell.prototype.get_level = function () {
493 HeadingCell.prototype.get_level = function () {
494 return this.level;
494 return this.level;
495 };
495 };
496
496
497
497
498 HeadingCell.prototype.set_rendered = function (text) {
498 HeadingCell.prototype.set_rendered = function (text) {
499 var r = this.element.find("div.text_cell_render");
499 var r = this.element.find("div.text_cell_render");
500 r.empty();
500 r.empty();
501 r.append($('<h'+this.level+'/>').html(text));
501 r.append($('<h'+this.level+'/>').html(text));
502 };
502 };
503
503
504
504
505 HeadingCell.prototype.get_rendered = function () {
505 HeadingCell.prototype.get_rendered = function () {
506 var r = this.element.find("div.text_cell_render");
506 var r = this.element.find("div.text_cell_render");
507 return r.children().first().html();
507 return r.children().first().html();
508 };
508 };
509
509
510
510
511 HeadingCell.prototype.render = function () {
511 HeadingCell.prototype.render = function () {
512 if (this.rendered === false) {
512 if (this.rendered === false) {
513 var text = this.get_text();
513 var text = this.get_text();
514 if (text === "") { text = this.placeholder; }
514 if (text === "") { text = this.placeholder; }
515 this.set_rendered(text);
515 this.set_rendered(text);
516 this.typeset();
516 this.typeset();
517 this.element.find('div.text_cell_input').hide();
517 this.element.find('div.text_cell_input').hide();
518 this.element.find("div.text_cell_render").show();
518 this.element.find("div.text_cell_render").show();
519 this.rendered = true;
519 this.rendered = true;
520 };
520 };
521 };
521 };
522
522
523 IPython.TextCell = TextCell;
523 IPython.TextCell = TextCell;
524 IPython.HTMLCell = HTMLCell;
524 IPython.HTMLCell = HTMLCell;
525 IPython.MarkdownCell = MarkdownCell;
525 IPython.MarkdownCell = MarkdownCell;
526 IPython.RawCell = RawCell;
526 IPython.RawCell = RawCell;
527 IPython.HeadingCell = HeadingCell;
527 IPython.HeadingCell = HeadingCell;
528
528
529
529
530 return IPython;
530 return IPython;
531
531
532 }(IPython));
532 }(IPython));
533
533
General Comments 0
You need to be logged in to leave comments. Login now