1
//----------------------------------------------------------------------------
2
// Copyright (C) 2008-2011 The IPython Development Team
4
// Distributed under the terms of the BSD License. The full license is in
5
// the file COPYING, distributed as part of this software.
6
//----------------------------------------------------------------------------
8
//============================================================================
10
//============================================================================
12
var IPython = (function (IPython) {
14
// TextCell base class
16
var TextCell = function (notebook) {
17
this.code_mirror_mode = this.code_mirror_mode || 'htmlmixed';
18
IPython.Cell.apply(this, arguments);
19
this.rendered = false;
20
this.cell_type = this.cell_type || 'text';
24
TextCell.prototype = new IPython.Cell();
27
TextCell.prototype.create_element = function () {
28
var cell = $("<div>").addClass('cell text_cell border-box-sizing');
29
cell.attr('tabindex','2');
30
var input_area = $('<div/>').addClass('text_cell_input border-box-sizing');
31
this.code_mirror = CodeMirror(input_area.get(0), {
33
mode: this.code_mirror_mode,
35
value: this.placeholder,
36
readOnly: this.read_only,
38
onKeyEvent: $.proxy(this.handle_codemirror_keyevent,this)
40
// The tabindex=-1 makes this div focusable.
41
var render_area = $('<div/>').addClass('text_cell_render border-box-sizing').
42
addClass('rendered_html').attr('tabindex','-1');
43
cell.append(input_area).append(render_area);
48
TextCell.prototype.bind_events = function () {
49
IPython.Cell.prototype.bind_events.apply(this);
51
this.element.keydown(function (event) {
52
if (event.which === 13 && !event.shiftKey) {
59
this.element.dblclick(function () {
65
TextCell.prototype.handle_codemirror_keyevent = function (editor, event) {
66
// This method gets called in CodeMirror's onKeyDown/onKeyPress
67
// handlers and is used to provide custom key handling. Its return
68
// value is used to determine if CodeMirror should ignore the event:
69
// true = ignore, false = don't ignore.
71
if (event.keyCode === 13 && (event.shiftKey || event.ctrlKey)) {
72
// Always ignore shift-enter in CodeMirror as we handle it.
79
TextCell.prototype.select = function () {
80
IPython.Cell.prototype.select.apply(this);
81
var output = this.element.find("div.text_cell_render");
82
output.trigger('focus');
86
TextCell.prototype.unselect = function() {
87
// render on selection of another cell
89
IPython.Cell.prototype.unselect.apply(this);
93
TextCell.prototype.edit = function () {
94
if ( this.read_only ) return;
95
if (this.rendered === true) {
96
var text_cell = this.element;
97
var output = text_cell.find("div.text_cell_render");
99
text_cell.find('div.text_cell_input').show();
100
this.code_mirror.refresh();
101
this.code_mirror.focus();
102
// We used to need an additional refresh() after the focus, but
103
// it appears that this has been fixed in CM. This bug would show
104
// up on FF when a newly loaded markdown cell was edited.
105
this.rendered = false;
106
if (this.get_text() === this.placeholder) {
114
// Subclasses must define render.
115
TextCell.prototype.render = function () {};
118
TextCell.prototype.get_text = function() {
119
return this.code_mirror.getValue();
123
TextCell.prototype.set_text = function(text) {
124
this.code_mirror.setValue(text);
125
this.code_mirror.refresh();
129
TextCell.prototype.get_rendered = function() {
130
return this.element.find('div.text_cell_render').html();
134
TextCell.prototype.set_rendered = function(text) {
135
this.element.find('div.text_cell_render').html(text);
139
TextCell.prototype.at_top = function () {
148
TextCell.prototype.at_bottom = function () {
157
TextCell.prototype.fromJSON = function (data) {
158
if (data.cell_type === this.cell_type) {
159
if (data.source !== undefined) {
160
this.set_text(data.source);
161
this.set_rendered(data.rendered || '');
162
this.rendered = false;
169
TextCell.prototype.toJSON = function () {
171
data.cell_type = this.cell_type;
172
data.source = this.get_text();
179
var HTMLCell = function (notebook) {
180
this.placeholder = "Type <strong>HTML</strong> and LaTeX: $\\alpha^2$";
181
IPython.TextCell.apply(this, arguments);
182
this.cell_type = 'html';
186
HTMLCell.prototype = new TextCell();
189
HTMLCell.prototype.render = function () {
190
if (this.rendered === false) {
191
var text = this.get_text();
192
if (text === "") { text = this.placeholder; }
193
this.set_rendered(text);
195
this.element.find('div.text_cell_input').hide();
196
this.element.find("div.text_cell_render").show();
197
this.rendered = true;
204
var MarkdownCell = function (notebook) {
205
this.placeholder = "Type *Markdown* and LaTeX: $\\alpha^2$";
206
IPython.TextCell.apply(this, arguments);
207
this.cell_type = 'markdown';
211
MarkdownCell.prototype = new TextCell();
214
MarkdownCell.prototype.render = function () {
215
if (this.rendered === false) {
216
var text = this.get_text();
217
if (text === "") { text = this.placeholder; }
218
var html = IPython.markdown_converter.makeHtml(text);
219
this.set_rendered(html);
221
this.element.find('div.text_cell_input').hide();
222
this.element.find("div.text_cell_render").show();
223
var code_snippets = this.element.find("pre > code");
224
code_snippets.replaceWith(function () {
225
var code = $(this).html();
226
/* Substitute br for newlines and for spaces
227
before highlighting, since prettify doesn't
228
preserve those on all browsers */
229
code = code.replace(/(\r\n|\n|\r)/gm, "<br/>");
230
code = code.replace(/ /gm, ' ');
231
code = prettyPrintOne(code);
233
return '<code class="prettyprint">' + code + '</code>';
235
this.rendered = true;
242
var PlaintextCell = function (notebook) {
243
this.placeholder = "Type plain text and LaTeX: $\\alpha^2$";
244
this.code_mirror_mode = 'rst';
245
IPython.TextCell.apply(this, arguments);
246
this.cell_type = 'plaintext';
250
PlaintextCell.prototype = new TextCell();
253
PlaintextCell.prototype.render = function () {
254
this.rendered = true;
259
PlaintextCell.prototype.select = function () {
260
IPython.Cell.prototype.select.apply(this);
261
this.code_mirror.refresh();
262
this.code_mirror.focus();
266
PlaintextCell.prototype.at_top = function () {
267
var cursor = this.code_mirror.getCursor();
268
if (cursor.line === 0) {
276
PlaintextCell.prototype.at_bottom = function () {
277
var cursor = this.code_mirror.getCursor();
278
if (cursor.line === (this.code_mirror.lineCount()-1)) {
288
var HeadingCell = function (notebook) {
289
this.placeholder = "Type Heading Here";
290
IPython.TextCell.apply(this, arguments);
291
this.cell_type = 'heading';
296
HeadingCell.prototype = new TextCell();
299
HeadingCell.prototype.fromJSON = function (data) {
300
if (data.level != undefined){
301
this.level = data.level;
303
IPython.TextCell.prototype.fromJSON.apply(this, arguments);
307
HeadingCell.prototype.toJSON = function () {
308
var data = IPython.TextCell.prototype.toJSON.apply(this);
309
data.level = this.get_level();
314
HeadingCell.prototype.set_level = function (level) {
317
this.rendered = false;
323
HeadingCell.prototype.get_level = function () {
328
HeadingCell.prototype.set_rendered = function (text) {
329
var r = this.element.find("div.text_cell_render");
331
r.append($('<h'+this.level+'/>').html(text));
335
HeadingCell.prototype.get_rendered = function () {
336
var r = this.element.find("div.text_cell_render");
337
return r.children().first().html();
341
HeadingCell.prototype.render = function () {
342
if (this.rendered === false) {
343
var text = this.get_text();
344
if (text === "") { text = this.placeholder; }
345
this.set_rendered(text);
347
this.element.find('div.text_cell_input').hide();
348
this.element.find("div.text_cell_render").show();
349
this.rendered = true;
353
IPython.TextCell = TextCell;
354
IPython.HTMLCell = HTMLCell;
355
IPython.MarkdownCell = MarkdownCell;
356
IPython.PlaintextCell = PlaintextCell;
357
IPython.HeadingCell = HeadingCell;