Merge pull request #1934 from minrk/cellmd

Cell/Worksheet metadata

* metadata dicts are attached to cells and worksheets
* restores collapsed flag to the nbformat - this change happened in the refactor, and was undocumented, and possibly accidental.  But we should either document it or fix it, and this includes a fix.
* adds a new field, `nbformat_minor`, used to denote minor bumps of the notebook format that expose new capabilities but don't prevent loading by older clients.
* Add a warning in Javascript if loading a multiworksheet notebook (which will exist in the future) as current JS code will only save the first.


closes #1915
This commit is contained in:
Fernando Perez 2012-06-17 17:21:35 -07:00
commit f52a1f689c
4 changed files with 75 additions and 6 deletions

View File

@ -19,6 +19,7 @@ var IPython = (function (IPython) {
this.read_only = false; this.read_only = false;
this.selected = false; this.selected = false;
this.element = null; this.element = null;
this.metadata = {};
this.create_element(); this.create_element();
if (this.element !== null) { if (this.element !== null) {
this.element.data("cell", this); this.element.data("cell", this);
@ -90,10 +91,16 @@ var IPython = (function (IPython) {
Cell.prototype.toJSON = function () { Cell.prototype.toJSON = function () {
var data = {};
data.metadata = this.metadata;
return data;
}; };
Cell.prototype.fromJSON = function (data) { Cell.prototype.fromJSON = function (data) {
if (data.metadata !== undefined) {
this.metadata = data.metadata;
}
}; };

View File

@ -22,6 +22,7 @@ var IPython = (function (IPython) {
this.code_mirror = null; this.code_mirror = null;
this.input_prompt_number = null; this.input_prompt_number = null;
this.tooltip_on_tab = true; this.tooltip_on_tab = true;
this.collapsed = false;
IPython.Cell.apply(this, arguments); IPython.Cell.apply(this, arguments);
}; };
@ -200,16 +201,19 @@ var IPython = (function (IPython) {
CodeCell.prototype.collapse = function () { CodeCell.prototype.collapse = function () {
this.collapsed = true;
this.output_area.collapse(); this.output_area.collapse();
}; };
CodeCell.prototype.expand = function () { CodeCell.prototype.expand = function () {
this.collapsed = false;
this.output_area.expand(); this.output_area.expand();
}; };
CodeCell.prototype.toggle_output = function () { CodeCell.prototype.toggle_output = function () {
this.collapsed = Boolean(1 - this.collapsed);
this.output_area.toggle_output(); this.output_area.toggle_output();
}; };
@ -264,6 +268,7 @@ var IPython = (function (IPython) {
// JSON serialization // JSON serialization
CodeCell.prototype.fromJSON = function (data) { CodeCell.prototype.fromJSON = function (data) {
IPython.Cell.prototype.fromJSON.apply(this, arguments);
if (data.cell_type === 'code') { if (data.cell_type === 'code') {
if (data.input !== undefined) { if (data.input !== undefined) {
this.set_text(data.input); this.set_text(data.input);
@ -289,7 +294,7 @@ var IPython = (function (IPython) {
CodeCell.prototype.toJSON = function () { CodeCell.prototype.toJSON = function () {
var data = {}; var data = IPython.Cell.prototype.toJSON.apply(this);
data.input = this.get_text(); data.input = this.get_text();
data.cell_type = 'code'; data.cell_type = 'code';
if (this.input_prompt_number) { if (this.input_prompt_number) {

View File

@ -25,11 +25,14 @@ var IPython = (function (IPython) {
this.paste_enabled = false; this.paste_enabled = false;
this.dirty = false; this.dirty = false;
this.metadata = {}; this.metadata = {};
// single worksheet for now
this.worksheet_metadata = {};
this.control_key_active = false; this.control_key_active = false;
this.notebook_id = null; this.notebook_id = null;
this.notebook_name = null; this.notebook_name = null;
this.notebook_name_blacklist_re = /[\/\\:]/; this.notebook_name_blacklist_re = /[\/\\:]/;
this.nbformat = 3 // Increment this when changing the nbformat this.nbformat = 3 // Increment this when changing the nbformat
this.nbformat_minor = 0 // Increment this when changing the nbformat
this.style(); this.style();
this.create_elements(); this.create_elements();
this.bind_events(); this.bind_events();
@ -1018,6 +1021,9 @@ var IPython = (function (IPython) {
// Only handle 1 worksheet for now. // Only handle 1 worksheet for now.
var worksheet = data.worksheets[0]; var worksheet = data.worksheets[0];
if (worksheet !== undefined) { if (worksheet !== undefined) {
if (worksheet.metadata) {
this.worksheet_metadata = worksheet.metadata;
}
var new_cells = worksheet.cells; var new_cells = worksheet.cells;
ncells = new_cells.length; ncells = new_cells.length;
var cell_data = null; var cell_data = null;
@ -1034,6 +1040,27 @@ var IPython = (function (IPython) {
new_cell.fromJSON(cell_data); new_cell.fromJSON(cell_data);
}; };
}; };
if (data.worksheets.length > 1) {
var dialog = $('<div/>');
dialog.html("This notebook has " + data.worksheets.length + " worksheets, " +
"but this version of IPython can only handle the first. " +
"If you save this notebook, worksheets after the first will be lost."
);
this.element.append(dialog);
dialog.dialog({
resizable: false,
modal: true,
title: "Multiple worksheets",
closeText: "",
close: function(event, ui) {$(this).dialog('destroy').remove();},
buttons : {
"OK": function () {
$(this).dialog('close');
}
},
width: 400
});
}
}; };
@ -1046,7 +1073,10 @@ var IPython = (function (IPython) {
}; };
var data = { var data = {
// Only handle 1 worksheet for now. // Only handle 1 worksheet for now.
worksheets : [{cells:cell_array}], worksheets : [{
cells: cell_array,
metadata: this.worksheet_metadata
}],
metadata : this.metadata metadata : this.metadata
}; };
return data; return data;
@ -1057,6 +1087,7 @@ var IPython = (function (IPython) {
var data = this.toJSON(); var data = this.toJSON();
data.metadata.name = this.notebook_name; data.metadata.name = this.notebook_name;
data.nbformat = this.nbformat; data.nbformat = this.nbformat;
data.nbformat_minor = this.nbformat_minor;
// We do the call with settings so we can set cache to false. // We do the call with settings so we can set cache to false.
var settings = { var settings = {
processData : false, processData : false,
@ -1133,6 +1164,31 @@ var IPython = (function (IPython) {
}, },
width: 400 width: 400
}); });
} else if (data.orig_nbformat_minor !== undefined && data.nbformat_minor !== data.orig_nbformat_minor) {
var that = this;
var orig_vs = 'v' + data.nbformat + '.' + data.orig_nbformat_minor;
var this_vs = 'v' + data.nbformat + '.' + this.nbformat_minor;
msg = "This notebook is version " + orig_vs + ", but we only fully support up to " +
this_vs + ". You can still work with this notebook, but some features " +
"introduced in later notebook versions may not be available."
var dialog = $('<div/>');
dialog.html(msg);
this.element.append(dialog);
dialog.dialog({
resizable: false,
modal: true,
title: "Newer Notebook",
closeText: "",
close: function(event, ui) {$(this).dialog('destroy').remove();},
buttons : {
"OK": function () {
$(this).dialog('close');
}
},
width: 400
});
} }
// Create the kernel after the notebook is completely loaded to prevent // Create the kernel after the notebook is completely loaded to prevent
// code execution upon loading, which is a security risk. // code execution upon loading, which is a security risk.

View File

@ -155,6 +155,7 @@ var IPython = (function (IPython) {
TextCell.prototype.fromJSON = function (data) { TextCell.prototype.fromJSON = function (data) {
IPython.Cell.prototype.fromJSON.apply(this, arguments);
if (data.cell_type === this.cell_type) { if (data.cell_type === this.cell_type) {
if (data.source !== undefined) { if (data.source !== undefined) {
this.set_text(data.source); this.set_text(data.source);
@ -170,7 +171,7 @@ var IPython = (function (IPython) {
TextCell.prototype.toJSON = function () { TextCell.prototype.toJSON = function () {
var data = {}; var data = IPython.Cell.prototype.toJSON.apply(this);
data.cell_type = this.cell_type; data.cell_type = this.cell_type;
data.source = this.get_text(); data.source = this.get_text();
return data; return data;