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