##// END OF EJS Templates
add doc to base Cell
Matthias BUSSONNIER -
Show More
@@ -1,240 +1,252
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 * @module Cell
12 * @module Cell
13 * An extendable module that provide base functionnality to create cell for notebook.
13 * An extendable module that provide base functionnality to create cell for notebook.
14 */
14 */
15
15
16 var IPython = (function (IPython) {
16 var IPython = (function (IPython) {
17
17
18 var utils = IPython.utils;
18 var utils = IPython.utils;
19
19
20 /**
20 /**
21 * The Base `Cell` class from which to inherit
21 * The Base `Cell` class from which to inherit
22 * @class Cell
22 * @class Cell
23 */
23 */
24
24
25 /*
25 /*
26 * @constructor
26 * @constructor
27 */
27 */
28 var Cell = function () {
28 var Cell = function () {
29 this.placeholder = this.placeholder || '';
29 this.placeholder = this.placeholder || '';
30 this.read_only = false;
30 this.read_only = false;
31 this.selected = false;
31 this.selected = false;
32 this.element = null;
32 this.element = null;
33 this.metadata = {};
33 this.metadata = {};
34 // load this from metadata later ?
34 // load this from metadata later ?
35 this.user_highlight == 'auto';
35 this.user_highlight == 'auto';
36 this.create_element();
36 this.create_element();
37 if (this.element !== null) {
37 if (this.element !== null) {
38 this.element.data("cell", this);
38 this.element.data("cell", this);
39 this.bind_events();
39 this.bind_events();
40 }
40 }
41 this.cell_id = utils.uuid();
41 this.cell_id = utils.uuid();
42 };
42 };
43
43
44
44
45 /**
45 /**
46 * Empty. Subclasses must implement create_element.
46 * Empty. Subclasses must implement create_element.
47 * This should contain all the code to create the DOM element in notebook
47 * This should contain all the code to create the DOM element in notebook
48 * and will be called by Base Class constructor.
48 * and will be called by Base Class constructor.
49 * @method create_element
49 * @method create_element
50 */
50 */
51 Cell.prototype.create_element = function () {};
51 Cell.prototype.create_element = function () {};
52
52
53
53
54 /**
54 /**
55 * Empty. Subclasses must implement create_element.
55 * Subclasses can implement override bind_events.
56 * This should contain all the code to create the DOM element in notebook
56 * Be carefull to call the parent method when overwriting as it fires event.
57 * and will be called by Base Class constructor.
57 * this will be triggerd after create_element in constructor.
58 * @method bind_events
58 * @method bind_events
59 */
59 */
60 Cell.prototype.bind_events = function () {
60 Cell.prototype.bind_events = function () {
61 var that = this;
61 var that = this;
62 // We trigger events so that Cell doesn't have to depend on Notebook.
62 // We trigger events so that Cell doesn't have to depend on Notebook.
63 that.element.click(function (event) {
63 that.element.click(function (event) {
64 if (that.selected === false) {
64 if (that.selected === false) {
65 $([IPython.events]).trigger('select.Cell', {'cell':that});
65 $([IPython.events]).trigger('select.Cell', {'cell':that});
66 }
66 }
67 });
67 });
68 that.element.focusin(function (event) {
68 that.element.focusin(function (event) {
69 if (that.selected === false) {
69 if (that.selected === false) {
70 $([IPython.events]).trigger('select.Cell', {'cell':that});
70 $([IPython.events]).trigger('select.Cell', {'cell':that});
71 }
71 }
72 });
72 });
73 };
73 };
74
74
75 /**
76 * Triger typsetting of math by mathjax on current cell element
77 * @method typeset
78 */
75 Cell.prototype.typeset = function () {
79 Cell.prototype.typeset = function () {
76 if (window.MathJax){
80 if (window.MathJax){
77 var cell_math = this.element.get(0);
81 var cell_math = this.element.get(0);
78 MathJax.Hub.Queue(["Typeset",MathJax.Hub,cell_math]);
82 MathJax.Hub.Queue(["Typeset",MathJax.Hub,cell_math]);
79 }
83 }
80 };
84 };
81
85
86 /**
87 * should be triggerd when cell is selected
88 * @method select
89 */
82 Cell.prototype.select = function () {
90 Cell.prototype.select = function () {
83 this.element.addClass('ui-widget-content ui-corner-all');
91 this.element.addClass('ui-widget-content ui-corner-all');
84 this.selected = true;
92 this.selected = true;
85 };
93 };
86
94
87
95
96 /**
97 * should be triggerd when cell is unselected
98 * @method unselect
99 */
88 Cell.prototype.unselect = function () {
100 Cell.prototype.unselect = function () {
89 this.element.removeClass('ui-widget-content ui-corner-all');
101 this.element.removeClass('ui-widget-content ui-corner-all');
90 this.selected = false;
102 this.selected = false;
91 };
103 };
92
104
93
105
94 Cell.prototype.get_text = function () {
106 Cell.prototype.get_text = function () {
95 };
107 };
96
108
97
109
98 Cell.prototype.set_text = function (text) {
110 Cell.prototype.set_text = function (text) {
99 };
111 };
100
112
101
113
102 Cell.prototype.refresh = function () {
114 Cell.prototype.refresh = function () {
103 this.code_mirror.refresh();
115 this.code_mirror.refresh();
104 };
116 };
105
117
106
118
107 Cell.prototype.edit = function () {
119 Cell.prototype.edit = function () {
108 };
120 };
109
121
110
122
111 Cell.prototype.render = function () {
123 Cell.prototype.render = function () {
112 };
124 };
113
125
114
126
115 Cell.prototype.toJSON = function () {
127 Cell.prototype.toJSON = function () {
116 var data = {};
128 var data = {};
117 data.metadata = this.metadata;
129 data.metadata = this.metadata;
118 return data;
130 return data;
119 };
131 };
120
132
121
133
122 Cell.prototype.fromJSON = function (data) {
134 Cell.prototype.fromJSON = function (data) {
123 if (data.metadata !== undefined) {
135 if (data.metadata !== undefined) {
124 this.metadata = data.metadata;
136 this.metadata = data.metadata;
125 }
137 }
126 };
138 };
127
139
128
140
129 Cell.prototype.is_splittable = function () {
141 Cell.prototype.is_splittable = function () {
130 return true;
142 return true;
131 };
143 };
132
144
133
145
134 Cell.prototype.get_pre_cursor = function () {
146 Cell.prototype.get_pre_cursor = function () {
135 var cursor = this.code_mirror.getCursor();
147 var cursor = this.code_mirror.getCursor();
136 var text = this.code_mirror.getRange({line:0,ch:0}, cursor);
148 var text = this.code_mirror.getRange({line:0,ch:0}, cursor);
137 text = text.replace(/^\n+/, '').replace(/\n+$/, '');
149 text = text.replace(/^\n+/, '').replace(/\n+$/, '');
138 return text;
150 return text;
139 }
151 }
140
152
141
153
142 Cell.prototype.get_post_cursor = function () {
154 Cell.prototype.get_post_cursor = function () {
143 var cursor = this.code_mirror.getCursor();
155 var cursor = this.code_mirror.getCursor();
144 var last_line_num = this.code_mirror.lineCount()-1;
156 var last_line_num = this.code_mirror.lineCount()-1;
145 var last_line_len = this.code_mirror.getLine(last_line_num).length;
157 var last_line_len = this.code_mirror.getLine(last_line_num).length;
146 var end = {line:last_line_num, ch:last_line_len}
158 var end = {line:last_line_num, ch:last_line_len}
147 var text = this.code_mirror.getRange(cursor, end);
159 var text = this.code_mirror.getRange(cursor, end);
148 text = text.replace(/^\n+/, '').replace(/\n+$/, '');
160 text = text.replace(/^\n+/, '').replace(/\n+$/, '');
149 return text;
161 return text;
150 };
162 };
151
163
152
164
153 Cell.prototype.grow = function(element) {
165 Cell.prototype.grow = function(element) {
154 // Grow the cell by hand. This is used upon reloading from JSON, when the
166 // Grow the cell by hand. This is used upon reloading from JSON, when the
155 // autogrow handler is not called.
167 // autogrow handler is not called.
156 var dom = element.get(0);
168 var dom = element.get(0);
157 var lines_count = 0;
169 var lines_count = 0;
158 // modified split rule from
170 // modified split rule from
159 // http://stackoverflow.com/questions/2035910/how-to-get-the-number-of-lines-in-a-textarea/2036424#2036424
171 // http://stackoverflow.com/questions/2035910/how-to-get-the-number-of-lines-in-a-textarea/2036424#2036424
160 var lines = dom.value.split(/\r|\r\n|\n/);
172 var lines = dom.value.split(/\r|\r\n|\n/);
161 lines_count = lines.length;
173 lines_count = lines.length;
162 if (lines_count >= 1) {
174 if (lines_count >= 1) {
163 dom.rows = lines_count;
175 dom.rows = lines_count;
164 } else {
176 } else {
165 dom.rows = 1;
177 dom.rows = 1;
166 }
178 }
167 };
179 };
168
180
169
181
170 Cell.prototype.toggle_line_numbers = function () {
182 Cell.prototype.toggle_line_numbers = function () {
171 if (this.code_mirror.getOption('lineNumbers') == false) {
183 if (this.code_mirror.getOption('lineNumbers') == false) {
172 this.code_mirror.setOption('lineNumbers', true);
184 this.code_mirror.setOption('lineNumbers', true);
173 } else {
185 } else {
174 this.code_mirror.setOption('lineNumbers', false);
186 this.code_mirror.setOption('lineNumbers', false);
175 }
187 }
176 this.code_mirror.refresh();
188 this.code_mirror.refresh();
177 };
189 };
178
190
179 Cell.prototype.force_highlight = function(mode) {
191 Cell.prototype.force_highlight = function(mode) {
180 this.user_highlight = mode;
192 this.user_highlight = mode;
181 this.auto_highlight();
193 this.auto_highlight();
182 };
194 };
183
195
184 Cell.prototype._auto_highlight = function (modes) {
196 Cell.prototype._auto_highlight = function (modes) {
185 //Here we handle manually selected modes
197 //Here we handle manually selected modes
186 if( this.user_highlight != undefined && this.user_highlight != 'auto' )
198 if( this.user_highlight != undefined && this.user_highlight != 'auto' )
187 {
199 {
188 var mode = this.user_highlight;
200 var mode = this.user_highlight;
189 CodeMirror.autoLoadMode(this.code_mirror, mode);
201 CodeMirror.autoLoadMode(this.code_mirror, mode);
190 this.code_mirror.setOption('mode', mode);
202 this.code_mirror.setOption('mode', mode);
191 return;
203 return;
192 }
204 }
193 var first_line = this.code_mirror.getLine(0);
205 var first_line = this.code_mirror.getLine(0);
194 // loop on every pairs
206 // loop on every pairs
195 for( var mode in modes) {
207 for( var mode in modes) {
196 var regs = modes[mode]['reg'];
208 var regs = modes[mode]['reg'];
197 // only one key every time but regexp can't be keys...
209 // only one key every time but regexp can't be keys...
198 for(var reg in regs ) {
210 for(var reg in regs ) {
199 // here we handle non magic_modes
211 // here we handle non magic_modes
200 if(first_line.match(regs[reg]) != null) {
212 if(first_line.match(regs[reg]) != null) {
201 if (mode.search('magic_') != 0) {
213 if (mode.search('magic_') != 0) {
202 this.code_mirror.setOption('mode',mode);
214 this.code_mirror.setOption('mode',mode);
203 CodeMirror.autoLoadMode(this.code_mirror, mode);
215 CodeMirror.autoLoadMode(this.code_mirror, mode);
204 return;
216 return;
205 }
217 }
206 var open = modes[mode]['open']|| "%%";
218 var open = modes[mode]['open']|| "%%";
207 var close = modes[mode]['close']|| "%%end";
219 var close = modes[mode]['close']|| "%%end";
208 var mmode = mode;
220 var mmode = mode;
209 mode = mmode.substr(6);
221 mode = mmode.substr(6);
210 CodeMirror.autoLoadMode(this.code_mirror, mode);
222 CodeMirror.autoLoadMode(this.code_mirror, mode);
211 // create on the fly a mode that swhitch between
223 // create on the fly a mode that swhitch between
212 // plain/text and smth else otherwise `%%` is
224 // plain/text and smth else otherwise `%%` is
213 // source of some highlight issues.
225 // source of some highlight issues.
214 // we use patchedGetMode to circumvent a bug in CM
226 // we use patchedGetMode to circumvent a bug in CM
215 CodeMirror.defineMode(mmode , function(config) {
227 CodeMirror.defineMode(mmode , function(config) {
216 return CodeMirror.multiplexingMode(
228 return CodeMirror.multiplexingMode(
217 CodeMirror.patchedGetMode(config, 'text/plain'),
229 CodeMirror.patchedGetMode(config, 'text/plain'),
218 // always set someting on close
230 // always set someting on close
219 {open: open, close: close,
231 {open: open, close: close,
220 mode: CodeMirror.patchedGetMode(config, mode),
232 mode: CodeMirror.patchedGetMode(config, mode),
221 delimStyle: "delimit"
233 delimStyle: "delimit"
222 }
234 }
223 );
235 );
224 });
236 });
225 this.code_mirror.setOption('mode', mmode);
237 this.code_mirror.setOption('mode', mmode);
226 return;
238 return;
227 }
239 }
228 }
240 }
229 }
241 }
230 // fallback on default (python)
242 // fallback on default (python)
231 var default_mode = this.default_mode || 'text/plain';
243 var default_mode = this.default_mode || 'text/plain';
232 this.code_mirror.setOption('mode', default_mode);
244 this.code_mirror.setOption('mode', default_mode);
233 };
245 };
234
246
235 IPython.Cell = Cell;
247 IPython.Cell = Cell;
236
248
237 return IPython;
249 return IPython;
238
250
239 }(IPython));
251 }(IPython));
240
252
@@ -1,528 +1,529
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 */
14 */
15 var IPython = (function (IPython) {
15 var IPython = (function (IPython) {
16
16
17 // TextCell base class
17 // TextCell base class
18 var key = IPython.utils.keycodes;
18 var key = IPython.utils.keycodes;
19
19
20 /**
20 /**
21 * Construct a new TextCell, codemirror mode is by default 'htmlmixed', and cell type is 'text'
21 * Construct a new TextCell, codemirror mode is by default 'htmlmixed', and cell type is 'text'
22 * cell start as not redered.
22 * cell start as not redered.
23 *
23 *
24 * @class TextCell
24 * @class TextCell
25 * @constructor TextCell
25 * @constructor TextCell
26 * @extend Cell
26 */
27 */
27 var TextCell = function () {
28 var TextCell = function () {
28 this.code_mirror_mode = this.code_mirror_mode || 'htmlmixed';
29 this.code_mirror_mode = this.code_mirror_mode || 'htmlmixed';
29 IPython.Cell.apply(this, arguments);
30 IPython.Cell.apply(this, arguments);
30 this.rendered = false;
31 this.rendered = false;
31 this.cell_type = this.cell_type || 'text';
32 this.cell_type = this.cell_type || 'text';
32 };
33 };
33
34
34 TextCell.prototype = new IPython.Cell();
35 TextCell.prototype = new IPython.Cell();
35
36
36 /**
37 /**
37 * Create the DOM element of the TextCell
38 * Create the DOM element of the TextCell
38 * @method create_element
39 * @method create_element
39 * @private
40 * @private
40 */
41 */
41 TextCell.prototype.create_element = function () {
42 TextCell.prototype.create_element = function () {
42 var cell = $("<div>").addClass('cell text_cell border-box-sizing');
43 var cell = $("<div>").addClass('cell text_cell border-box-sizing');
43 cell.attr('tabindex','2');
44 cell.attr('tabindex','2');
44 var input_area = $('<div/>').addClass('text_cell_input border-box-sizing');
45 var input_area = $('<div/>').addClass('text_cell_input border-box-sizing');
45 this.code_mirror = CodeMirror(input_area.get(0), {
46 this.code_mirror = CodeMirror(input_area.get(0), {
46 indentUnit : 4,
47 indentUnit : 4,
47 mode: this.code_mirror_mode,
48 mode: this.code_mirror_mode,
48 theme: 'default',
49 theme: 'default',
49 value: this.placeholder,
50 value: this.placeholder,
50 readOnly: this.read_only,
51 readOnly: this.read_only,
51 lineWrapping : true,
52 lineWrapping : true,
52 extraKeys: {"Tab": "indentMore","Shift-Tab" : "indentLess"},
53 extraKeys: {"Tab": "indentMore","Shift-Tab" : "indentLess"},
53 onKeyEvent: $.proxy(this.handle_codemirror_keyevent,this)
54 onKeyEvent: $.proxy(this.handle_codemirror_keyevent,this)
54 });
55 });
55 // The tabindex=-1 makes this div focusable.
56 // The tabindex=-1 makes this div focusable.
56 var render_area = $('<div/>').addClass('text_cell_render border-box-sizing').
57 var render_area = $('<div/>').addClass('text_cell_render border-box-sizing').
57 addClass('rendered_html').attr('tabindex','-1');
58 addClass('rendered_html').attr('tabindex','-1');
58 cell.append(input_area).append(render_area);
59 cell.append(input_area).append(render_area);
59 this.element = cell;
60 this.element = cell;
60 };
61 };
61
62
62
63
63 /**
64 /**
64 * Bind the DOM evet to cell actions
65 * Bind the DOM evet to cell actions
65 * Need to be called after TextCell.create_element
66 * Need to be called after TextCell.create_element
66 * @private
67 * @private
67 * @method bind_event
68 * @method bind_event
68 */
69 */
69 TextCell.prototype.bind_events = function () {
70 TextCell.prototype.bind_events = function () {
70 IPython.Cell.prototype.bind_events.apply(this);
71 IPython.Cell.prototype.bind_events.apply(this);
71 var that = this;
72 var that = this;
72 this.element.keydown(function (event) {
73 this.element.keydown(function (event) {
73 if (event.which === 13 && !event.shiftKey) {
74 if (event.which === 13 && !event.shiftKey) {
74 if (that.rendered) {
75 if (that.rendered) {
75 that.edit();
76 that.edit();
76 return false;
77 return false;
77 };
78 };
78 };
79 };
79 });
80 });
80 this.element.dblclick(function () {
81 this.element.dblclick(function () {
81 that.edit();
82 that.edit();
82 });
83 });
83 };
84 };
84
85
85 /**
86 /**
86 * This method gets called in CodeMirror's onKeyDown/onKeyPress
87 * This method gets called in CodeMirror's onKeyDown/onKeyPress
87 * handlers and is used to provide custom key handling.
88 * handlers and is used to provide custom key handling.
88 *
89 *
89 * Subclass should override this method to have custom handeling
90 * Subclass should override this method to have custom handeling
90 *
91 *
91 * @method handle_codemirror_keyevent
92 * @method handle_codemirror_keyevent
92 * @param {CodeMirror} editor - The codemirror instance bound to the cell
93 * @param {CodeMirror} editor - The codemirror instance bound to the cell
93 * @param {event} event -
94 * @param {event} event -
94 * @return {Boolean} `true` if CodeMirror should ignore the event, `false` Otherwise
95 * @return {Boolean} `true` if CodeMirror should ignore the event, `false` Otherwise
95 */
96 */
96 TextCell.prototype.handle_codemirror_keyevent = function (editor, event) {
97 TextCell.prototype.handle_codemirror_keyevent = function (editor, event) {
97
98
98 if (event.keyCode === 13 && (event.shiftKey || event.ctrlKey)) {
99 if (event.keyCode === 13 && (event.shiftKey || event.ctrlKey)) {
99 // Always ignore shift-enter in CodeMirror as we handle it.
100 // Always ignore shift-enter in CodeMirror as we handle it.
100 return true;
101 return true;
101 }
102 }
102 return false;
103 return false;
103 };
104 };
104
105
105 /**
106 /**
106 * Select the current cell and trigger 'focus'
107 * Select the current cell and trigger 'focus'
107 * @method select
108 * @method select
108 */
109 */
109 TextCell.prototype.select = function () {
110 TextCell.prototype.select = function () {
110 IPython.Cell.prototype.select.apply(this);
111 IPython.Cell.prototype.select.apply(this);
111 var output = this.element.find("div.text_cell_render");
112 var output = this.element.find("div.text_cell_render");
112 output.trigger('focus');
113 output.trigger('focus');
113 };
114 };
114
115
115 /**
116 /**
116 * unselect the current cell and `render` it
117 * unselect the current cell and `render` it
117 * @method unselect
118 * @method unselect
118 */
119 */
119 TextCell.prototype.unselect = function() {
120 TextCell.prototype.unselect = function() {
120 // render on selection of another cell
121 // render on selection of another cell
121 this.render();
122 this.render();
122 IPython.Cell.prototype.unselect.apply(this);
123 IPython.Cell.prototype.unselect.apply(this);
123 };
124 };
124
125
125 /**
126 /**
126 *
127 *
127 * put the current cell in edition mode
128 * put the current cell in edition mode
128 * @method edit
129 * @method edit
129 */
130 */
130 TextCell.prototype.edit = function () {
131 TextCell.prototype.edit = function () {
131 if ( this.read_only ) return;
132 if ( this.read_only ) return;
132 if (this.rendered === true) {
133 if (this.rendered === true) {
133 var text_cell = this.element;
134 var text_cell = this.element;
134 var output = text_cell.find("div.text_cell_render");
135 var output = text_cell.find("div.text_cell_render");
135 output.hide();
136 output.hide();
136 text_cell.find('div.text_cell_input').show();
137 text_cell.find('div.text_cell_input').show();
137 this.code_mirror.refresh();
138 this.code_mirror.refresh();
138 this.code_mirror.focus();
139 this.code_mirror.focus();
139 // We used to need an additional refresh() after the focus, but
140 // We used to need an additional refresh() after the focus, but
140 // it appears that this has been fixed in CM. This bug would show
141 // it appears that this has been fixed in CM. This bug would show
141 // up on FF when a newly loaded markdown cell was edited.
142 // up on FF when a newly loaded markdown cell was edited.
142 this.rendered = false;
143 this.rendered = false;
143 if (this.get_text() === this.placeholder) {
144 if (this.get_text() === this.placeholder) {
144 this.set_text('');
145 this.set_text('');
145 this.refresh();
146 this.refresh();
146 }
147 }
147 }
148 }
148 };
149 };
149
150
150
151
151 /**
152 /**
152 * Empty, Subclasses must define render.
153 * Empty, Subclasses must define render.
153 * @method render
154 * @method render
154 */
155 */
155 TextCell.prototype.render = function () {};
156 TextCell.prototype.render = function () {};
156
157
157
158
158 /**
159 /**
159 * setter: {{#crossLink "TextCell/set_text"}}{{/crossLink}}
160 * setter: {{#crossLink "TextCell/set_text"}}{{/crossLink}}
160 * @method get_text
161 * @method get_text
161 * @retrun {string} CodeMirror current text value
162 * @retrun {string} CodeMirror current text value
162 */
163 */
163 TextCell.prototype.get_text = function() {
164 TextCell.prototype.get_text = function() {
164 return this.code_mirror.getValue();
165 return this.code_mirror.getValue();
165 };
166 };
166
167
167 /**
168 /**
168 * @param {string} text - Codemiror text value
169 * @param {string} text - Codemiror text value
169 * @see TextCell#get_text
170 * @see TextCell#get_text
170 * @method set_text
171 * @method set_text
171 * */
172 * */
172 TextCell.prototype.set_text = function(text) {
173 TextCell.prototype.set_text = function(text) {
173 this.code_mirror.setValue(text);
174 this.code_mirror.setValue(text);
174 this.code_mirror.refresh();
175 this.code_mirror.refresh();
175 };
176 };
176
177
177 /**
178 /**
178 * setter :{{#crossLink "TextCell/set_rendered"}}{{/crossLink}}
179 * setter :{{#crossLink "TextCell/set_rendered"}}{{/crossLink}}
179 * @method get_rendered
180 * @method get_rendered
180 * @return {html} html of rendered element
181 * @return {html} html of rendered element
181 * */
182 * */
182 TextCell.prototype.get_rendered = function() {
183 TextCell.prototype.get_rendered = function() {
183 return this.element.find('div.text_cell_render').html();
184 return this.element.find('div.text_cell_render').html();
184 };
185 };
185
186
186 /**
187 /**
187 * @method set_rendered
188 * @method set_rendered
188 */
189 */
189 TextCell.prototype.set_rendered = function(text) {
190 TextCell.prototype.set_rendered = function(text) {
190 this.element.find('div.text_cell_render').html(text);
191 this.element.find('div.text_cell_render').html(text);
191 };
192 };
192
193
193 /**
194 /**
194 * not deprecated, but implementation wrong
195 * not deprecated, but implementation wrong
195 * @method at_top
196 * @method at_top
196 * @deprecated
197 * @deprecated
197 * @return {Boolean} true is cell rendered, false otherwise
198 * @return {Boolean} true is cell rendered, false otherwise
198 * I doubt this is what it is supposed to do
199 * I doubt this is what it is supposed to do
199 * this implementation is completly false
200 * this implementation is completly false
200 */
201 */
201 TextCell.prototype.at_top = function () {
202 TextCell.prototype.at_top = function () {
202 if (this.rendered) {
203 if (this.rendered) {
203 return true;
204 return true;
204 } else {
205 } else {
205 return false;
206 return false;
206 }
207 }
207 };
208 };
208
209
209
210
210 /**
211 /**
211 * not deprecated, but implementation wrong
212 * not deprecated, but implementation wrong
212 * @method at_bottom
213 * @method at_bottom
213 * @deprecated
214 * @deprecated
214 * @return {Boolean} true is cell rendered, false otherwise
215 * @return {Boolean} true is cell rendered, false otherwise
215 * I doubt this is what it is supposed to do
216 * I doubt this is what it is supposed to do
216 * this implementation is completly false
217 * this implementation is completly false
217 * */
218 * */
218 TextCell.prototype.at_bottom = function () {
219 TextCell.prototype.at_bottom = function () {
219 if (this.rendered) {
220 if (this.rendered) {
220 return true;
221 return true;
221 } else {
222 } else {
222 return false;
223 return false;
223 }
224 }
224 };
225 };
225
226
226 /**
227 /**
227 * Create Text cell from JSON
228 * Create Text cell from JSON
228 * @param {json} data - JSON serialized text-cell
229 * @param {json} data - JSON serialized text-cell
229 * @method fromJSON
230 * @method fromJSON
230 */
231 */
231 TextCell.prototype.fromJSON = function (data) {
232 TextCell.prototype.fromJSON = function (data) {
232 IPython.Cell.prototype.fromJSON.apply(this, arguments);
233 IPython.Cell.prototype.fromJSON.apply(this, arguments);
233 if (data.cell_type === this.cell_type) {
234 if (data.cell_type === this.cell_type) {
234 if (data.source !== undefined) {
235 if (data.source !== undefined) {
235 this.set_text(data.source);
236 this.set_text(data.source);
236 // make this value the starting point, so that we can only undo
237 // make this value the starting point, so that we can only undo
237 // to this state, instead of a blank cell
238 // to this state, instead of a blank cell
238 this.code_mirror.clearHistory();
239 this.code_mirror.clearHistory();
239 this.set_rendered(data.rendered || '');
240 this.set_rendered(data.rendered || '');
240 this.rendered = false;
241 this.rendered = false;
241 this.render();
242 this.render();
242 }
243 }
243 }
244 }
244 };
245 };
245
246
246 /** Generate JSON from cell
247 /** Generate JSON from cell
247 * @return {object} cell data serialised to json
248 * @return {object} cell data serialised to json
248 */
249 */
249 TextCell.prototype.toJSON = function () {
250 TextCell.prototype.toJSON = function () {
250 var data = IPython.Cell.prototype.toJSON.apply(this);
251 var data = IPython.Cell.prototype.toJSON.apply(this);
251 data.cell_type = this.cell_type;
252 data.cell_type = this.cell_type;
252 data.source = this.get_text();
253 data.source = this.get_text();
253 return data;
254 return data;
254 };
255 };
255
256
256
257
257 /**
258 /**
258 * @constructor HtmlCell
259 * @constructor HtmlCell
259 * @class HtmlCell
260 * @class HtmlCell
260 * @extends TextCell
261 * @extends TextCell
261 */
262 */
262 var HTMLCell = function () {
263 var HTMLCell = function () {
263 this.placeholder = "Type <strong>HTML</strong> and LaTeX: $\\alpha^2$";
264 this.placeholder = "Type <strong>HTML</strong> and LaTeX: $\\alpha^2$";
264 IPython.TextCell.apply(this, arguments);
265 IPython.TextCell.apply(this, arguments);
265 this.cell_type = 'html';
266 this.cell_type = 'html';
266 };
267 };
267
268
268
269
269 HTMLCell.prototype = new TextCell();
270 HTMLCell.prototype = new TextCell();
270
271
271 /**
272 /**
272 * @method render
273 * @method render
273 */
274 */
274 HTMLCell.prototype.render = function () {
275 HTMLCell.prototype.render = function () {
275 if (this.rendered === false) {
276 if (this.rendered === false) {
276 var text = this.get_text();
277 var text = this.get_text();
277 if (text === "") { text = this.placeholder; }
278 if (text === "") { text = this.placeholder; }
278 this.set_rendered(text);
279 this.set_rendered(text);
279 this.typeset();
280 this.typeset();
280 this.element.find('div.text_cell_input').hide();
281 this.element.find('div.text_cell_input').hide();
281 this.element.find("div.text_cell_render").show();
282 this.element.find("div.text_cell_render").show();
282 this.rendered = true;
283 this.rendered = true;
283 }
284 }
284 };
285 };
285
286
286
287
287 /**
288 /**
288 * @class MarkdownCell
289 * @class MarkdownCell
289 * @constructor MarkdownCell
290 * @constructor MarkdownCell
290 * @extends HtmlCell
291 * @extends HtmlCell
291 */
292 */
292 var MarkdownCell = function () {
293 var MarkdownCell = function () {
293 this.placeholder = "Type *Markdown* and LaTeX: $\\alpha^2$";
294 this.placeholder = "Type *Markdown* and LaTeX: $\\alpha^2$";
294 IPython.TextCell.apply(this, arguments);
295 IPython.TextCell.apply(this, arguments);
295 this.cell_type = 'markdown';
296 this.cell_type = 'markdown';
296 };
297 };
297
298
298
299
299 MarkdownCell.prototype = new TextCell();
300 MarkdownCell.prototype = new TextCell();
300
301
301 /**
302 /**
302 * @method render
303 * @method render
303 */
304 */
304 MarkdownCell.prototype.render = function () {
305 MarkdownCell.prototype.render = function () {
305 if (this.rendered === false) {
306 if (this.rendered === false) {
306 var text = this.get_text();
307 var text = this.get_text();
307 if (text === "") { text = this.placeholder; }
308 if (text === "") { text = this.placeholder; }
308 text = IPython.mathjaxutils.remove_math(text)
309 text = IPython.mathjaxutils.remove_math(text)
309 var html = IPython.markdown_converter.makeHtml(text);
310 var html = IPython.markdown_converter.makeHtml(text);
310 html = IPython.mathjaxutils.replace_math(html)
311 html = IPython.mathjaxutils.replace_math(html)
311 try {
312 try {
312 this.set_rendered(html);
313 this.set_rendered(html);
313 } catch (e) {
314 } catch (e) {
314 console.log("Error running Javascript in Markdown:");
315 console.log("Error running Javascript in Markdown:");
315 console.log(e);
316 console.log(e);
316 this.set_rendered($("<div/>").addClass("js-error").html(
317 this.set_rendered($("<div/>").addClass("js-error").html(
317 "Error rendering Markdown!<br/>" + e.toString())
318 "Error rendering Markdown!<br/>" + e.toString())
318 );
319 );
319 }
320 }
320 this.element.find('div.text_cell_input').hide();
321 this.element.find('div.text_cell_input').hide();
321 this.element.find("div.text_cell_render").show();
322 this.element.find("div.text_cell_render").show();
322 var code_snippets = this.element.find("pre > code");
323 var code_snippets = this.element.find("pre > code");
323 code_snippets.replaceWith(function () {
324 code_snippets.replaceWith(function () {
324 var code = $(this).html();
325 var code = $(this).html();
325 /* Substitute br for newlines and &nbsp; for spaces
326 /* Substitute br for newlines and &nbsp; for spaces
326 before highlighting, since prettify doesn't
327 before highlighting, since prettify doesn't
327 preserve those on all browsers */
328 preserve those on all browsers */
328 code = code.replace(/(\r\n|\n|\r)/gm, "<br/>");
329 code = code.replace(/(\r\n|\n|\r)/gm, "<br/>");
329 code = code.replace(/ /gm, '&nbsp;');
330 code = code.replace(/ /gm, '&nbsp;');
330 code = prettyPrintOne(code);
331 code = prettyPrintOne(code);
331
332
332 return '<code class="prettyprint">' + code + '</code>';
333 return '<code class="prettyprint">' + code + '</code>';
333 });
334 });
334 this.typeset()
335 this.typeset()
335 this.rendered = true;
336 this.rendered = true;
336 }
337 }
337 };
338 };
338
339
339
340
340 // RawCell
341 // RawCell
341
342
342 /**
343 /**
343 * @class RawCell
344 * @class RawCell
344 * @constructor RawCell
345 * @constructor RawCell
345 * @extends TextCell
346 * @extends TextCell
346 */
347 */
347 var RawCell = function () {
348 var RawCell = function () {
348 this.placeholder = "Type plain text and LaTeX: $\\alpha^2$";
349 this.placeholder = "Type plain text and LaTeX: $\\alpha^2$";
349 this.code_mirror_mode = 'rst';
350 this.code_mirror_mode = 'rst';
350 IPython.TextCell.apply(this, arguments);
351 IPython.TextCell.apply(this, arguments);
351 this.cell_type = 'raw';
352 this.cell_type = 'raw';
352 var that = this
353 var that = this
353
354
354 this.element.focusout(
355 this.element.focusout(
355 function() { that.auto_highlight(); }
356 function() { that.auto_highlight(); }
356 );
357 );
357 };
358 };
358
359
359
360
360 RawCell.prototype = new TextCell();
361 RawCell.prototype = new TextCell();
361
362
362 /**
363 /**
363 * Trigger autodetection of highlight scheme for current cell
364 * Trigger autodetection of highlight scheme for current cell
364 * @method auto_highlight
365 * @method auto_highlight
365 */
366 */
366 RawCell.prototype.auto_highlight = function () {
367 RawCell.prototype.auto_highlight = function () {
367 this._auto_highlight(IPython.config.raw_cell_highlight);
368 this._auto_highlight(IPython.config.raw_cell_highlight);
368 };
369 };
369
370
370 /** @method render **/
371 /** @method render **/
371 RawCell.prototype.render = function () {
372 RawCell.prototype.render = function () {
372 this.rendered = true;
373 this.rendered = true;
373 this.edit();
374 this.edit();
374 };
375 };
375
376
376
377
377 /** @method handle_codemirror_keyevent **/
378 /** @method handle_codemirror_keyevent **/
378 RawCell.prototype.handle_codemirror_keyevent = function (editor, event) {
379 RawCell.prototype.handle_codemirror_keyevent = function (editor, event) {
379
380
380 var that = this;
381 var that = this;
381 if (event.which === key.UPARROW && event.type === 'keydown') {
382 if (event.which === key.UPARROW && event.type === 'keydown') {
382 // If we are not at the top, let CM handle the up arrow and
383 // If we are not at the top, let CM handle the up arrow and
383 // prevent the global keydown handler from handling it.
384 // prevent the global keydown handler from handling it.
384 if (!that.at_top()) {
385 if (!that.at_top()) {
385 event.stop();
386 event.stop();
386 return false;
387 return false;
387 } else {
388 } else {
388 return true;
389 return true;
389 };
390 };
390 } else if (event.which === key.DOWNARROW && event.type === 'keydown') {
391 } else if (event.which === key.DOWNARROW && event.type === 'keydown') {
391 // If we are not at the bottom, let CM handle the down arrow and
392 // If we are not at the bottom, let CM handle the down arrow and
392 // prevent the global keydown handler from handling it.
393 // prevent the global keydown handler from handling it.
393 if (!that.at_bottom()) {
394 if (!that.at_bottom()) {
394 event.stop();
395 event.stop();
395 return false;
396 return false;
396 } else {
397 } else {
397 return true;
398 return true;
398 };
399 };
399 };
400 };
400 return false;
401 return false;
401 };
402 };
402
403
403 /** @method select **/
404 /** @method select **/
404 RawCell.prototype.select = function () {
405 RawCell.prototype.select = function () {
405 IPython.Cell.prototype.select.apply(this);
406 IPython.Cell.prototype.select.apply(this);
406 this.code_mirror.refresh();
407 this.code_mirror.refresh();
407 this.code_mirror.focus();
408 this.code_mirror.focus();
408 };
409 };
409
410
410 /** @method at_top **/
411 /** @method at_top **/
411 RawCell.prototype.at_top = function () {
412 RawCell.prototype.at_top = function () {
412 var cursor = this.code_mirror.getCursor();
413 var cursor = this.code_mirror.getCursor();
413 if (cursor.line === 0 && cursor.ch === 0) {
414 if (cursor.line === 0 && cursor.ch === 0) {
414 return true;
415 return true;
415 } else {
416 } else {
416 return false;
417 return false;
417 }
418 }
418 };
419 };
419
420
420
421
421 /** @method at_bottom **/
422 /** @method at_bottom **/
422 RawCell.prototype.at_bottom = function () {
423 RawCell.prototype.at_bottom = function () {
423 var cursor = this.code_mirror.getCursor();
424 var cursor = this.code_mirror.getCursor();
424 if (cursor.line === (this.code_mirror.lineCount()-1) && cursor.ch === this.code_mirror.getLine(cursor.line).length) {
425 if (cursor.line === (this.code_mirror.lineCount()-1) && cursor.ch === this.code_mirror.getLine(cursor.line).length) {
425 return true;
426 return true;
426 } else {
427 } else {
427 return false;
428 return false;
428 }
429 }
429 };
430 };
430
431
431
432
432 /**
433 /**
433 * @class HeadingCell
434 * @class HeadingCell
434 * @extends TextCell
435 * @extends TextCell
435 */
436 */
436
437
437 /**
438 /**
438 * @constructor HeadingCell
439 * @constructor HeadingCell
439 * @extends TextCell
440 * @extends TextCell
440 */
441 */
441 var HeadingCell = function () {
442 var HeadingCell = function () {
442 this.placeholder = "Type Heading Here";
443 this.placeholder = "Type Heading Here";
443 IPython.TextCell.apply(this, arguments);
444 IPython.TextCell.apply(this, arguments);
444 /**
445 /**
445 * heading level of the cell, use getter and setter to access
446 * heading level of the cell, use getter and setter to access
446 * @property level
447 * @property level
447 */
448 */
448 this.level = 1;
449 this.level = 1;
449 this.cell_type = 'heading';
450 this.cell_type = 'heading';
450 };
451 };
451
452
452
453
453 HeadingCell.prototype = new TextCell();
454 HeadingCell.prototype = new TextCell();
454
455
455 /** @method fromJSON */
456 /** @method fromJSON */
456 HeadingCell.prototype.fromJSON = function (data) {
457 HeadingCell.prototype.fromJSON = function (data) {
457 if (data.level != undefined){
458 if (data.level != undefined){
458 this.level = data.level;
459 this.level = data.level;
459 }
460 }
460 IPython.TextCell.prototype.fromJSON.apply(this, arguments);
461 IPython.TextCell.prototype.fromJSON.apply(this, arguments);
461 };
462 };
462
463
463
464
464 /** @method toJSON */
465 /** @method toJSON */
465 HeadingCell.prototype.toJSON = function () {
466 HeadingCell.prototype.toJSON = function () {
466 var data = IPython.TextCell.prototype.toJSON.apply(this);
467 var data = IPython.TextCell.prototype.toJSON.apply(this);
467 data.level = this.get_level();
468 data.level = this.get_level();
468 return data;
469 return data;
469 };
470 };
470
471
471
472
472 /**
473 /**
473 * Change heading level of cell, and re-render
474 * Change heading level of cell, and re-render
474 * @method set_level
475 * @method set_level
475 */
476 */
476 HeadingCell.prototype.set_level = function (level) {
477 HeadingCell.prototype.set_level = function (level) {
477 this.level = level;
478 this.level = level;
478 if (this.rendered) {
479 if (this.rendered) {
479 this.rendered = false;
480 this.rendered = false;
480 this.render();
481 this.render();
481 };
482 };
482 };
483 };
483
484
484 /** The depth of header cell, based on html (h1 to h6)
485 /** The depth of header cell, based on html (h1 to h6)
485 * @method get_level
486 * @method get_level
486 * @return {integer} level - for 1 to 6
487 * @return {integer} level - for 1 to 6
487 */
488 */
488 HeadingCell.prototype.get_level = function () {
489 HeadingCell.prototype.get_level = function () {
489 return this.level;
490 return this.level;
490 };
491 };
491
492
492
493
493 HeadingCell.prototype.set_rendered = function (text) {
494 HeadingCell.prototype.set_rendered = function (text) {
494 var r = this.element.find("div.text_cell_render");
495 var r = this.element.find("div.text_cell_render");
495 r.empty();
496 r.empty();
496 r.append($('<h'+this.level+'/>').html(text));
497 r.append($('<h'+this.level+'/>').html(text));
497 };
498 };
498
499
499
500
500 HeadingCell.prototype.get_rendered = function () {
501 HeadingCell.prototype.get_rendered = function () {
501 var r = this.element.find("div.text_cell_render");
502 var r = this.element.find("div.text_cell_render");
502 return r.children().first().html();
503 return r.children().first().html();
503 };
504 };
504
505
505
506
506 HeadingCell.prototype.render = function () {
507 HeadingCell.prototype.render = function () {
507 if (this.rendered === false) {
508 if (this.rendered === false) {
508 var text = this.get_text();
509 var text = this.get_text();
509 if (text === "") { text = this.placeholder; }
510 if (text === "") { text = this.placeholder; }
510 this.set_rendered(text);
511 this.set_rendered(text);
511 this.typeset();
512 this.typeset();
512 this.element.find('div.text_cell_input').hide();
513 this.element.find('div.text_cell_input').hide();
513 this.element.find("div.text_cell_render").show();
514 this.element.find("div.text_cell_render").show();
514 this.rendered = true;
515 this.rendered = true;
515 };
516 };
516 };
517 };
517
518
518 IPython.TextCell = TextCell;
519 IPython.TextCell = TextCell;
519 IPython.HTMLCell = HTMLCell;
520 IPython.HTMLCell = HTMLCell;
520 IPython.MarkdownCell = MarkdownCell;
521 IPython.MarkdownCell = MarkdownCell;
521 IPython.RawCell = RawCell;
522 IPython.RawCell = RawCell;
522 IPython.HeadingCell = HeadingCell;
523 IPython.HeadingCell = HeadingCell;
523
524
524
525
525 return IPython;
526 return IPython;
526
527
527 }(IPython));
528 }(IPython));
528
529
General Comments 0
You need to be logged in to leave comments. Login now