');
- bad_filename.html(
- "The filename you entered (" + filename + ") is not valid. Notebook filenames must have the following form: foo.ipynb"
- );
- bad_filename.dialog({title: 'Invalid filename', modal: true});
- return false;
- };
- };
-
- Notebook.prototype.save_notebook = function (filename) {
- this.filename = filename || this.filename || '';
- if (this.filename === '') {
- var no_filename = $('');
- no_filename.html(
- "This notebook has no filename, please specify a filename of the form: foo.ipynb"
- );
- no_filename.dialog({title: 'Missing filename', modal: true});
- return;
- }
- if (!this.test_filename(this.filename)) {return;}
- var thedata = this.toJSON();
- var settings = {
- processData : false,
- cache : false,
- type : "PUT",
- data : JSON.stringify(thedata),
- success : function (data, status, xhr) {console.log(data);}
- };
- $.ajax("/notebooks/" + this.filename, settings);
- };
+ Notebook.prototype.notebook_saved = function (data, status, xhr) {
+ IPython.save_widget.status_save();
+ }
- Notebook.prototype.load_notebook = function (filename) {
- if (!this.test_filename(filename)) {return;}
- var that = this;
+ Notebook.prototype.load_notebook = function () {
+ var notebook_id = IPython.save_widget.get_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.fromJSON(data);
- that.filename = filename;
- that.kernel.restart();
- }
+ success : $.proxy(this.notebook_loaded,this)
};
- $.ajax("/notebooks/" + filename, settings);
+ IPython.save_widget.status_loading();
+ $.ajax("/notebooks/" + notebook_id, settings);
}
+
+ Notebook.prototype.notebook_loaded = function (data, status, xhr) {
+ this.fromJSON(data);
+ if (this.ncells() === 0) {
+ this.insert_code_cell_after();
+ };
+ IPython.save_widget.status_save();
+ IPython.save_widget.set_notebook_name(data.name);
+ this.start_kernel();
+ };
+
IPython.Notebook = Notebook;
return IPython;
diff --git a/IPython/frontend/html/notebook/static/js/notebook_main.js b/IPython/frontend/html/notebook/static/js/notebook_main.js
index 57d8909..0d5071d 100644
--- a/IPython/frontend/html/notebook/static/js/notebook_main.js
+++ b/IPython/frontend/html/notebook/static/js/notebook_main.js
@@ -30,14 +30,18 @@ $(document).ready(function () {
IPython.kernel_status_widget.status_idle();
IPython.layout_manager.do_resize();
- IPython.notebook.insert_code_cell_after();
- IPython.layout_manager.do_resize();
// These have display: none in the css file and are made visible here to prevent FLOUC.
$('div#header').css('display','block');
$('div#notebook_app').css('display','block');
- IPython.layout_manager.do_resize();
- IPython.pager.collapse();
- IPython.layout_manager.do_resize();
+
+ IPython.notebook.load_notebook();
+
+ // Perform these actions after the notebook has been loaded.
+ setTimeout(function () {
+ IPython.save_widget.update_url();
+ IPython.layout_manager.do_resize();
+ IPython.pager.collapse();
+ }, 100);
});
diff --git a/IPython/frontend/html/notebook/static/js/panelsection.js b/IPython/frontend/html/notebook/static/js/panelsection.js
index f95b872..82a76c3 100644
--- a/IPython/frontend/html/notebook/static/js/panelsection.js
+++ b/IPython/frontend/html/notebook/static/js/panelsection.js
@@ -82,20 +82,31 @@ var IPython = (function (IPython) {
this.content.addClass('ui-helper-clearfix');
this.content.find('div.section_row').addClass('ui-helper-clearfix');
this.content.find('#new_open').buttonset();
+ this.content.find('#download_notebook').button();
+ this.content.find('#upload_notebook').button();
+ this.content.find('#download_format').addClass('ui-widget ui-widget-content');
+ this.content.find('#download_format option').addClass('ui-widget ui-widget-content');
};
NotebookSection.prototype.bind_events = function () {
PanelSection.prototype.bind_events.apply(this);
+ var that = this;
this.content.find('#new_notebook').click(function () {
- alert('Not Implemented');
+ console.log('click!')
+ window.open('/');
});
this.content.find('#open_notebook').click(function () {
alert('Not Implemented');
});
+ this.content.find('#download_notebook').click(function () {
+ var format = that.content.find('#download_format').val();
+ var notebook_id = IPython.save_widget.get_notebook_id();
+ var url = '/notebooks/' + notebook_id + '?format=' + format;
+ window.open(url,'_newtab');
+ });
};
-
// CellSection
var CellSection = function () {
diff --git a/IPython/frontend/html/notebook/static/js/savewidget.js b/IPython/frontend/html/notebook/static/js/savewidget.js
index 57c3420..bf0e22e 100644
--- a/IPython/frontend/html/notebook/static/js/savewidget.js
+++ b/IPython/frontend/html/notebook/static/js/savewidget.js
@@ -9,6 +9,7 @@ var IPython = (function (IPython) {
var SaveWidget = function (selector) {
this.selector = selector;
+ this.notebook_name_re = /[^/\\]+/
if (this.selector !== undefined) {
this.element = $(selector);
this.style();
@@ -29,7 +30,7 @@ var IPython = (function (IPython) {
SaveWidget.prototype.bind_events = function () {
var that = this;
this.element.find('button#save_notebook').click(function () {
- IPython.notebook.save_notebook(that.get_notebook_name());
+ IPython.notebook.save_notebook();
});
};
@@ -39,11 +40,59 @@ var IPython = (function (IPython) {
}
- SaveWidget.prototype.set_notebook_name = function (name) {
- this.element.find('input#notebook_name').attr('value',name);
+ SaveWidget.prototype.set_notebook_name = function (nbname) {
+ this.element.find('input#notebook_name').attr('value',nbname);
}
+ SaveWidget.prototype.get_notebook_id = function () {
+ return this.element.find('span#notebook_id').text()
+ };
+
+
+ SaveWidget.prototype.update_url = function () {
+ var notebook_id = this.get_notebook_id();
+ if (notebook_id !== '') {
+ window.history.replaceState({}, '', notebook_id);
+ };
+ };
+
+
+ SaveWidget.prototype.test_notebook_name = function () {
+ var nbname = this.get_notebook_name();
+ if (this.notebook_name_re.test(nbname)) {
+ return true;
+ } else {
+ var bad_name = $('');
+ bad_name.html(
+ "The notebook name you entered (" +
+ nbname +
+ ") is not valid. Notebook names can contain any characters except / and \\"
+ );
+ bad_name.dialog({title: 'Invalid name', modal: true});
+ return false;
+ };
+ };
+
+
+ SaveWidget.prototype.status_save = function () {
+ this.element.find('span.ui-button-text').text('Save');
+ this.element.find('button#save_notebook').button('enable');
+ };
+
+
+ SaveWidget.prototype.status_saving = function () {
+ this.element.find('span.ui-button-text').text('Saving');
+ this.element.find('button#save_notebook').button('disable');
+ };
+
+
+ SaveWidget.prototype.status_loading = function () {
+ this.element.find('span.ui-button-text').text('Loading');
+ this.element.find('button#save_notebook').button('disable');
+ };
+
+
IPython.SaveWidget = SaveWidget;
return IPython;
diff --git a/IPython/frontend/html/notebook/static/js/textcell.js b/IPython/frontend/html/notebook/static/js/textcell.js
index ff3c936..7141ded 100644
--- a/IPython/frontend/html/notebook/static/js/textcell.js
+++ b/IPython/frontend/html/notebook/static/js/textcell.js
@@ -129,17 +129,19 @@ var IPython = (function (IPython) {
TextCell.prototype.fromJSON = function (data) {
if (data.cell_type === 'text') {
- this.set_text(data.text);
- this.grow(this.element.find("textarea.text_cell_input"));
+ if (data.text !== undefined) {
+ this.set_text(data.text);
+ this.grow(this.element.find("textarea.text_cell_input"));
+ };
};
}
TextCell.prototype.toJSON = function () {
- return {
- cell_type : 'text',
- text : this.get_text(),
- };
+ var data = {}
+ data.cell_type = 'text';
+ data.text = this.get_text();
+ return data;
};
IPython.TextCell = TextCell;
diff --git a/IPython/frontend/html/notebook/templates/notebook.html b/IPython/frontend/html/notebook/templates/notebook.html
index 2df57a0..024a7fa 100644
--- a/IPython/frontend/html/notebook/templates/notebook.html
+++ b/IPython/frontend/html/notebook/templates/notebook.html
@@ -33,6 +33,7 @@
IPython Notebook
+ {{notebook_id}}
Idle
@@ -52,6 +53,18 @@
+
+
+
+
+
+
+
+
diff --git a/IPython/nbformat/current.py b/IPython/nbformat/current.py
index f857124..c587bac 100644
--- a/IPython/nbformat/current.py
+++ b/IPython/nbformat/current.py
@@ -5,6 +5,11 @@ import re
from IPython.nbformat import v2
from IPython.nbformat import v1
+from IPython.nbformat.v2 import (
+ NotebookNode,
+ new_code_cell, new_text_cell, new_notebook, new_output, new_worksheet
+)
+
current_nbformat = 2
diff --git a/IPython/nbformat/v2/nbpy.py b/IPython/nbformat/v2/nbpy.py
index 1c51cf0..aa775ff 100644
--- a/IPython/nbformat/v2/nbpy.py
+++ b/IPython/nbformat/v2/nbpy.py
@@ -36,10 +36,11 @@ class PyWriter(NotebookWriter):
for ws in nb.worksheets:
for cell in ws.cells:
if cell.cell_type == 'code':
- input = cell.input
- lines.extend([u'# ',u''])
- lines.extend(input.splitlines())
- lines.extend([u'',u'# '])
+ input = cell.get('input')
+ if input is not None:
+ lines.extend([u'# ',u''])
+ lines.extend(input.splitlines())
+ lines.extend([u'',u'# '])
lines.append('')
return unicode('\n'.join(lines))