Merge pull request #1303 from ellisonbg/updatecm

This updates CodeMirror and refactors a good bit of the notebook code related to it.

* Updated CodeMirror to the latest stable release.
* Fix numerous bugs related to the CM update.
* Refactored the Cell API and the notebook's cell handling methods.
* Generalized split/merge to work with all cell types.
* Generalized "Edit in Ace" to work with all cell types.
* Loading optimizations: pager starts out hidden, faster loads.
* Shading added to Markdown and HTML cells when they are being edited.
* This branch will require solid usability testing on Safari, FF and Chrome before merging.
* Fixed a number of CM related bugs.
Brian E. Granger 14 years ago
commit d8e1b38507

@ -1,15 +1,11 @@
CodeMirror.defineMode("python", function(conf, parserConf) {
var ERRORCLASS = 'error';
function wordRegexp(words) {
return new RegExp("^((" + words.join(")|(") + "))\\b");
}
// IPython-specific changes: add '?' as recognized character.
//var singleOperators = new RegExp("^[\\+\\-\\*/%&|\\^~<>!]");
var singleOperators = new RegExp("^[\\+\\-\\*/%&|\\^~<>!\\?]");
// End IPython changes.
var singleOperators = new RegExp("^[\\+\\-\\*/%&|\\^~<>!\\?]");
var singleDelimiters = new RegExp('^[\\(\\)\\[\\]\\{\\}@,:`=;\\.]');
var doubleOperators = new RegExp("^((==)|(!=)|(<=)|(>=)|(<>)|(<<)|(>>)|(//)|(\\*\\*))");
var doubleDelimiters = new RegExp("^((\\+=)|(\\-=)|(\\*=)|(%=)|(/=)|(&=)|(\\|=)|(\\^=))");
@ -69,15 +65,15 @@ CodeMirror.defineMode("python", function(conf, parserConf) {
if (stream.eatSpace()) {
return null;
}
var ch = stream.peek();
// Handle Comments
if (ch === '#') {
stream.skipToEnd();
return 'comment';
}
// Handle Number Literals
if (stream.match(/^[0-9\.]/, false)) {
var floatLiteral = false;
@ -113,13 +109,13 @@ CodeMirror.defineMode("python", function(conf, parserConf) {
return 'number';
}
}
// Handle Strings
if (stream.match(stringPrefixes)) {
state.tokenize = tokenStringFactory(stream.current());
return state.tokenize(stream, state);
}
// Handle operators and Delimiters
if (stream.match(tripleDelimiters) || stream.match(doubleDelimiters)) {
return null;
@ -132,31 +128,31 @@ CodeMirror.defineMode("python", function(conf, parserConf) {
if (stream.match(singleDelimiters)) {
return null;
}
if (stream.match(types)) {
return 'builtin';
}
if (stream.match(keywords)) {
return 'keyword';
}
if (stream.match(identifiers)) {
return 'variable';
}
// Handle non-detected items
stream.next();
return ERRORCLASS;
}
function tokenStringFactory(delimiter) {
while ('rub'.indexOf(delimiter.charAt(0).toLowerCase()) >= 0) {
delimiter = delimiter.substr(1);
}
var singleline = delimiter.length == 1;
var OUTCLASS = 'string';
return function tokenString(stream, state) {
while (!stream.eol()) {
stream.eatWhile(/[^'"\\]/);
@ -182,11 +178,15 @@ CodeMirror.defineMode("python", function(conf, parserConf) {
return OUTCLASS;
};
}
function indent(stream, state, type) {
type = type || 'py';
var indentUnit = 0;
if (type === 'py') {
if (state.scopes[0].type !== 'py') {
state.scopes[0].offset = stream.indentation();
return;
}
for (var i = 0; i < state.scopes.length; ++i) {
if (state.scopes[i].type === 'py') {
indentUnit = state.scopes[i].offset + conf.indentUnit;
@ -201,8 +201,9 @@ CodeMirror.defineMode("python", function(conf, parserConf) {
type: type
});
}
function dedent(stream, state) {
function dedent(stream, state, type) {
type = type || 'py';
if (state.scopes.length == 1) return;
if (state.scopes[0].type === 'py') {
var _indent = stream.indentation();
@ -221,8 +222,16 @@ CodeMirror.defineMode("python", function(conf, parserConf) {
}
return false
} else {
state.scopes.shift();
return false;
if (type === 'py') {
state.scopes[0].offset = stream.indentation();
return false;
} else {
if (state.scopes[0].type != type) {
return true;
}
state.scopes.shift();
return false;
}
}
}
@ -241,7 +250,7 @@ CodeMirror.defineMode("python", function(conf, parserConf) {
return ERRORCLASS;
}
}
// Handle decorators
if (current === '@') {
style = state.tokenize(stream, state);
@ -254,7 +263,7 @@ CodeMirror.defineMode("python", function(conf, parserConf) {
return ERRORCLASS;
}
}
// Handle scope changes.
if (current === 'pass' || current === 'return') {
state.dedent += 1;
@ -274,7 +283,7 @@ CodeMirror.defineMode("python", function(conf, parserConf) {
}
delimiter_index = '])}'.indexOf(current);
if (delimiter_index !== -1) {
if (dedent(stream, state)) {
if (dedent(stream, state, current)) {
return ERRORCLASS;
}
}
@ -282,7 +291,7 @@ CodeMirror.defineMode("python", function(conf, parserConf) {
if (state.scopes.length > 1) state.scopes.shift();
state.dedent -= 1;
}
return style;
}
@ -296,27 +305,27 @@ CodeMirror.defineMode("python", function(conf, parserConf) {
dedent: 0
};
},
token: function(stream, state) {
var style = tokenLexer(stream, state);
state.lastToken = {style:style, content: stream.current()};
if (stream.eol() && stream.lambda) {
state.lambda = false;
}
return style;
},
indent: function(state, textAfter) {
if (state.tokenize != tokenBase) {
return 0;
}
return state.scopes[0].offset;
}
};
return external;
});

@ -137,6 +137,7 @@ div#pager_splitter {
div#pager {
padding: 15px;
overflow: auto;
display: none;
}
div.cell {
@ -238,10 +239,14 @@ div.output_jpeg {
div.text_cell {
background-color: white;
padding: 5px 5px 5px 5px;
}
div.text_cell_input {
color: black;
border: 1px solid #ddd;
border-radius: 3px;
background: #f7f7f7;
}
div.text_cell_render {

@ -13,7 +13,9 @@ var IPython = (function (IPython) {
var utils = IPython.utils;
var Cell = function (notebook) {
this.placeholder = this.placeholder || '';
this.notebook = notebook;
this.read_only = false;
if (notebook){
@ -23,7 +25,6 @@ var IPython = (function (IPython) {
this.element = null;
this.create_element();
if (this.element !== null) {
this.set_autoindent(true);
this.element.data("cell", this);
this.bind_events();
}
@ -31,16 +32,8 @@ var IPython = (function (IPython) {
};
Cell.prototype.select = function () {
this.element.addClass('ui-widget-content ui-corner-all');
this.selected = true;
};
Cell.prototype.unselect = function () {
this.element.removeClass('ui-widget-content ui-corner-all');
this.selected = false;
};
// Subclasses must implement create_element.
Cell.prototype.create_element = function () {};
Cell.prototype.bind_events = function () {
@ -58,6 +51,80 @@ var IPython = (function (IPython) {
});
};
// typeset with MathJax if MathJax is available
Cell.prototype.typeset = function () {
if (window.MathJax){
MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
}
};
Cell.prototype.select = function () {
this.element.addClass('ui-widget-content ui-corner-all');
this.selected = true;
};
Cell.prototype.unselect = function () {
this.element.removeClass('ui-widget-content ui-corner-all');
this.selected = false;
};
Cell.prototype.get_text = function () {
};
Cell.prototype.set_text = function (text) {
};
Cell.prototype.refresh = function () {
this.code_mirror.refresh();
};
Cell.prototype.edit = function () {
};
Cell.prototype.render = function () {
};
Cell.prototype.toJSON = function () {
};
Cell.prototype.fromJSON = function (data) {
};
Cell.prototype.is_splittable = function () {
return true;
};
Cell.prototype.get_pre_cursor = function () {
var cursor = this.code_mirror.getCursor();
var text = this.code_mirror.getRange({line:0,ch:0}, cursor);
text = text.replace(/^\n+/, '').replace(/\n+$/, '');
return text;
}
Cell.prototype.get_post_cursor = function () {
var cursor = this.code_mirror.getCursor();
var last_line_num = this.code_mirror.lineCount()-1;
var last_line_len = this.code_mirror.getLine(last_line_num).length;
var end = {line:last_line_num, ch:last_line_len}
var text = this.code_mirror.getRange(cursor, end);
text = text.replace(/^\n+/, '').replace(/\n+$/, '');
return text;
};
Cell.prototype.grow = function(element) {
// Grow the cell by hand. This is used upon reloading from JSON, when the
// autogrow handler is not called.
@ -75,26 +142,6 @@ var IPython = (function (IPython) {
};
Cell.prototype.set_autoindent = function (state) {
if (state) {
this.code_mirror.setOption('tabMode', 'indent');
this.code_mirror.setOption('enterMode', 'indent');
} else {
this.code_mirror.setOption('tabMode', 'shift');
this.code_mirror.setOption('enterMode', 'flat');
}
};
// Subclasses must implement create_element.
Cell.prototype.create_element = function () {};
// typeset with MathJax if MathJax is available
Cell.prototype.typeset = function () {
if (window.MathJax){
MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
}
};
IPython.Cell = Cell;
return IPython;

@ -86,13 +86,31 @@ var IPython = (function (IPython) {
if (event.keyCode === 13 && (event.shiftKey || event.ctrlKey)) {
// Always ignore shift-enter in CodeMirror as we handle it.
return true;
}else if (event.which === 40 && event.type === 'keypress' && tooltip_wait_time >= 0) {
} else if (event.which === 40 && event.type === 'keypress' && tooltip_wait_time >= 0) {
// triger aon keypress (!) otherwise inconsistent event.which depending on plateform
// browser and keyboard layout !
// Pressing '(' , request tooltip, don't forget to reappend it
var cursor = editor.getCursor();
var pre_cursor = editor.getRange({line:cursor.line,ch:0},cursor).trim()+'(';
that.request_tooltip_after_time(pre_cursor,tooltip_wait_time);
} else if (event.which === 38) {
// If we are not at the top, let CM handle the up arrow and
// prevent the global keydown handler from handling it.
if (!that.at_top()) {
event.stop();
return false;
} else {
return true;
};
} else if (event.which === 40) {
// If we are not at the bottom, let CM handle the down arrow and
// prevent the global keydown handler from handling it.
if (!that.at_bottom()) {
event.stop();
return false;
} else {
return true;
};
} else if (event.keyCode === 9 && event.type == 'keydown') {
// Tab completion.
var cur = editor.getCursor();
@ -499,6 +517,7 @@ var IPython = (function (IPython) {
select.focus();
};
CodeCell.prototype.toggle_line_numbers = function () {
if (this.code_mirror.getOption('lineNumbers') == false) {
this.code_mirror.setOption('lineNumbers', true);
@ -508,15 +527,14 @@ var IPython = (function (IPython) {
this.code_mirror.refresh();
};
CodeCell.prototype.select = function () {
IPython.Cell.prototype.select.apply(this);
// Todo: this dance is needed because as of CodeMirror 2.12, focus is
// not causing the cursor to blink if the editor is empty initially.
// While this seems to fix the issue, this should be fixed
// in CodeMirror proper.
var s = this.code_mirror.getValue();
// In some cases (inserting a new cell) we need a refresh before and
// after the focus. Not sure why this is the case.
this.code_mirror.refresh();
this.code_mirror.focus();
if (s === '') this.code_mirror.setValue('');
this.code_mirror.refresh();
};
@ -754,12 +772,12 @@ var IPython = (function (IPython) {
};
CodeCell.prototype.get_code = function () {
CodeCell.prototype.get_text = function () {
return this.code_mirror.getValue();
};
CodeCell.prototype.set_code = function (code) {
CodeCell.prototype.set_text = function (code) {
return this.code_mirror.setValue(code);
};
@ -787,7 +805,7 @@ var IPython = (function (IPython) {
CodeCell.prototype.fromJSON = function (data) {
if (data.cell_type === 'code') {
if (data.input !== undefined) {
this.set_code(data.input);
this.set_text(data.input);
}
if (data.prompt_number !== undefined) {
this.set_input_prompt(data.prompt_number);
@ -809,7 +827,7 @@ var IPython = (function (IPython) {
CodeCell.prototype.toJSON = function () {
var data = {};
data.input = this.get_code();
data.input = this.get_text();
data.cell_type = 'code';
if (this.input_prompt_number !== ' ') {
data.prompt_number = this.input_prompt_number;

@ -26,7 +26,7 @@ var IPython = (function (IPython) {
select : function (event, ui) {
// The selected cell loses focus when the menu is entered, so we
// re-select it upon selection.
var i = IPython.notebook.selected_index();
var i = IPython.notebook.get_selected_index();
IPython.notebook.select(i);
}
});
@ -100,10 +100,10 @@ var IPython = (function (IPython) {
});
// Insert
this.element.find('#insert_cell_above').click(function () {
IPython.notebook.insert_code_cell_above();
IPython.notebook.insert_cell_above('code');
});
this.element.find('#insert_cell_below').click(function () {
IPython.notebook.insert_code_cell_below();
IPython.notebook.insert_cell_below('code');
});
// Cell
this.element.find('#full_edit_cell').click(function () {

@ -32,7 +32,6 @@ var IPython = (function (IPython) {
this.set_tooltipontab(true);
this.set_smartcompleter(true);
this.set_timebeforetooltip(1200);
this.set_autoindent(true);
};
@ -47,11 +46,11 @@ var IPython = (function (IPython) {
// ii) to prevent the div from scrolling up when the last cell is being
// edited, but is too low on the page, which browsers will do automatically.
var that = this;
var end_space = $('<div class="end_space"></div>').height("30%");
var end_space = $('<div/>').addClass('end_space').height("30%");
end_space.dblclick(function (e) {
if (that.read_only) return;
var ncells = that.ncells();
that.insert_code_cell_below(ncells-1);
that.insert_cell_below('code',ncells-1);
});
this.element.append(end_space);
$('div#notebook').addClass('border-box-sizing');
@ -69,13 +68,13 @@ var IPython = (function (IPython) {
event.preventDefault();
}
if (event.which === 38 && !event.shiftKey) {
var cell = that.selected_cell();
var cell = that.get_selected_cell();
if (cell.at_top()) {
event.preventDefault();
that.select_prev();
};
} else if (event.which === 40 && !event.shiftKey) {
var cell = that.selected_cell();
var cell = that.get_selected_cell();
if (cell.at_bottom()) {
event.preventDefault();
that.select_next();
@ -111,12 +110,12 @@ var IPython = (function (IPython) {
return false;
} else if (event.which === 65 && that.control_key_active) {
// Insert code cell above selected = a
that.insert_code_cell_above();
that.insert_cell_above('code');
that.control_key_active = false;
return false;
} else if (event.which === 66 && that.control_key_active) {
// Insert code cell below selected = b
that.insert_code_cell_below();
that.insert_cell_below('code');
that.control_key_active = false;
return false;
} else if (event.which === 89 && that.control_key_active) {
@ -234,29 +233,67 @@ var IPython = (function (IPython) {
// Cell indexing, retrieval, etc.
Notebook.prototype.cell_elements = function () {
Notebook.prototype.get_cell_elements = function () {
return this.element.children("div.cell");
};
Notebook.prototype.get_cell_element = function (index) {
var result = null;
var e = this.get_cell_elements().eq(index);
if (e.length !== 0) {
result = e;
}
return result;
};
Notebook.prototype.ncells = function (cell) {
return this.cell_elements().length;
return this.get_cell_elements().length;
};
// TODO: we are often calling cells as cells()[i], which we should optimize
// to cells(i) or a new method.
Notebook.prototype.cells = function () {
return this.cell_elements().toArray().map(function (e) {
Notebook.prototype.get_cells = function () {
return this.get_cell_elements().toArray().map(function (e) {
return $(e).data("cell");
});
};
Notebook.prototype.get_cell = function (index) {
var result = null;
var ce = this.get_cell_element(index);
if (ce !== null) {
result = ce.data('cell');
}
return result;
}
Notebook.prototype.get_next_cell = function (cell) {
var result = null;
var index = this.find_cell_index(cell);
if (index !== null && index < this.ncells()) {
result = this.get_cell(index+1);
}
return result;
}
Notebook.prototype.get_prev_cell = function (cell) {
var result = null;
var index = this.find_cell_index(cell);
if (index !== null && index > 1) {
result = this.get_cell(index-1);
}
return result;
}
Notebook.prototype.find_cell_index = function (cell) {
var result = null;
this.cell_elements().filter(function (index) {
this.get_cell_elements().filter(function (index) {
if ($(this).data("cell") === cell) {
result = index;
};
@ -267,8 +304,8 @@ var IPython = (function (IPython) {
Notebook.prototype.index_or_selected = function (index) {
var i;
if (index === undefined) {
i = this.selected_index();
if (index === undefined || index === null) {
i = this.get_selected_index();
if (i === null) {
i = 0;
}
@ -279,38 +316,23 @@ var IPython = (function (IPython) {
};
Notebook.prototype.select = function (index) {
if (index !== undefined && index >= 0 && index < this.ncells()) {
if (this.selected_index() !== null) {
this.selected_cell().unselect();
};
this.cells()[index].select();
};
return this;
};
Notebook.prototype.select_next = function () {
var index = this.selected_index();
if (index !== null && index >= 0 && (index+1) < this.ncells()) {
this.select(index+1);
};
return this;
Notebook.prototype.get_selected_cell = function () {
var index = this.get_selected_index();
return this.get_cell(index);
};
Notebook.prototype.select_prev = function () {
var index = this.selected_index();
if (index !== null && index >= 0 && (index-1) < this.ncells()) {
this.select(index-1);
Notebook.prototype.is_valid_cell_index = function (index) {
if (index !== null && index >= 0 && index < this.ncells()) {
return true;
} else {
return false;
};
return this;
};
}
Notebook.prototype.selected_index = function () {
Notebook.prototype.get_selected_index = function () {
var result = null;
this.cell_elements().filter(function (index) {
this.get_cell_elements().filter(function (index) {
if ($(this).data("cell").selected === true) {
result = index;
};
@ -322,7 +344,7 @@ var IPython = (function (IPython) {
Notebook.prototype.cell_for_msg = function (msg_id) {
var cell_id = this.msg_cell_map[msg_id];
var result = null;
this.cell_elements().filter(function (index) {
this.get_cell_elements().filter(function (index) {
cell = $(this).data("cell");
if (cell.cell_id === cell_id) {
result = cell;
@ -332,68 +354,45 @@ var IPython = (function (IPython) {
};
Notebook.prototype.selected_cell = function () {
return this.cell_elements().eq(this.selected_index()).data("cell");
};
// Cell selection.
// Cell insertion, deletion and moving.
Notebook.prototype.delete_cell = function (index) {
var i = this.index_or_selected(index);
if (i !== null && i >= 0 && i < this.ncells()) {
this.cell_elements().eq(i).remove();
if (i === (this.ncells())) {
this.select(i-1);
} else {
this.select(i);
Notebook.prototype.select = function (index) {
if (index !== undefined && index >= 0 && index < this.ncells()) {
sindex = this.get_selected_index()
if (sindex !== null && index !== sindex) {
this.get_cell(sindex).unselect();
};
this.get_cell(index).select();
};
this.dirty = true;
return this;
};
Notebook.prototype.append_cell = function (cell) {
this.element.find('div.end_space').before(cell.element);
this.dirty = true;
return this;
};
Notebook.prototype.insert_cell_below = function (cell, index) {
var ncells = this.ncells();
if (ncells === 0) {
this.append_cell(cell);
return this;
};
if (index >= 0 && index < ncells) {
this.cell_elements().eq(index).after(cell.element);
Notebook.prototype.select_next = function () {
var index = this.get_selected_index();
if (index !== null && index >= 0 && (index+1) < this.ncells()) {
this.select(index+1);
};
this.dirty = true;
return this;
};
Notebook.prototype.insert_cell_above = function (cell, index) {
var ncells = this.ncells();
if (ncells === 0) {
this.append_cell(cell);
return this;
};
if (index >= 0 && index < ncells) {
this.cell_elements().eq(index).before(cell.element);
Notebook.prototype.select_prev = function () {
var index = this.get_selected_index();
if (index !== null && index >= 0 && (index-1) < this.ncells()) {
this.select(index-1);
};
this.dirty = true;
return this;
};
// Cell movement
Notebook.prototype.move_cell_up = function (index) {
var i = index || this.selected_index();
var i = this.index_or_selected();
if (i !== null && i < this.ncells() && i > 0) {
var pivot = this.cell_elements().eq(i-1);
var tomove = this.cell_elements().eq(i);
var pivot = this.get_cell_element(i-1);
var tomove = this.get_cell_element(i);
if (pivot !== null && tomove !== null) {
tomove.detach();
pivot.before(tomove);
@ -406,10 +405,10 @@ var IPython = (function (IPython) {
Notebook.prototype.move_cell_down = function (index) {
var i = index || this.selected_index();
var i = this.index_or_selected();
if (i !== null && i < (this.ncells()-1) && i >= 0) {
var pivot = this.cell_elements().eq(i+1);
var tomove = this.cell_elements().eq(i);
var pivot = this.get_cell_element(i+1);
var tomove = this.get_cell_element(i);
if (pivot !== null && tomove !== null) {
tomove.detach();
pivot.after(tomove);
@ -422,14 +421,16 @@ var IPython = (function (IPython) {
Notebook.prototype.sort_cells = function () {
// This is not working right now. Calling this will actually crash
// the browser. I think there is an infinite loop in here...
var ncells = this.ncells();
var sindex = this.selected_index();
var sindex = this.get_selected_index();
var swapped;
do {
swapped = false;
for (var i=1; i<ncells; i++) {
current = this.cell_elements().eq(i).data("cell");
previous = this.cell_elements().eq(i-1).data("cell");
current = this.get_cell(i);
previous = this.get_cell(i-1);
if (previous.input_prompt_number > current.input_prompt_number) {
this.move_cell_up(i);
swapped = true;
@ -440,147 +441,150 @@ var IPython = (function (IPython) {
return this;
};
// Insertion, deletion.
Notebook.prototype.insert_code_cell_above = function (index) {
// TODO: Bounds check for i
var i = this.index_or_selected(index);
var cell = new IPython.CodeCell(this);
cell.set_input_prompt();
this.insert_cell_above(cell, i);
this.select(this.find_cell_index(cell));
return cell;
};
Notebook.prototype.insert_code_cell_below = function (index) {
// TODO: Bounds check for i
var i = this.index_or_selected(index);
var cell = new IPython.CodeCell(this);
cell.set_input_prompt();
this.insert_cell_below(cell, i);
this.select(this.find_cell_index(cell));
return cell;
};
Notebook.prototype.insert_html_cell_above = function (index) {
// TODO: Bounds check for i
var i = this.index_or_selected(index);
var cell = new IPython.HTMLCell(this);
cell.config_mathjax();
this.insert_cell_above(cell, i);
this.select(this.find_cell_index(cell));
return cell;
};
Notebook.prototype.insert_html_cell_below = function (index) {
// TODO: Bounds check for i
Notebook.prototype.delete_cell = function (index) {
var i = this.index_or_selected(index);
var cell = new IPython.HTMLCell(this);
cell.config_mathjax();
this.insert_cell_below(cell, i);
this.select(this.find_cell_index(cell));
return cell;
if (this.is_valid_cell_index(i)) {
var ce = this.get_cell_element(i);
ce.remove();
if (i === (this.ncells())) {
this.select(i-1);
} else {
this.select(i);
};
this.dirty = true;
};
return this;
};
Notebook.prototype.insert_markdown_cell_above = function (index) {
// TODO: Bounds check for i
var i = this.index_or_selected(index);
var cell = new IPython.MarkdownCell(this);
cell.config_mathjax();
this.insert_cell_above(cell, i);
this.select(this.find_cell_index(cell));
return cell;
Notebook.prototype.insert_cell_below = function (type, index) {
// type = ('code','html','markdown')
// index = cell index or undefined to insert below selected
index = this.index_or_selected(index);
if (this.ncells() === 0 || this.is_valid_cell_index(index)) {
var cell = null;
if (type === 'code') {
var cell = new IPython.CodeCell(this);
cell.set_input_prompt();
} else if (type === 'markdown') {
var cell = new IPython.MarkdownCell(this);
} else if (type === 'html') {
var cell = new IPython.HTMLCell(this);
};
if (cell !== null) {
if (this.ncells() === 0) {
this.element.find('div.end_space').before(cell.element);
} else if (this.is_valid_cell_index(index)) {
this.get_cell_element(index).after(cell.element);
};
cell.render();
this.select(this.find_cell_index(cell));
this.dirty = true;
return cell;
};
};
};
Notebook.prototype.insert_markdown_cell_below = function (index) {
// TODO: Bounds check for i
var i = this.index_or_selected(index);
var cell = new IPython.MarkdownCell(this);
cell.config_mathjax();
this.insert_cell_below(cell, i);
this.select(this.find_cell_index(cell));
return cell;
Notebook.prototype.insert_cell_above = function (type, index) {
// type = ('code','html','markdown')
// index = cell index or undefined to insert above selected
index = this.index_or_selected(index);
if (this.ncells() === 0 || this.is_valid_cell_index(index)) {
var cell = null;
if (type === 'code') {
var cell = new IPython.CodeCell(this);
cell.set_input_prompt();
} else if (type === 'markdown') {
var cell = new IPython.MarkdownCell(this);
} else if (type === 'html') {
var cell = new IPython.HTMLCell(this);
};
if (cell !== null) {
if (this.ncells() === 0) {
this.element.find('div.end_space').before(cell.element);
} else if (this.is_valid_cell_index(index)) {
this.get_cell_element(index).before(cell.element);
};
cell.render();
this.select(this.find_cell_index(cell));
this.dirty = true;
return cell;
};
};
};
Notebook.prototype.to_code = function (index) {
// TODO: Bounds check for i
var i = this.index_or_selected(index);
var source_element = this.cell_elements().eq(i);
var source_cell = source_element.data("cell");
if (source_cell instanceof IPython.HTMLCell ||
source_cell instanceof IPython.MarkdownCell) {
this.insert_code_cell_below(i);
var target_cell = this.cells()[i+1];
target_cell.set_code(source_cell.get_source());
source_element.remove();
target_cell.select();
if (this.is_valid_cell_index(i)) {
var source_element = this.get_cell_element(i);
var source_cell = source_element.data("cell");
if (!(source_cell instanceof IPython.CodeCell)) {
target_cell = this.insert_cell_below('code',i);
var text = source_cell.get_text();
if (text === source_cell.placeholder) {
text = '';
}
target_cell.set_text(text);
source_element.remove();
};
this.dirty = true;
};
this.dirty = true;
};
Notebook.prototype.to_markdown = function (index) {
// TODO: Bounds check for i
var i = this.index_or_selected(index);
var source_element = this.cell_elements().eq(i);
var source_cell = source_element.data("cell");
var target_cell = null;
if (source_cell instanceof IPython.CodeCell) {
this.insert_markdown_cell_below(i);
target_cell = this.cells()[i+1];
var text = source_cell.get_code();
} else if (source_cell instanceof IPython.HTMLCell) {
this.insert_markdown_cell_below(i);
target_cell = this.cells()[i+1];
var text = source_cell.get_source();
if (text === source_cell.placeholder) {
text = target_cell.placeholder;
}
}
if (target_cell !== null) {
if (text === "") {text = target_cell.placeholder;};
target_cell.set_source(text);
source_element.remove();
target_cell.edit();
}
this.dirty = true;
if (this.is_valid_cell_index(i)) {
var source_element = this.get_cell_element(i);
var source_cell = source_element.data("cell");
var target_cell = null;
if (!(source_cell instanceof IPython.MarkdownCell)) {
target_cell = this.insert_cell_below('markdown',i);
var text = source_cell.get_text();
if (text === source_cell.placeholder) {
text = '';
};
if (target_cell !== null) {
// The edit must come before the set_text.
target_cell.edit();
target_cell.set_text(text);
source_element.remove();
}
this.dirty = true;
};
};
};
Notebook.prototype.to_html = function (index) {
// TODO: Bounds check for i
var i = this.index_or_selected(index);
var source_element = this.cell_elements().eq(i);
var source_cell = source_element.data("cell");
var target_cell = null;
if (source_cell instanceof IPython.CodeCell) {
this.insert_html_cell_below(i);
target_cell = this.cells()[i+1];
var text = source_cell.get_code();
} else if (source_cell instanceof IPython.MarkdownCell) {
this.insert_html_cell_below(i);
target_cell = this.cells()[i+1];
var text = source_cell.get_source();
if (text === source_cell.placeholder) {
text = target_cell.placeholder;
}
}
if (target_cell !== null) {
if (text === "") {text = target_cell.placeholder;};
target_cell.set_source(text);
source_element.remove();
target_cell.edit();
}
this.dirty = true;
if (this.is_valid_cell_index(i)) {
var source_element = this.get_cell_element(i);
var source_cell = source_element.data("cell");
var target_cell = null;
if (!(source_cell instanceof IPython.HTMLCell)) {
target_cell = this.insert_cell_below('html',i);
var text = source_cell.get_text();
if (text === source_cell.placeholder) {
text = '';
};
if (target_cell !== null) {
// The edit must come before the set_text.
target_cell.edit();
target_cell.set_text(text);
source_element.remove();
}
this.dirty = true;
};
};
};
// Copy/Paste/Merge/Split
// Cut/Copy/Paste
Notebook.prototype.enable_paste = function () {
var that = this;
@ -612,7 +616,7 @@ var IPython = (function (IPython) {
}
Notebook.prototype.copy_cell = function () {
var cell = this.selected_cell();
var cell = this.get_selected_cell();
this.clipboard = cell.toJSON();
this.enable_paste();
};
@ -621,18 +625,11 @@ var IPython = (function (IPython) {
Notebook.prototype.paste_cell = function () {
if (this.clipboard !== null && this.paste_enabled) {
var cell_data = this.clipboard;
if (cell_data.cell_type == 'code') {
new_cell = this.insert_code_cell_above();
new_cell.fromJSON(cell_data);
} else if (cell_data.cell_type === 'html') {
new_cell = this.insert_html_cell_above();
new_cell.fromJSON(cell_data);
} else if (cell_data.cell_type === 'markdown') {
new_cell = this.insert_markdown_cell_above();
new_cell.fromJSON(cell_data);
};
this.select_next();
this.delete_cell();
var new_cell = this.insert_cell_above(cell_data.cell_type);
new_cell.fromJSON(cell_data);
old_cell = this.get_next_cell(new_cell);
this.delete_cell(this.find_cell_index(old_cell));
this.select(this.find_cell_index(new_cell));
};
};
@ -640,16 +637,8 @@ var IPython = (function (IPython) {
Notebook.prototype.paste_cell_above = function () {
if (this.clipboard !== null && this.paste_enabled) {
var cell_data = this.clipboard;
if (cell_data.cell_type == 'code') {
new_cell = this.insert_code_cell_above();
new_cell.fromJSON(cell_data);
} else if (cell_data.cell_type === 'html') {
new_cell = this.insert_html_cell_above();
new_cell.fromJSON(cell_data);
} else if (cell_data.cell_type === 'markdown') {
new_cell = this.insert_markdown_cell_above();
new_cell.fromJSON(cell_data);
};
var new_cell = this.insert_cell_above(cell_data.cell_type);
new_cell.fromJSON(cell_data);
};
};
@ -657,91 +646,102 @@ var IPython = (function (IPython) {
Notebook.prototype.paste_cell_below = function () {
if (this.clipboard !== null && this.paste_enabled) {
var cell_data = this.clipboard;
if (cell_data.cell_type == 'code') {
new_cell = this.insert_code_cell_below();
new_cell.fromJSON(cell_data);
} else if (cell_data.cell_type === 'html') {
new_cell = this.insert_html_cell_below();
new_cell.fromJSON(cell_data);
} else if (cell_data.cell_type === 'markdown') {
new_cell = this.insert_markdown_cell_below();
new_cell.fromJSON(cell_data);
};
var new_cell = this.insert_cell_below(cell_data.cell_type);
new_cell.fromJSON(cell_data);
};
};
// Split/merge
Notebook.prototype.split_cell = function () {
// Todo: implement spliting for other cell types.
var cell = this.selected_cell();
if (cell instanceof IPython.CodeCell) {
var cursor = cell.code_mirror.getCursor();
var last_line_num = cell.code_mirror.lineCount()-1;
var last_line_len = cell.code_mirror.getLine(last_line_num).length;
var end = {line:last_line_num, ch:last_line_len}
var texta = cell.code_mirror.getRange({line:0,ch:0}, cursor);
var textb = cell.code_mirror.getRange(cursor, end);
texta = texta.replace(/^\n+/, '').replace(/\n+$/, '');
textb = textb.replace(/^\n+/, '').replace(/\n+$/, '');
cell.set_code(texta);
var new_cell = this.insert_code_cell_below();
new_cell.set_code(textb);
var cell = this.get_selected_cell();
if (cell.is_splittable()) {
texta = cell.get_pre_cursor();
textb = cell.get_post_cursor();
if (cell instanceof IPython.CodeCell) {
cell.set_text(texta);
var new_cell = this.insert_cell_below('code');
new_cell.set_text(textb);
} else if (cell instanceof IPython.MarkdownCell) {
cell.set_text(texta);
cell.render();
var new_cell = this.insert_cell_below('markdown');
new_cell.edit(); // editor must be visible to call set_text
new_cell.set_text(textb);
new_cell.render();
} else if (cell instanceof IPython.HTMLCell) {
cell.set_text(texta);
cell.render();
var new_cell = this.insert_cell_below('html');
new_cell.edit(); // editor must be visible to call set_text
new_cell.set_text(textb);
new_cell.render();
};
};
};
Notebook.prototype.merge_cell_above = function () {
// Todo: implement merging for other cell types.
var cell = this.selected_cell();
var index = this.selected_index();
var index = this.get_selected_index();
var cell = this.get_cell(index);
if (index > 0) {
upper_cell = this.cells()[index-1];
lower_cell = this.cells()[index];
if (upper_cell instanceof IPython.CodeCell && lower_cell instanceof IPython.CodeCell) {
upper_text = upper_cell.get_code();
lower_text = lower_cell.get_code();
lower_cell.set_code(upper_text+'\n'+lower_text);
this.delete_cell(index-1);
upper_cell = this.get_cell(index-1);
upper_text = upper_cell.get_text();
text = cell.get_text();
if (cell instanceof IPython.CodeCell) {
cell.set_text(upper_text+'\n'+text);
} else if (cell instanceof IPython.MarkdownCell || cell instanceof IPython.HTMLCell) {
cell.edit();
cell.set_text(upper_text+'\n'+text);
cell.render();
};
this.delete_cell(index-1);
this.select(this.find_cell_index(cell));
};
};
Notebook.prototype.merge_cell_below = function () {
// Todo: implement merging for other cell types.
var cell = this.selected_cell();
var index = this.selected_index();
var index = this.get_selected_index();
var cell = this.get_cell(index);
if (index < this.ncells()-1) {
upper_cell = this.cells()[index];
lower_cell = this.cells()[index+1];
if (upper_cell instanceof IPython.CodeCell && lower_cell instanceof IPython.CodeCell) {
upper_text = upper_cell.get_code();
lower_text = lower_cell.get_code();
upper_cell.set_code(upper_text+'\n'+lower_text);
this.delete_cell(index+1);
lower_cell = this.get_cell(index+1);
lower_text = lower_cell.get_text();
text = cell.get_text();
if (cell instanceof IPython.CodeCell) {
cell.set_text(text+'\n'+lower_text);
} else if (cell instanceof IPython.MarkdownCell || cell instanceof IPython.HTMLCell) {
cell.edit();
cell.set_text(text+'\n'+lower_text);
cell.render();
};
this.delete_cell(index+1);
this.select(this.find_cell_index(cell));
};
};
// Cell collapsing and output clearing
Notebook.prototype.collapse = function (index) {
var i = this.index_or_selected(index);
this.cells()[i].collapse();
this.get_cell(i).collapse();
this.dirty = true;
};
Notebook.prototype.expand = function (index) {
var i = this.index_or_selected(index);
this.cells()[i].expand();
this.get_cell(i).expand();
this.dirty = true;
};
Notebook.prototype.toggle_output = function (index) {
var i = this.index_or_selected(index);
this.cells()[i].toggle_output();
this.get_cell(i).toggle_output();
this.dirty = true;
};
@ -750,26 +750,20 @@ var IPython = (function (IPython) {
this.time_before_tooltip = time;
};
Notebook.prototype.set_tooltipontab = function (state) {
this.tooltip_on_tab = state;
};
Notebook.prototype.set_smartcompleter = function (state) {
this.smart_completer = state;
};
Notebook.prototype.set_autoindent = function (state) {
var cells = this.cells();
len = cells.length;
for (var i=0; i<len; i++) {
cells[i].set_autoindent(state);
};
};
Notebook.prototype.clear_all_output = function () {
var ncells = this.ncells();
var cells = this.cells();
var cells = this.get_cells();
for (var i=0; i<ncells; i++) {
if (cells[i] instanceof IPython.CodeCell) {
cells[i].clear_output(true,true,true);
@ -778,10 +772,11 @@ var IPython = (function (IPython) {
this.dirty = true;
};
// Other cell functions: line numbers, ...
Notebook.prototype.cell_toggle_line_numbers = function() {
this.selected_cell().toggle_line_numbers();
this.get_selected_cell().toggle_line_numbers();
};
// Kernel related things
@ -868,8 +863,8 @@ var IPython = (function (IPython) {
}
} else if (payload[i].source === 'IPython.zmq.zmqshell.ZMQInteractiveShell.set_next_input') {
var index = this.find_cell_index(cell);
var new_cell = this.insert_code_cell_below(index);
new_cell.set_code(payload[i].text);
var new_cell = this.insert_cell_below('code',index);
new_cell.set_text(payload[i].text);
this.dirty = true;
}
};
@ -988,14 +983,14 @@ var IPython = (function (IPython) {
default_options = {terminal: false, add_new: true};
$.extend(default_options, options);
var that = this;
var cell = that.selected_cell();
var cell = that.get_selected_cell();
var cell_index = that.find_cell_index(cell);
if (cell instanceof IPython.CodeCell) {
cell.clear_output(true, true, true);
cell.set_input_prompt('*');
cell.element.addClass("running");
var code = cell.get_code();
var msg_id = that.kernel.execute(cell.get_code());
var code = cell.get_text();
var msg_id = that.kernel.execute(cell.get_text());
that.msg_cell_map[msg_id] = cell.cell_id;
} else if (cell instanceof IPython.HTMLCell) {
cell.render();
@ -1004,7 +999,7 @@ var IPython = (function (IPython) {
cell.select_all();
} else {
if ((cell_index === (that.ncells()-1)) && default_options.add_new) {
that.insert_code_cell_below();
that.insert_cell_below('code');
// If we are adding a new cell at the end, scroll down to show it.
that.scroll_to_bottom();
} else {
@ -1019,7 +1014,7 @@ var IPython = (function (IPython) {
var ncells = this.ncells();
for (var i=0; i<ncells; i++) {
this.select(i);
this.execute_selected_cell({add_new:false});
this.execute_get_selected_cell({add_new:false});
};
this.scroll_to_bottom();
};
@ -1075,23 +1070,15 @@ var IPython = (function (IPython) {
var new_cell = null;
for (i=0; i<ncells; i++) {
cell_data = new_cells[i];
if (cell_data.cell_type == 'code') {
new_cell = this.insert_code_cell_below();
new_cell.fromJSON(cell_data);
} else if (cell_data.cell_type === 'html') {
new_cell = this.insert_html_cell_below();
new_cell.fromJSON(cell_data);
} else if (cell_data.cell_type === 'markdown') {
new_cell = this.insert_markdown_cell_below();
new_cell.fromJSON(cell_data);
};
new_cell = this.insert_cell_below(cell_data.cell_type);
new_cell.fromJSON(cell_data);
};
};
};
Notebook.prototype.toJSON = function () {
var cells = this.cells();
var cells = this.get_cells();
var ncells = cells.length;
cell_array = new Array(ncells);
for (var i=0; i<ncells; i++) {
@ -1106,27 +1093,25 @@ var IPython = (function (IPython) {
};
Notebook.prototype.save_notebook = function () {
if (IPython.save_widget.test_notebook_name()) {
var notebook_id = IPython.save_widget.get_notebook_id();
var nbname = IPython.save_widget.get_notebook_name();
// We may want to move the name/id/nbformat logic inside toJSON?
var data = this.toJSON();
data.metadata.name = nbname;
data.nbformat = 2;
// We do the call with settings so we can set cache to false.
var settings = {
processData : false,
cache : false,
type : "PUT",
data : JSON.stringify(data),
headers : {'Content-Type': 'application/json'},
success : $.proxy(this.notebook_saved,this),
error : $.proxy(this.notebook_save_failed,this)
};
IPython.save_widget.status_saving();
var url = $('body').data('baseProjectUrl') + 'notebooks/' + notebook_id;
$.ajax(url, settings);
var notebook_id = IPython.save_widget.get_notebook_id();
var nbname = IPython.save_widget.get_notebook_name();
// We may want to move the name/id/nbformat logic inside toJSON?
var data = this.toJSON();
data.metadata.name = nbname;
data.nbformat = 2;
// We do the call with settings so we can set cache to false.
var settings = {
processData : false,
cache : false,
type : "PUT",
data : JSON.stringify(data),
headers : {'Content-Type': 'application/json'},
success : $.proxy(this.notebook_saved,this),
error : $.proxy(this.notebook_save_failed,this)
};
IPython.save_widget.status_saving();
var url = $('body').data('baseProjectUrl') + 'notebooks/' + notebook_id;
$.ajax(url, settings);
};
@ -1142,7 +1127,7 @@ var IPython = (function (IPython) {
};
Notebook.prototype.load_notebook = function (callback) {
Notebook.prototype.load_notebook = function () {
var that = this;
var notebook_id = IPython.save_widget.get_notebook_id();
// We do the call with settings so we can set cache to false.
@ -1153,9 +1138,6 @@ var IPython = (function (IPython) {
dataType : "json",
success : function (data, status, xhr) {
that.notebook_loaded(data, status, xhr);
if (callback !== undefined) {
callback();
};
}
};
IPython.save_widget.status_loading();
@ -1165,10 +1147,9 @@ var IPython = (function (IPython) {
Notebook.prototype.notebook_loaded = function (data, status, xhr) {
var allowed = xhr.getResponseHeader('Allow');
this.fromJSON(data);
if (this.ncells() === 0) {
this.insert_code_cell_below();
this.insert_cell_below('code');
};
IPython.save_widget.status_last_saved();
IPython.save_widget.set_notebook_name(data.metadata.name);
@ -1176,12 +1157,10 @@ var IPython = (function (IPython) {
if (! this.read_only) {
this.start_kernel();
}
// fromJSON always selects the last cell inserted. We need to wait
// until that is done before scrolling to the top.
setTimeout(function () {
IPython.notebook.select(0);
IPython.notebook.scroll_to_top();
}, 50);
this.select(0);
this.scroll_to_top();
IPython.save_widget.update_url();
IPython.layout_manager.do_resize();
};
IPython.Notebook = Notebook;

@ -109,16 +109,8 @@ $(document).ready(function () {
$('div#menubar').css('display','block');
$('div#main_app').css('display','block');
// Perform these actions after the notebook has been loaded.
// We wait 100 milliseconds because the notebook scrolls to the top after a load
// is completed and we need to wait for that to mostly finish.
IPython.notebook.load_notebook(function () {
setTimeout(function () {
IPython.save_widget.update_url();
IPython.layout_manager.do_resize();
IPython.pager.collapse();
},100);
});
IPython.layout_manager.do_resize();
IPython.notebook.load_notebook();
});

@ -16,7 +16,7 @@ var IPython = (function (IPython) {
var Pager = function (pager_selector, pager_splitter_selector) {
this.pager_element = $(pager_selector);
this.pager_splitter_element = $(pager_splitter_selector);
this.expanded = true;
this.expanded = false;
this.percentage_height = 0.40;
this.style();
this.bind_events();

@ -75,8 +75,8 @@ var IPython = (function (IPython) {
var new_name = $(this).find('input').attr('value');
if (!that.test_notebook_name(new_name)) {
$(this).find('h3').html(
"Invalid notebook name. " +
"Notebook names can contain any characters " +
"Invalid notebook name. Notebook names must "+
"have 1 or more characters and can contain any characters " +
"except / and \\. Please enter a new notebook name:"
);
} else {
@ -131,7 +131,8 @@ var IPython = (function (IPython) {
SaveWidget.prototype.test_notebook_name = function (nbname) {
if (this.notebook_name_blacklist_re.test(nbname) == false) {
nbname = nbname || '';
if (this.notebook_name_blacklist_re.test(nbname) == false && nbname.length>0) {
return true;
} else {
return false;

@ -15,7 +15,6 @@ var IPython = (function (IPython) {
var TextCell = function (notebook) {
this.code_mirror_mode = this.code_mirror_mode || 'htmlmixed';
this.placeholder = this.placeholder || '\u0000';
IPython.Cell.apply(this, arguments);
this.rendered = false;
this.cell_type = this.cell_type || 'text';
@ -28,16 +27,17 @@ var IPython = (function (IPython) {
TextCell.prototype.create_element = function () {
var cell = $("<div>").addClass('cell text_cell border-box-sizing');
cell.attr('tabindex','2');
var input_area = $('<div/>').addClass('text_cell_input');
var input_area = $('<div/>').addClass('text_cell_input border-box-sizing');
this.code_mirror = CodeMirror(input_area.get(0), {
indentUnit : 4,
mode: this.code_mirror_mode,
theme: 'default',
value: this.placeholder,
readOnly: this.read_only
readOnly: this.read_only,
onKeyEvent: $.proxy(this.handle_codemirror_keyevent,this)
});
// The tabindex=-1 makes this div focusable.
var render_area = $('<div/>').addClass('text_cell_render').
var render_area = $('<div/>').addClass('text_cell_render border-box-sizing').
addClass('rendered_html').attr('tabindex','-1');
cell.append(input_area).append(render_area);
this.element = cell;
@ -51,13 +51,30 @@ var IPython = (function (IPython) {
if (event.which === 13) {
if (that.rendered) {
that.edit();
event.preventDefault();
}
}
return false;
};
};
});
this.element.dblclick(function () {
that.edit();
});
};
TextCell.prototype.handle_codemirror_keyevent = function (editor, event) {
// This method gets called in CodeMirror's onKeyDown/onKeyPress
// handlers and is used to provide custom key handling. Its return
// value is used to determine if CodeMirror should ignore the event:
// true = ignore, false = don't ignore.
if (event.keyCode === 13 && (event.shiftKey || event.ctrlKey)) {
// Always ignore shift-enter in CodeMirror as we handle it.
return true;
}
return false;
};
TextCell.prototype.select = function () {
IPython.Cell.prototype.select.apply(this);
var output = this.element.find("div.text_cell_render");
@ -79,11 +96,18 @@ var IPython = (function (IPython) {
var output = text_cell.find("div.text_cell_render");
output.hide();
text_cell.find('div.text_cell_input').show();
// I don't know why I need to do this, but if I don't do
// refresh/focus/refresh, the to_markdown method won't work.
this.code_mirror.refresh();
this.code_mirror.focus();
// This final refresh is needed on Firefox to trigger the editor
// to be auto-sized. This glitch only happens on cell that are
// loaded initially and haven't had their editor focused before.
this.code_mirror.refresh();
this.rendered = false;
if (this.get_source() === this.placeholder) {
this.set_source('');
if (this.get_text() === this.placeholder) {
this.set_text('');
this.refresh();
}
}
};
@ -93,22 +117,12 @@ var IPython = (function (IPython) {
TextCell.prototype.render = function () {};
TextCell.prototype.config_mathjax = function () {
var text_cell = this.element;
var that = this;
text_cell.dblclick(function () {
that.edit();
});
that.render();
};
TextCell.prototype.get_source = function() {
TextCell.prototype.get_text = function() {
return this.code_mirror.getValue();
};
TextCell.prototype.set_source = function(text) {
TextCell.prototype.set_text = function(text) {
this.code_mirror.setValue(text);
this.code_mirror.refresh();
};
@ -145,7 +159,7 @@ var IPython = (function (IPython) {
TextCell.prototype.fromJSON = function (data) {
if (data.cell_type === this.cell_type) {
if (data.source !== undefined) {
this.set_source(data.source);
this.set_text(data.source);
this.set_rendered(data.rendered || '');
this.rendered = false;
this.render();
@ -157,7 +171,7 @@ var IPython = (function (IPython) {
TextCell.prototype.toJSON = function () {
var data = {};
data.cell_type = this.cell_type;
data.source = this.get_source();
data.source = this.get_text();
return data;
};
@ -165,7 +179,7 @@ var IPython = (function (IPython) {
// HTMLCell
var HTMLCell = function (notebook) {
this.placeholder = "\u0000Type <strong>HTML</strong> and LaTeX: $\\alpha^2$";
this.placeholder = "Type <strong>HTML</strong> and LaTeX: $\\alpha^2$";
IPython.TextCell.apply(this, arguments);
this.cell_type = 'html';
};
@ -176,7 +190,7 @@ var IPython = (function (IPython) {
HTMLCell.prototype.render = function () {
if (this.rendered === false) {
var text = this.get_source();
var text = this.get_text();
if (text === "") { text = this.placeholder; }
this.set_rendered(text);
this.typeset();
@ -190,7 +204,7 @@ var IPython = (function (IPython) {
// MarkdownCell
var MarkdownCell = function (notebook) {
this.placeholder = "\u0000Type *Markdown* and LaTeX: $\\alpha^2$";
this.placeholder = "Type *Markdown* and LaTeX: $\\alpha^2$";
IPython.TextCell.apply(this, arguments);
this.cell_type = 'markdown';
};
@ -201,7 +215,7 @@ var IPython = (function (IPython) {
MarkdownCell.prototype.render = function () {
if (this.rendered === false) {
var text = this.get_source();
var text = this.get_text();
if (text === "") { text = this.placeholder; }
var html = IPython.markdown_converter.makeHtml(text);
this.set_rendered(html);
@ -228,7 +242,7 @@ var IPython = (function (IPython) {
// RSTCell
var RSTCell = function (notebook) {
this.placeholder = "\u0000Type *ReStructured Text* and LaTeX: $\\alpha^2$";
this.placeholder = "Type *ReStructured Text* and LaTeX: $\\alpha^2$";
IPython.TextCell.apply(this, arguments);
this.cell_type = 'rst';
};
@ -239,7 +253,7 @@ var IPython = (function (IPython) {
RSTCell.prototype.render = function () {
if (this.rendered === false) {
var text = this.get_source();
var text = this.get_text();
if (text === "") { text = this.placeholder; }
var settings = {
processData : false,

@ -17,10 +17,7 @@
<link rel="stylesheet" href="/static/jquery/css/themes/base/jquery-ui.min.css" type="text/css" />
<link rel="stylesheet" href="/static/codemirror/lib/codemirror.css">
<link rel="stylesheet" href="/static/codemirror/mode/markdown/markdown.css">
<link rel="stylesheet" href="/static/codemirror/mode/rst/rst.css">
<link rel="stylesheet" href="/static/codemirror/theme/ipython.css">
<link rel="stylesheet" href="/static/codemirror/theme/default.css">
<link rel="stylesheet" href="/static/prettify/prettify.css"/>
@ -179,6 +176,8 @@
<script src="/static/ace/ace.js" type="text/javascript" charset="utf-8"></script>
<script src="/static/ace/mode-python.js" type="text/javascript" charset="utf-8"></script>
<script src="/static/ace/mode-markdown.js" type="text/javascript" charset="utf-8"></script>
<script src="/static/ace/mode-html.js" type="text/javascript" charset="utf-8"></script>
<script src="/static/ace/theme-textmate.js" type="text/javascript" charset="utf-8"></script>
<script src="/static/pagedown/Markdown.Converter.js" charset="utf-8"></script>

Loading…
Cancel
Save