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