Merge pull request #1361 from ellisonbg/nbissues

A number of bug fixes for notebook issues that had crept up recently with all the major improvements done on multiple fronts.

In closing #1359, we've changed slightly how Math() works: it now unconditionally surrounds its input with $$...$$, so that it always appears in displayed math mode.  We have also introduced a new display object, Latex(), which does *not* add any latex markup, for other constructs beyond simple math expressions.  This change makes Math() friendlier to use in simple cases and means that Math(sympy.latex(foo)) will produce the expected displayed math results without the user having to add any $ markup.

Summary of fixes:

Fixes #1344: Ctrl + M + L does not toggle line numbering in htmlnotebook.

Fixes #1337: Tab in the notebook after `(` should not indent, only give a tooltip.

Fixes #1339: Notebook printing broken.

Fixes #1348: `Ctrl-m-Ctrl-m` does not switch to markdown cell

Fixes #1359: [sympyprinting] MathJax can't render \root{m}{n}
This commit is contained in:
Fernando Perez 2012-02-02 13:41:01 -08:00
commit 8c6572347a
13 changed files with 350 additions and 183 deletions

View File

@ -55,6 +55,19 @@ span#notebook_name {
margin: 0.3em 0;
}
#menubar_container {
position: relative;
}
#notification {
position: absolute;
right: 3px;
top: 3px;
height: 25px;
padding: 3px 6px;
z-index: 10;
}
#toolbar {
/* Initially hidden to prevent FLOUC */
display: none;
@ -71,31 +84,6 @@ span#quick_help_area {
margin: 0px 0px 0px 0px;
}
span#kernel_status {
position: absolute;
padding: 8px 5px 5px 5px;
right: 10px;
font-weight: bold;
}
.status_idle {
color: gray;
visibility: hidden;
}
.status_busy {
color: red;
}
.status_restarting {
color: black;
}
#kernel_persist {
float: right;
}
.help_string {
float: right;
width: 170px;

View File

@ -142,6 +142,16 @@ var IPython = (function (IPython) {
};
Cell.prototype.toggle_line_numbers = function () {
if (this.code_mirror.getOption('lineNumbers') == false) {
this.code_mirror.setOption('lineNumbers', true);
} else {
this.code_mirror.setOption('lineNumbers', false);
}
this.code_mirror.refresh();
};
IPython.Cell = Cell;
return IPython;

View File

@ -79,11 +79,11 @@ var IPython = (function (IPython) {
var that = this;
// whatever key is pressed, first, cancel the tooltip request before
// they are sent, and remove tooltip if any
if(event.type === 'keydown' ){
if(event.type === 'keydown' ) {
that.remove_and_cancel_tooltip();
}
};
if (event.keyCode === 13 && (event.shiftKey || event.ctrlKey)) {
// Always ignore shift-enter in CodeMirror as we handle it.
return true;
@ -123,6 +123,10 @@ var IPython = (function (IPython) {
return false;
} else if ((pre_cursor.substr(-1) === "("|| pre_cursor.substr(-1) === " ") && tooltip_on_tab ) {
that.request_tooltip_after_time(pre_cursor,0);
// Prevent the event from bubbling up.
event.stop();
// Prevent CodeMirror from handling the tab.
return true;
} else {
pre_cursor.trim();
// Autocomplete the current line.
@ -132,7 +136,7 @@ var IPython = (function (IPython) {
this.completion_cursor = cur;
IPython.notebook.complete_cell(this, line, cur.ch);
return true;
}
};
} else if (event.keyCode === 8 && event.type == 'keydown') {
// If backspace and the line ends with 4 spaces, remove them.
var cur = editor.getCursor();
@ -147,13 +151,8 @@ var IPython = (function (IPython) {
return true;
} else {
return false;
}
} else if (event.keyCode === 76 && event.ctrlKey && event.shiftKey
&& event.type == 'keydown') {
// toggle line numbers with Ctrl-Shift-L
this.toggle_line_numbers();
}
else {
};
} else {
// keypress/keyup also trigger on TAB press, and we don't want to
// use those to disable tab completion.
if (this.is_completing && event.keyCode !== 9) {
@ -162,8 +161,8 @@ var IPython = (function (IPython) {
if (ed_cur.line !== cc_cur.line || ed_cur.ch !== cc_cur.ch) {
this.is_completing = false;
this.completion_cursor = null;
}
}
};
};
return false;
};
return false;
@ -545,16 +544,6 @@ var IPython = (function (IPython) {
};
CodeCell.prototype.toggle_line_numbers = function () {
if (this.code_mirror.getOption('lineNumbers') == false) {
this.code_mirror.setOption('lineNumbers', true);
} else {
this.code_mirror.setOption('lineNumbers', false);
}
this.code_mirror.refresh();
};
CodeCell.prototype.select = function () {
IPython.Cell.prototype.select.apply(this);
this.code_mirror.refresh();

View File

@ -0,0 +1,31 @@
//----------------------------------------------------------------------------
// Copyright (C) 2008-2011 The IPython Development Team
//
// Distributed under the terms of the BSD License. The full license is in
// the file COPYING, distributed as part of this software.
//----------------------------------------------------------------------------
//============================================================================
// Events
//============================================================================
// Give us an object to bind all events to. This object should be created
// before all other objects so it exists when others register event handlers.
// To trigger an event handler:
// $([IPython.events]).trigger('event.Namespace);
// To handle it:
// $([IPython.events]).on('event.Namespace',function () {});
var IPython = (function (IPython) {
var utils = IPython.utils;
var Events = function () {};
IPython.Events = Events;
IPython.events = new Events();
return IPython;
}(IPython));

View File

@ -62,7 +62,7 @@ var IPython = (function (IPython) {
Kernel.prototype.restart = function (callback) {
IPython.kernel_status_widget.status_restarting();
$([IPython.events]).trigger('status_restarting.Kernel');
var url = this.kernel_url + "/restart";
var that = this;
if (this.running) {
@ -84,20 +84,19 @@ var IPython = (function (IPython) {
this.kernel_url = this.base_url + "/" + this.kernel_id;
this.start_channels();
callback();
IPython.kernel_status_widget.status_idle();
};
Kernel.prototype._websocket_closed = function(ws_url, early){
var msg;
var parent_item = $('body');
if (early) {
msg = "Websocket connection to " + ws_url + " could not be established.<br/>" +
" You will NOT be able to run code.<br/>" +
msg = "Websocket connection to " + ws_url + " could not be established." +
" You will NOT be able to run code." +
" Your browser may not be compatible with the websocket version in the server," +
" or if the url does not look right, there could be an error in the" +
" server's configuration.";
} else {
msg = "Websocket connection closed unexpectedly.<br/>" +
msg = "Websocket connection closed unexpectedly." +
" The kernel will no longer be responsive.";
}
var dialog = $('<div/>');
@ -107,8 +106,10 @@ var IPython = (function (IPython) {
resizable: false,
modal: true,
title: "Websocket closed",
closeText: "",
close: function(event, ui) {$(this).dialog('destroy').remove();},
buttons : {
"Okay": function () {
"OK": function () {
$(this).dialog('close');
}
}
@ -211,6 +212,7 @@ var IPython = (function (IPython) {
Kernel.prototype.interrupt = function () {
if (this.running) {
$([IPython.events]).trigger('status_interrupting.Kernel');
$.post(this.kernel_url + "/interrupt");
};
};

View File

@ -45,21 +45,21 @@ var IPython = (function (IPython) {
IPython.save_widget.rename_notebook();
});
this.element.find('#copy_notebook').click(function () {
var notebook_id = IPython.save_widget.get_notebook_id();
var notebook_id = IPython.notebook.get_notebook_id();
var url = $('body').data('baseProjectUrl') + notebook_id + '/copy';
window.open(url,'_newtab');
});
this.element.find('#save_notebook').click(function () {
IPython.save_widget.save_notebook();
IPython.notebook.save_notebook();
});
this.element.find('#download_ipynb').click(function () {
var notebook_id = IPython.save_widget.get_notebook_id();
var notebook_id = IPython.notebook.get_notebook_id();
var url = $('body').data('baseProjectUrl') + 'notebooks/' +
notebook_id + '?format=json';
window.open(url,'_newtab');
});
this.element.find('#download_py').click(function () {
var notebook_id = IPython.save_widget.get_notebook_id();
var notebook_id = IPython.notebook.get_notebook_id();
var url = $('body').data('baseProjectUrl') + 'notebooks/' +
notebook_id + '?format=py';
window.open(url,'_newtab');

View File

@ -26,6 +26,10 @@ var IPython = (function (IPython) {
this.msg_cell_map = {};
this.metadata = {};
this.control_key_active = false;
this.notebook_id = null;
this.notebook_name = null;
this.notebook_name_blacklist_re = /[\/\\]/;
this.nbformat = 3 // Increment this when changing the nbformat
this.style();
this.create_elements();
this.bind_events();
@ -66,7 +70,7 @@ var IPython = (function (IPython) {
// Save (CTRL+S) or (AppleKey+S)
//metaKey = applekey on mac
if ((event.ctrlKey || event.metaKey) && event.keyCode==83) {
IPython.save_widget.save_notebook();
that.save_notebook();
event.preventDefault();
return false;
} else if (event.which === 27) {
@ -92,7 +96,7 @@ var IPython = (function (IPython) {
} else if (event.which === 13 && event.ctrlKey) {
that.execute_selected_cell({terminal:true});
return false;
} else if (event.which === 77 && event.ctrlKey) {
} else if (event.which === 77 && event.ctrlKey && that.control_key_active == false) {
that.control_key_active = true;
return false;
} else if (event.which === 88 && that.control_key_active) {
@ -177,7 +181,7 @@ var IPython = (function (IPython) {
return false;
} else if (event.which === 83 && that.control_key_active) {
// Save notebook = s
IPython.save_widget.save_notebook();
that.save_notebook();
that.control_key_active = false;
return false;
} else if (event.which === 74 && that.control_key_active) {
@ -207,12 +211,12 @@ var IPython = (function (IPython) {
return false;
} else if (event.which === 73 && that.control_key_active) {
// Interrupt kernel = i
IPython.notebook.kernel.interrupt();
that.kernel.interrupt();
that.control_key_active = false;
return false;
} else if (event.which === 190 && that.control_key_active) {
// Restart kernel = . # matches qt console
IPython.notebook.restart_kernel();
that.restart_kernel();
that.control_key_active = false;
return false;
} else if (event.which === 72 && that.control_key_active) {
@ -402,10 +406,14 @@ var IPython = (function (IPython) {
var cell = this.get_cell(index)
cell.select();
if (cell.cell_type === 'heading') {
IPython.toolbar.set_cell_type(cell.cell_type+cell.level);
$([IPython.events]).trigger('selected_cell_type_changed.Notebook',
{'cell_type':cell.cell_type,level:cell.level}
);
} else {
IPython.toolbar.set_cell_type(cell.cell_type)
}
$([IPython.events]).trigger('selected_cell_type_changed.Notebook',
{'cell_type':cell.cell_type}
);
};
};
return this;
};
@ -676,7 +684,9 @@ var IPython = (function (IPython) {
source_element.remove();
this.dirty = true;
};
IPython.toolbar.set_cell_type("heading"+level);
$([IPython.events]).trigger('selected_cell_type_changed.Notebook',
{'cell_type':'heading',level:level}
);
};
};
@ -880,15 +890,12 @@ var IPython = (function (IPython) {
Notebook.prototype.start_kernel = function () {
this.kernel = new IPython.Kernel();
var notebook_id = IPython.save_widget.get_notebook_id();
this.kernel.start(notebook_id, $.proxy(this.kernel_started, this));
this.kernel.start(this.notebook_id, $.proxy(this.kernel_started, this));
};
Notebook.prototype.restart_kernel = function () {
var that = this;
var notebook_id = IPython.save_widget.get_notebook_id();
var dialog = $('<div/>');
dialog.html('Do you want to restart the current kernel? You will lose all variables defined in it.');
$(document).append(dialog);
@ -976,8 +983,8 @@ var IPython = (function (IPython) {
var cell = this.cell_for_msg(reply.parent_header.msg_id);
if (msg_type !== 'status' && !cell){
// message not from this notebook, but should be attached to a cell
console.log("Received IOPub message not caused by one of my cells");
console.log(reply);
// console.log("Received IOPub message not caused by one of my cells");
// console.log(reply);
return;
}
var output_types = ['stream','display_data','pyout','pyerr'];
@ -985,9 +992,10 @@ var IPython = (function (IPython) {
this.handle_output(cell, msg_type, content);
} else if (msg_type === 'status') {
if (content.execution_state === 'busy') {
$([IPython.events]).trigger('status_busy.Kernel');
IPython.kernel_status_widget.status_busy();
} else if (content.execution_state === 'idle') {
IPython.kernel_status_widget.status_idle();
$([IPython.events]).trigger('status_idle.Kernel');
} else if (content.execution_state === 'dead') {
this.handle_status_dead();
};
@ -1142,8 +1150,33 @@ var IPython = (function (IPython) {
this.msg_cell_map[msg_id] = cell.cell_id;
};
// Persistance and loading
Notebook.prototype.get_notebook_id = function () {
return this.notebook_id;
};
Notebook.prototype.get_notebook_name = function () {
return this.notebook_name;
};
Notebook.prototype.set_notebook_name = function (name) {
this.notebook_name = name;
};
Notebook.prototype.test_notebook_name = function (nbname) {
nbname = nbname || '';
if (this.notebook_name_blacklist_re.test(nbname) == false && nbname.length>0) {
return true;
} else {
return false;
};
};
Notebook.prototype.fromJSON = function (data) {
var ncells = this.ncells();
@ -1152,8 +1185,9 @@ var IPython = (function (IPython) {
// Always delete cell 0 as they get renumbered as they are deleted.
this.delete_cell(0);
};
// Save the metadata
// Save the metadata and name.
this.metadata = data.metadata;
this.notebook_name = data.metadata.name;
// Only handle 1 worksheet for now.
var worksheet = data.worksheets[0];
if (worksheet !== undefined) {
@ -1186,12 +1220,10 @@ var IPython = (function (IPython) {
};
Notebook.prototype.save_notebook = function () {
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 = 3;
data.metadata.name = this.notebook_name;
data.nbformat = this.nbformat;
// We do the call with settings so we can set cache to false.
var settings = {
processData : false,
@ -1199,63 +1231,108 @@ var IPython = (function (IPython) {
type : "PUT",
data : JSON.stringify(data),
headers : {'Content-Type': 'application/json'},
success : $.proxy(this.notebook_saved,this),
error : $.proxy(this.notebook_save_failed,this)
success : $.proxy(this.save_notebook_success,this),
error : $.proxy(this.save_notebook_error,this)
};
IPython.save_widget.status_saving();
var url = $('body').data('baseProjectUrl') + 'notebooks/' + notebook_id;
$([IPython.events]).trigger('notebook_saving.Notebook');
var url = $('body').data('baseProjectUrl') + 'notebooks/' + this.notebook_id;
$.ajax(url, settings);
};
Notebook.prototype.notebook_saved = function (data, status, xhr) {
Notebook.prototype.save_notebook_success = function (data, status, xhr) {
this.dirty = false;
IPython.save_widget.notebook_saved();
IPython.save_widget.status_last_saved();
$([IPython.events]).trigger('notebook_saved.Notebook');
};
Notebook.prototype.notebook_save_failed = function (xhr, status, error_msg) {
IPython.save_widget.status_save_failed();
Notebook.prototype.save_notebook_error = function (xhr, status, error_msg) {
$([IPython.events]).trigger('notebook_save_failed.Notebook');
};
Notebook.prototype.load_notebook = function () {
Notebook.prototype.load_notebook = function (notebook_id) {
var that = this;
var notebook_id = IPython.save_widget.get_notebook_id();
this.notebook_id = notebook_id;
// We do the call with settings so we can set cache to false.
var settings = {
processData : false,
cache : false,
type : "GET",
dataType : "json",
success : function (data, status, xhr) {
that.notebook_loaded(data, status, xhr);
}
success : $.proxy(this.load_notebook_success,this),
error : $.proxy(this.load_notebook_error,this),
};
IPython.save_widget.status_loading();
var url = $('body').data('baseProjectUrl') + 'notebooks/' + notebook_id;
$([IPython.events]).trigger('notebook_loading.Notebook');
var url = $('body').data('baseProjectUrl') + 'notebooks/' + this.notebook_id;
$.ajax(url, settings);
};
Notebook.prototype.notebook_loaded = function (data, status, xhr) {
Notebook.prototype.load_notebook_success = function (data, status, xhr) {
this.fromJSON(data);
if (this.ncells() === 0) {
this.insert_cell_below('code');
};
IPython.save_widget.status_last_saved();
IPython.save_widget.set_notebook_name(data.metadata.name);
this.dirty = false;
if (! this.read_only) {
this.start_kernel();
}
this.select(0);
this.scroll_to_top();
IPython.save_widget.update_url();
IPython.layout_manager.do_resize();
if (data.orig_nbformat !== undefined && data.nbformat !== data.orig_nbformat) {
msg = "This notebook has been converted from an older " +
"notebook format (v"+data.orig_nbformat+") to the current notebook " +
"format (v"+data.nbformat+"). The next time you save this notebook, the " +
"newer notebook format will be used and older verions of IPython " +
"may not be able to read it. To keep the older version, close the " +
"notebook without saving it.";
var dialog = $('<div/>');
dialog.html(msg);
this.element.append(dialog);
dialog.dialog({
resizable: false,
modal: true,
title: "Notebook converted",
closeText: "",
close: function(event, ui) {$(this).dialog('destroy').remove();},
buttons : {
"OK": function () {
$(this).dialog('close');
}
},
width: 400
});
}
$([IPython.events]).trigger('notebook_loaded.Notebook');
};
Notebook.prototype.load_notebook_error = function (xhr, textStatus, errorThrow) {
if (xhr.status === 500) {
msg = "An error occurred while loading this notebook. Most likely " +
"this notebook is in a newer format than is supported by this " +
"version of IPython. This version can load notebook formats " +
"v"+this.nbformat+" or earlier.";
var dialog = $('<div/>');
dialog.html(msg);
this.element.append(dialog);
dialog.dialog({
resizable: false,
modal: true,
title: "Error loading notebook",
closeText: "",
close: function(event, ui) {$(this).dialog('destroy').remove();},
buttons : {
"OK": function () {
$(this).dialog('close');
}
},
width: 400
});
}
}
IPython.Notebook = Notebook;

View File

@ -82,14 +82,13 @@ $(document).ready(function () {
IPython.layout_manager = new IPython.LayoutManager();
IPython.pager = new IPython.Pager('div#pager', 'div#pager_splitter');
IPython.save_widget = new IPython.SaveWidget('span#save_widget');
IPython.quick_help = new IPython.QuickHelp('span#quick_help_area');
IPython.login_widget = new IPython.LoginWidget('span#login_widget');
IPython.notebook = new IPython.Notebook('div#notebook');
IPython.kernel_status_widget = new IPython.KernelStatusWidget('#kernel_status');
IPython.save_widget = new IPython.SaveWidget('span#save_widget');
IPython.menubar = new IPython.MenuBar('#menubar')
IPython.toolbar = new IPython.ToolBar('#toolbar')
IPython.kernel_status_widget.status_idle();
IPython.notification_widget = new IPython.NotificationWidget('#notification')
IPython.layout_manager.do_resize();
@ -111,7 +110,11 @@ $(document).ready(function () {
$('div#main_app').css('display','block');
IPython.layout_manager.do_resize();
IPython.notebook.load_notebook();
$([IPython.events]).on('notebook_loaded.Notebook', function () {
IPython.layout_manager.do_resize();
IPython.save_widget.update_url();
})
IPython.notebook.load_notebook($('body').data('notebookId'));
});

View File

@ -0,0 +1,102 @@
//----------------------------------------------------------------------------
// Copyright (C) 2008-2011 The IPython Development Team
//
// Distributed under the terms of the BSD License. The full license is in
// the file COPYING, distributed as part of this software.
//----------------------------------------------------------------------------
//============================================================================
// Notification widget
//============================================================================
var IPython = (function (IPython) {
var utils = IPython.utils;
var NotificationWidget = function (selector) {
this.selector = selector;
this.timeout = null;
this.busy = false;
if (this.selector !== undefined) {
this.element = $(selector);
this.style();
this.bind_events();
}
};
NotificationWidget.prototype.style = function () {
this.element.addClass('ui-widget ui-widget-content ui-corner-all');
this.element.addClass('border-box-sizing');
};
NotificationWidget.prototype.bind_events = function () {
var that = this;
// Kernel events
$([IPython.events]).on('status_idle.Kernel',function () {
IPython.save_widget.update_document_title();
if (that.get_message() === 'Kernel busy') {
that.element.fadeOut(100, function () {
that.element.html('');
});
};
});
$([IPython.events]).on('status_busy.Kernel',function () {
window.document.title='(Busy) '+window.document.title;
that.set_message("Kernel busy");
});
$([IPython.events]).on('status_restarting.Kernel',function () {
that.set_message("Restarting kernel",500);
});
$([IPython.events]).on('status_interrupting.Kernel',function () {
that.set_message("Interrupting kernel",500);
});
// Notebook events
$([IPython.events]).on('notebook_loading.Notebook', function () {
that.set_message("Loading notebook",500);
});
$([IPython.events]).on('notebook_loaded.Notebook', function () {
that.set_message("Notebook loaded",500);
});
$([IPython.events]).on('notebook_saving.Notebook', function () {
that.set_message("Saving notebook",500);
});
$([IPython.events]).on('notebook_saved.Notebook', function () {
that.set_message("Notebook saved",500);
});
$([IPython.events]).on('notebook_save_failed.Notebook', function () {
that.set_message("Notebook save failed",500);
});
};
NotificationWidget.prototype.set_message = function (msg, timeout) {
var that = this;
this.element.html(msg);
this.element.fadeIn(100);
if (this.timeout !== null) {
clearTimeout(this.timeout);
this.timeout = null;
};
if (timeout !== undefined) {
this.timeout = setTimeout(function () {
that.element.fadeOut(100, function () {that.element.html('');});
that.timeout = null;
}, timeout)
};
};
NotificationWidget.prototype.get_message = function () {
return this.element.html();
};
IPython.NotificationWidget = NotificationWidget;
return IPython;
}(IPython));

View File

@ -15,8 +15,6 @@ var IPython = (function (IPython) {
var SaveWidget = function (selector) {
this.selector = selector;
this.notebook_name_blacklist_re = /[\/\\]/;
this.last_saved_name = '';
if (this.selector !== undefined) {
this.element = $(selector);
this.style();
@ -43,11 +41,19 @@ var IPython = (function (IPython) {
}, function () {
$(this).removeClass("ui-state-hover");
});
};
SaveWidget.prototype.save_notebook = function () {
IPython.notebook.save_notebook();
$([IPython.events]).on('notebook_loaded.Notebook', function () {
that.set_last_saved();
that.update_notebook_name();
that.update_document_title();
});
$([IPython.events]).on('notebook_saved.Notebook', function () {
that.set_last_saved();
that.update_notebook_name();
that.update_document_title();
});
$([IPython.events]).on('notebook_save_failed.Notebook', function () {
that.set_save_status('');
});
};
@ -61,7 +67,7 @@ var IPython = (function (IPython) {
dialog.append(
$('<input/>').attr('type','text').attr('size','25')
.addClass('ui-widget ui-widget-content')
.attr('value',that.get_notebook_name())
.attr('value',IPython.notebook.get_notebook_name())
);
// $(document).append(dialog);
dialog.dialog({
@ -73,15 +79,15 @@ var IPython = (function (IPython) {
buttons : {
"OK": function () {
var new_name = $(this).find('input').attr('value');
if (!that.test_notebook_name(new_name)) {
if (!IPython.notebook.test_notebook_name(new_name)) {
$(this).find('h3').html(
"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 {
that.set_notebook_name(new_name);
that.save_notebook();
IPython.notebook.set_notebook_name(new_name);
IPython.notebook.save_notebook();
$(this).dialog('close');
}
},
@ -92,82 +98,36 @@ var IPython = (function (IPython) {
});
}
SaveWidget.prototype.notebook_saved = function () {
this.set_document_title();
this.last_saved_name = this.get_notebook_name();
};
SaveWidget.prototype.get_notebook_name = function () {
return this.element.find('span#notebook_name').html();
};
SaveWidget.prototype.set_notebook_name = function (nbname) {
SaveWidget.prototype.update_notebook_name = function () {
var nbname = IPython.notebook.get_notebook_name();
this.element.find('span#notebook_name').html(nbname);
this.set_document_title();
this.last_saved_name = nbname;
};
SaveWidget.prototype.set_document_title = function () {
nbname = this.get_notebook_name();
SaveWidget.prototype.update_document_title = function () {
var nbname = IPython.notebook.get_notebook_name();
document.title = nbname;
};
SaveWidget.prototype.get_notebook_id = function () {
return $('body').data('notebookId');
};
SaveWidget.prototype.update_url = function () {
var notebook_id = this.get_notebook_id();
if (notebook_id !== '') {
var notebook_id = IPython.notebook.get_notebook_id();
if (notebook_id !== null) {
var new_url = $('body').data('baseProjectUrl') + notebook_id;
window.history.replaceState({}, '', new_url);
};
};
SaveWidget.prototype.test_notebook_name = function (nbname) {
nbname = nbname || '';
if (this.notebook_name_blacklist_re.test(nbname) == false && nbname.length>0) {
return true;
} else {
return false;
};
};
SaveWidget.prototype.set_save_status = function (msg) {
this.element.find('span#save_status').html(msg);
}
SaveWidget.prototype.set_last_saved = function () {
var d = new Date();
$('#save_status').html('Last saved: '+d.format('mmm dd h:MM TT'));
};
SaveWidget.prototype.reset_status = function () {
this.element.find('span#save_status').html('');
};
SaveWidget.prototype.status_last_saved = function () {
this.set_last_saved();
};
SaveWidget.prototype.status_saving = function () {
this.element.find('span#save_status').html('Saving...');
};
SaveWidget.prototype.status_save_failed = function () {
this.element.find('span#save_status').html('Save failed');
};
SaveWidget.prototype.status_loading = function () {
this.element.find('span#save_status').html('Loading...');
this.set_save_status('Last saved: '+d.format('mmm dd h:MM TT'));
};

View File

@ -49,7 +49,7 @@ var IPython = (function (IPython) {
IPython.Cell.prototype.bind_events.apply(this);
var that = this;
this.element.keydown(function (event) {
if (event.which === 13) {
if (event.which === 13 && !event.shiftKey) {
if (that.rendered) {
that.edit();
return false;

View File

@ -72,8 +72,9 @@ var IPython = (function (IPython) {
ToolBar.prototype.bind_events = function () {
var that = this;
this.element.find('#save_b').click(function () {
IPython.save_widget.save_notebook();
IPython.notebook.save_notebook();
});
this.element.find('#cut_b').click(function () {
IPython.notebook.cut_cell();
@ -124,12 +125,13 @@ var IPython = (function (IPython) {
IPython.notebook.to_heading(undefined, 6);
};
});
};
ToolBar.prototype.set_cell_type = function (cell_type) {
this.element.find('#cell_type').val(cell_type);
$([IPython.events]).on('selected_cell_type_changed', function (event, data) {
if (data.cell_type === 'heading') {
that.element.find('#cell_type').val(data.cell_type+data.level);
} else {
that.element.find('#cell_type').val(data.cell_type);
}
});
};

View File

@ -54,10 +54,9 @@
<button id="login">Login</button>
{% end %}
</span>
<span id="kernel_status">Idle</span>
</div>
<div id="menubar_container">
<div id="menubar">
<ul id="menus">
<li><a href="#">File</a>
@ -153,6 +152,9 @@
</ul>
</div>
<div id="notification"></div>
</div>
<div id="toolbar">
@ -220,12 +222,12 @@
<script src="{{ static_url("dateformat/date.format.js") }}" charset="utf-8"></script>
<script src="{{ static_url("js/namespace.js") }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ static_url("js/events.js") }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ static_url("js/utils.js") }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ static_url("js/cell.js") }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ static_url("js/codecell.js") }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ static_url("js/textcell.js") }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ static_url("js/kernel.js") }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ static_url("js/kernelstatus.js") }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ static_url("js/layout.js") }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ static_url("js/savewidget.js") }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ static_url("js/quickhelp.js") }}" type="text/javascript" charset="utf-8"></script>
@ -234,6 +236,7 @@
<script src="{{ static_url("js/menubar.js") }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ static_url("js/toolbar.js") }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ static_url("js/notebook.js") }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ static_url("js/notificationwidget.js") }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ static_url("js/notebookmain.js") }}" type="text/javascript" charset="utf-8"></script>
</body>