Show More
@@ -1,84 +1,143 b'' | |||||
1 | //---------------------------------------------------------------------------- |
|
1 | //---------------------------------------------------------------------------- | |
2 | // Copyright (C) 2013 The IPython Development Team |
|
2 | // Copyright (C) 2013 The IPython Development Team | |
3 | // |
|
3 | // | |
4 | // Distributed under the terms of the BSD License. The full license is in |
|
4 | // Distributed under the terms of the BSD License. The full license is in | |
5 | // the file COPYING, distributed as part of this software. |
|
5 | // the file COPYING, distributed as part of this software. | |
6 | //---------------------------------------------------------------------------- |
|
6 | //---------------------------------------------------------------------------- | |
7 |
|
7 | |||
8 | //============================================================================ |
|
8 | //============================================================================ | |
9 | // Utility for modal dialogs with bootstrap |
|
9 | // Utility for modal dialogs with bootstrap | |
10 | //============================================================================ |
|
10 | //============================================================================ | |
11 |
|
11 | |||
12 | IPython.namespace('IPython.dialog'); |
|
12 | IPython.namespace('IPython.dialog'); | |
13 |
|
13 | |||
14 | IPython.dialog = (function (IPython) { |
|
14 | IPython.dialog = (function (IPython) { | |
15 | "use strict"; |
|
15 | "use strict"; | |
16 |
|
16 | |||
17 | var modal = function (options) { |
|
17 | var modal = function (options) { | |
18 | var dialog = $("<div/>").addClass("modal").attr("role", "dialog"); |
|
18 | var dialog = $("<div/>").addClass("modal").attr("role", "dialog"); | |
19 | dialog.append( |
|
19 | dialog.append( | |
20 | $("<div/>") |
|
20 | $("<div/>") | |
21 | .addClass("modal-header") |
|
21 | .addClass("modal-header") | |
22 | .append($("<button>") |
|
22 | .append($("<button>") | |
23 | .addClass("close") |
|
23 | .addClass("close") | |
24 | .attr("data-dismiss", "modal") |
|
24 | .attr("data-dismiss", "modal") | |
25 | .html("×") |
|
25 | .html("×") | |
26 | ).append( |
|
26 | ).append( | |
27 | $("<h3/>").text(options.title || "") |
|
27 | $("<h3/>").text(options.title || "") | |
28 | ) |
|
28 | ) | |
29 | ).append( |
|
29 | ).append( | |
30 | $("<div/>").addClass("modal-body").append( |
|
30 | $("<div/>").addClass("modal-body").append( | |
31 | options.body || $("<p/>") |
|
31 | options.body || $("<p/>") | |
32 | ) |
|
32 | ) | |
33 | ); |
|
33 | ); | |
34 |
|
34 | |||
35 | var footer = $("<div/>").addClass("modal-footer"); |
|
35 | var footer = $("<div/>").addClass("modal-footer"); | |
36 |
|
36 | |||
37 | for (var label in options.buttons) { |
|
37 | for (var label in options.buttons) { | |
38 | var btn_opts = options.buttons[label]; |
|
38 | var btn_opts = options.buttons[label]; | |
39 | var button = $("<button/>") |
|
39 | var button = $("<button/>") | |
40 | .addClass("btn") |
|
40 | .addClass("btn") | |
41 | .attr("data-dismiss", "modal") |
|
41 | .attr("data-dismiss", "modal") | |
42 | .text(label); |
|
42 | .text(label); | |
43 | if (btn_opts.click) { |
|
43 | if (btn_opts.click) { | |
44 | button.click($.proxy(btn_opts.click, dialog)); |
|
44 | button.click($.proxy(btn_opts.click, dialog)); | |
45 | } |
|
45 | } | |
46 | if (btn_opts.class) { |
|
46 | if (btn_opts.class) { | |
47 | button.addClass(btn_opts.class); |
|
47 | button.addClass(btn_opts.class); | |
48 | } |
|
48 | } | |
49 | footer.append(button); |
|
49 | footer.append(button); | |
50 | } |
|
50 | } | |
51 | dialog.append(footer); |
|
51 | dialog.append(footer); | |
52 | // hook up on-open event |
|
52 | // hook up on-open event | |
53 | dialog.on("shown", function() { |
|
53 | dialog.on("shown", function() { | |
54 | setTimeout(function() { |
|
54 | setTimeout(function() { | |
55 | footer.find("button").last().focus(); |
|
55 | footer.find("button").last().focus(); | |
56 | if (options.open) { |
|
56 | if (options.open) { | |
57 | $.proxy(options.open, dialog)(); |
|
57 | $.proxy(options.open, dialog)(); | |
58 | } |
|
58 | } | |
59 | }, 0); |
|
59 | }, 0); | |
60 | }); |
|
60 | }); | |
61 |
|
61 | |||
62 | // destroy dialog on hide, unless explicitly asked not to |
|
62 | // destroy dialog on hide, unless explicitly asked not to | |
63 | if (options.destroy == undefined || options.destroy) { |
|
63 | if (options.destroy === undefined || options.destroy) { | |
64 | dialog.on("hidden", function () { |
|
64 | dialog.on("hidden", function () { | |
65 | dialog.remove(); |
|
65 | dialog.remove(); | |
66 | }); |
|
66 | }); | |
67 | } |
|
67 | } | |
68 | if (options.reselect_cell !== false) { |
|
68 | if (options.reselect_cell !== false) { | |
69 | dialog.on("hidden", function () { |
|
69 | dialog.on("hidden", function () { | |
70 | if (IPython.notebook) { |
|
70 | if (IPython.notebook) { | |
71 | var cell = IPython.notebook.get_selected_cell(); |
|
71 | var cell = IPython.notebook.get_selected_cell(); | |
72 | if (cell) cell.select(); |
|
72 | if (cell) cell.select(); | |
73 | } |
|
73 | } | |
74 | }); |
|
74 | }); | |
75 | } |
|
75 | } | |
76 |
|
76 | |||
77 | return dialog.modal(options); |
|
77 | return dialog.modal(options); | |
|
78 | }; | |||
|
79 | ||||
|
80 | var edit_metadata = function (md, callback, name) { | |||
|
81 | name = name || "Cell"; | |||
|
82 | var error_div = $('<div/>').css('color', 'red'); | |||
|
83 | var message = | |||
|
84 | "Manually edit the JSON below to manipulate the metadata for this " + name + "." + | |||
|
85 | " We recommend putting custom metadata attributes in an appropriately named sub-structure," + | |||
|
86 | " so they don't conflict with those of others."; | |||
|
87 | ||||
|
88 | var textarea = $('<textarea/>') | |||
|
89 | .attr('rows', '13') | |||
|
90 | .attr('cols', '80') | |||
|
91 | .attr('name', 'metadata') | |||
|
92 | .text(JSON.stringify(md || {}, null, 2)); | |||
|
93 | ||||
|
94 | var dialogform = $('<div/>').attr('title', 'Edit the metadata') | |||
|
95 | .append( | |||
|
96 | $('<form/>').append( | |||
|
97 | $('<fieldset/>').append( | |||
|
98 | $('<label/>') | |||
|
99 | .attr('for','metadata') | |||
|
100 | .text(message) | |||
|
101 | ) | |||
|
102 | .append(error_div) | |||
|
103 | .append($('<br/>')) | |||
|
104 | .append(textarea) | |||
|
105 | ) | |||
|
106 | ); | |||
|
107 | var editor = CodeMirror.fromTextArea(textarea[0], { | |||
|
108 | lineNumbers: true, | |||
|
109 | matchBrackets: true, | |||
|
110 | indentUnit: 2, | |||
|
111 | autoIndent: true, | |||
|
112 | mode: 'application/json', | |||
|
113 | }); | |||
|
114 | IPython.dialog.modal({ | |||
|
115 | title: "Edit " + name + " Metadata", | |||
|
116 | body: dialogform, | |||
|
117 | buttons: { | |||
|
118 | OK: { class : "btn-primary", | |||
|
119 | click: function() { | |||
|
120 | // validate json and set it | |||
|
121 | var new_md; | |||
|
122 | try { | |||
|
123 | new_md = JSON.parse(editor.getValue()); | |||
|
124 | } catch(e) { | |||
|
125 | console.log(e); | |||
|
126 | error_div.text('WARNING: Could not save invalid JSON.'); | |||
|
127 | return false; | |||
|
128 | } | |||
|
129 | callback(new_md); | |||
78 | } |
|
130 | } | |
|
131 | }, | |||
|
132 | Cancel: {} | |||
|
133 | } | |||
|
134 | }); | |||
|
135 | editor.refresh(); | |||
|
136 | }; | |||
79 |
|
137 | |||
80 | return { |
|
138 | return { | |
81 | modal : modal, |
|
139 | modal : modal, | |
|
140 | edit_metadata : edit_metadata, | |||
82 | }; |
|
141 | }; | |
83 |
|
142 | |||
84 | }(IPython)); |
|
143 | }(IPython)); |
@@ -1,90 +1,46 b'' | |||||
1 | //---------------------------------------------------------------------------- |
|
1 | //---------------------------------------------------------------------------- | |
2 | // Copyright (C) 2012 The IPython Development Team |
|
2 | // Copyright (C) 2012 The IPython Development Team | |
3 | // |
|
3 | // | |
4 | // Distributed under the terms of the BSD License. The full license is in |
|
4 | // Distributed under the terms of the BSD License. The full license is in | |
5 | // the file COPYING, distributed as part of this software. |
|
5 | // the file COPYING, distributed as part of this software. | |
6 | //---------------------------------------------------------------------------- |
|
6 | //---------------------------------------------------------------------------- | |
7 |
|
7 | |||
8 | //============================================================================ |
|
8 | //============================================================================ | |
9 | // CellToolbar Default |
|
9 | // CellToolbar Default | |
10 | //============================================================================ |
|
10 | //============================================================================ | |
11 |
|
11 | |||
12 | /** |
|
12 | /** | |
13 | * Example Use for the CellToolbar library |
|
13 | * Example Use for the CellToolbar library | |
14 | */ |
|
14 | */ | |
15 | // IIFE without asignement, we don't modifiy the IPython namespace |
|
15 | // IIFE without asignement, we don't modifiy the IPython namespace | |
16 | (function (IPython) { |
|
16 | (function (IPython) { | |
17 | "use strict"; |
|
17 | "use strict"; | |
18 |
|
18 | |||
19 | var CellToolbar = IPython.CellToolbar; |
|
19 | var CellToolbar = IPython.CellToolbar; | |
20 |
|
20 | |||
21 | var raw_edit = function(cell){ |
|
21 | var raw_edit = function(cell){ | |
22 |
|
22 | IPython.dialog.edit_metadata(cell.metadata, function (md) { | ||
23 |
|
|
23 | cell.metadata = md; | |
24 | var error_div = $('<div/>').css('color','red') |
|
|||
25 |
|
||||
26 | var textarea = $('<textarea/>') |
|
|||
27 | .attr('rows','13') |
|
|||
28 | .attr('cols','75') |
|
|||
29 | .attr('name','metadata') |
|
|||
30 | .text(JSON.stringify(md, null,4)||''); |
|
|||
31 | var dialogform = $('<div/>').attr('title','Edit the metadata') |
|
|||
32 | .append( |
|
|||
33 | $('<form/>').append( |
|
|||
34 | $('<fieldset/>').append( |
|
|||
35 | $('<label/>') |
|
|||
36 | .attr('for','metadata') |
|
|||
37 | .text("Manually edit the JSON below to manipulate the metadata for this cell. This assumes you know what you are doing and won't complain if it breaks your notebook. We also recommend putting your metadata attributes in an appropriately named sub-structure, so they don't conflict with those of others.") |
|
|||
38 | ) |
|
|||
39 | .append(error_div) |
|
|||
40 | .append($('<br/>')) |
|
|||
41 | .append( |
|
|||
42 | textarea |
|
|||
43 | ) |
|
|||
44 | ) |
|
|||
45 | ); |
|
|||
46 | var editor = CodeMirror.fromTextArea(textarea[0], { |
|
|||
47 | lineNumbers: true, |
|
|||
48 | matchBrackets: true, |
|
|||
49 | }); |
|
|||
50 | IPython.dialog.modal({ |
|
|||
51 | title: "Edit Cell Metadata", |
|
|||
52 | body: dialogform, |
|
|||
53 | buttons: { |
|
|||
54 | "OK": { class : "btn-primary", |
|
|||
55 | click: function() { |
|
|||
56 | //validate json and set it |
|
|||
57 | try { |
|
|||
58 | var json = JSON.parse(editor.getValue()); |
|
|||
59 | cell.metadata = json; |
|
|||
60 | } catch(e) { |
|
|||
61 | error_div.text('Warning, invalid json, not saved'); |
|
|||
62 | return false; |
|
|||
63 | } |
|
|||
64 | }}, |
|
|||
65 | Cancel: {} |
|
|||
66 | } |
|
|||
67 | }); |
|
24 | }); | |
68 | editor.refresh(); |
|
25 | }; | |
69 | } |
|
|||
70 |
|
26 | |||
71 | var add_raw_edit_button = function(div, cell) { |
|
27 | var add_raw_edit_button = function(div, cell) { | |
72 | var button_container = div; |
|
28 | var button_container = div; | |
73 | var button = $('<button/>') |
|
29 | var button = $('<button/>') | |
74 | .addClass("btn btn-mini") |
|
30 | .addClass("btn btn-mini") | |
75 | .text("Raw Edit") |
|
31 | .text("Raw Edit") | |
76 | .click( function () { |
|
32 | .click( function () { | |
77 | raw_edit(cell); |
|
33 | raw_edit(cell); | |
78 | return false; |
|
34 | return false; | |
79 | }); |
|
35 | }); | |
80 | button_container.append(button); |
|
36 | button_container.append(button); | |
81 | } |
|
37 | }; | |
82 |
|
38 | |||
83 | CellToolbar.register_callback('default.rawedit',add_raw_edit_button); |
|
39 | CellToolbar.register_callback('default.rawedit', add_raw_edit_button); | |
84 | var example_preset = [] |
|
40 | var example_preset = []; | |
85 | example_preset.push('default.rawedit'); |
|
41 | example_preset.push('default.rawedit'); | |
86 |
|
42 | |||
87 | CellToolbar.register_preset('Default',example_preset); |
|
43 | CellToolbar.register_preset('Default', example_preset); | |
88 | console.log('Default extension for metadata editing loaded.'); |
|
44 | console.log('Default extension for metadata editing loaded.'); | |
89 |
|
45 | |||
90 | }(IPython)); |
|
46 | }(IPython)); |
@@ -1,270 +1,274 b'' | |||||
1 | //---------------------------------------------------------------------------- |
|
1 | //---------------------------------------------------------------------------- | |
2 | // Copyright (C) 2008-2011 The IPython Development Team |
|
2 | // Copyright (C) 2008-2011 The IPython Development Team | |
3 | // |
|
3 | // | |
4 | // Distributed under the terms of the BSD License. The full license is in |
|
4 | // Distributed under the terms of the BSD License. The full license is in | |
5 | // the file COPYING, distributed as part of this software. |
|
5 | // the file COPYING, distributed as part of this software. | |
6 | //---------------------------------------------------------------------------- |
|
6 | //---------------------------------------------------------------------------- | |
7 |
|
7 | |||
8 | //============================================================================ |
|
8 | //============================================================================ | |
9 | // MenuBar |
|
9 | // MenuBar | |
10 | //============================================================================ |
|
10 | //============================================================================ | |
11 |
|
11 | |||
12 | /** |
|
12 | /** | |
13 | * @module IPython |
|
13 | * @module IPython | |
14 | * @namespace IPython |
|
14 | * @namespace IPython | |
15 | * @submodule MenuBar |
|
15 | * @submodule MenuBar | |
16 | */ |
|
16 | */ | |
17 |
|
17 | |||
18 |
|
18 | |||
19 | var IPython = (function (IPython) { |
|
19 | var IPython = (function (IPython) { | |
20 | "use strict"; |
|
20 | "use strict"; | |
21 |
|
21 | |||
22 | /** |
|
22 | /** | |
23 | * A MenuBar Class to generate the menubar of IPython noteboko |
|
23 | * A MenuBar Class to generate the menubar of IPython noteboko | |
24 | * @Class MenuBar |
|
24 | * @Class MenuBar | |
25 | * |
|
25 | * | |
26 | * @constructor |
|
26 | * @constructor | |
27 | * |
|
27 | * | |
28 | * |
|
28 | * | |
29 | * @param selector {string} selector for the menubar element in DOM |
|
29 | * @param selector {string} selector for the menubar element in DOM | |
30 | * @param {object} [options] |
|
30 | * @param {object} [options] | |
31 | * @param [options.baseProjectUrl] {String} String to use for the |
|
31 | * @param [options.baseProjectUrl] {String} String to use for the | |
32 | * Base Project url, default would be to inspect |
|
32 | * Base Project url, default would be to inspect | |
33 | * $('body').data('baseProjectUrl'); |
|
33 | * $('body').data('baseProjectUrl'); | |
34 | * does not support change for now is set through this option |
|
34 | * does not support change for now is set through this option | |
35 | */ |
|
35 | */ | |
36 | var MenuBar = function (selector, options) { |
|
36 | var MenuBar = function (selector, options) { | |
37 | var options = options || {}; |
|
37 | var options = options || {}; | |
38 | if(options.baseProjectUrl!= undefined){ |
|
38 | if(options.baseProjectUrl!= undefined){ | |
39 | this._baseProjectUrl = options.baseProjectUrl; |
|
39 | this._baseProjectUrl = options.baseProjectUrl; | |
40 | } |
|
40 | } | |
41 | this.selector = selector; |
|
41 | this.selector = selector; | |
42 | if (this.selector !== undefined) { |
|
42 | if (this.selector !== undefined) { | |
43 | this.element = $(selector); |
|
43 | this.element = $(selector); | |
44 | this.style(); |
|
44 | this.style(); | |
45 | this.bind_events(); |
|
45 | this.bind_events(); | |
46 | } |
|
46 | } | |
47 | }; |
|
47 | }; | |
48 |
|
48 | |||
49 | MenuBar.prototype.baseProjectUrl = function(){ |
|
49 | MenuBar.prototype.baseProjectUrl = function(){ | |
50 | return this._baseProjectUrl || $('body').data('baseProjectUrl'); |
|
50 | return this._baseProjectUrl || $('body').data('baseProjectUrl'); | |
51 | }; |
|
51 | }; | |
52 |
|
52 | |||
53 |
|
53 | |||
54 | MenuBar.prototype.style = function () { |
|
54 | MenuBar.prototype.style = function () { | |
55 | this.element.addClass('border-box-sizing'); |
|
55 | this.element.addClass('border-box-sizing'); | |
56 | this.element.find("li").click(function (event, ui) { |
|
56 | this.element.find("li").click(function (event, ui) { | |
57 | // The selected cell loses focus when the menu is entered, so we |
|
57 | // The selected cell loses focus when the menu is entered, so we | |
58 | // re-select it upon selection. |
|
58 | // re-select it upon selection. | |
59 | var i = IPython.notebook.get_selected_index(); |
|
59 | var i = IPython.notebook.get_selected_index(); | |
60 | IPython.notebook.select(i); |
|
60 | IPython.notebook.select(i); | |
61 | } |
|
61 | } | |
62 | ); |
|
62 | ); | |
63 | }; |
|
63 | }; | |
64 |
|
64 | |||
65 |
|
65 | |||
66 | MenuBar.prototype.bind_events = function () { |
|
66 | MenuBar.prototype.bind_events = function () { | |
67 | // File |
|
67 | // File | |
68 | var that = this; |
|
68 | var that = this; | |
69 | this.element.find('#new_notebook').click(function () { |
|
69 | this.element.find('#new_notebook').click(function () { | |
70 | window.open(that.baseProjectUrl()+'new'); |
|
70 | window.open(that.baseProjectUrl()+'new'); | |
71 | }); |
|
71 | }); | |
72 | this.element.find('#open_notebook').click(function () { |
|
72 | this.element.find('#open_notebook').click(function () { | |
73 | window.open(that.baseProjectUrl()); |
|
73 | window.open(that.baseProjectUrl()); | |
74 | }); |
|
74 | }); | |
75 | this.element.find('#rename_notebook').click(function () { |
|
75 | this.element.find('#rename_notebook').click(function () { | |
76 | IPython.save_widget.rename_notebook(); |
|
76 | IPython.save_widget.rename_notebook(); | |
77 | }); |
|
77 | }); | |
78 | this.element.find('#copy_notebook').click(function () { |
|
78 | this.element.find('#copy_notebook').click(function () { | |
79 | var notebook_id = IPython.notebook.get_notebook_id(); |
|
79 | var notebook_id = IPython.notebook.get_notebook_id(); | |
80 | var url = that.baseProjectUrl() + notebook_id + '/copy'; |
|
80 | var url = that.baseProjectUrl() + notebook_id + '/copy'; | |
81 | window.open(url,'_blank'); |
|
81 | window.open(url,'_blank'); | |
82 | return false; |
|
82 | return false; | |
83 | }); |
|
83 | }); | |
84 | this.element.find('#save_checkpoint').click(function () { |
|
84 | this.element.find('#save_checkpoint').click(function () { | |
85 | IPython.notebook.save_checkpoint(); |
|
85 | IPython.notebook.save_checkpoint(); | |
86 | }); |
|
86 | }); | |
87 | this.element.find('#restore_checkpoint').click(function () { |
|
87 | this.element.find('#restore_checkpoint').click(function () { | |
88 | }); |
|
88 | }); | |
89 | this.element.find('#download_ipynb').click(function () { |
|
89 | this.element.find('#download_ipynb').click(function () { | |
90 | var notebook_id = IPython.notebook.get_notebook_id(); |
|
90 | var notebook_id = IPython.notebook.get_notebook_id(); | |
91 | var url = that.baseProjectUrl() + 'notebooks/' + |
|
91 | var url = that.baseProjectUrl() + 'notebooks/' + | |
92 | notebook_id + '?format=json'; |
|
92 | notebook_id + '?format=json'; | |
93 | window.location.assign(url); |
|
93 | window.location.assign(url); | |
94 | }); |
|
94 | }); | |
95 | this.element.find('#download_py').click(function () { |
|
95 | this.element.find('#download_py').click(function () { | |
96 | var notebook_id = IPython.notebook.get_notebook_id(); |
|
96 | var notebook_id = IPython.notebook.get_notebook_id(); | |
97 | var url = that.baseProjectUrl() + 'notebooks/' + |
|
97 | var url = that.baseProjectUrl() + 'notebooks/' + | |
98 | notebook_id + '?format=py'; |
|
98 | notebook_id + '?format=py'; | |
99 | window.location.assign(url); |
|
99 | window.location.assign(url); | |
100 | }); |
|
100 | }); | |
101 | this.element.find('#kill_and_exit').click(function () { |
|
101 | this.element.find('#kill_and_exit').click(function () { | |
102 | IPython.notebook.kernel.kill(); |
|
102 | IPython.notebook.kernel.kill(); | |
103 | setTimeout(function(){window.close();}, 200); |
|
103 | setTimeout(function(){window.close();}, 200); | |
104 | }); |
|
104 | }); | |
105 | // Edit |
|
105 | // Edit | |
106 | this.element.find('#cut_cell').click(function () { |
|
106 | this.element.find('#cut_cell').click(function () { | |
107 | IPython.notebook.cut_cell(); |
|
107 | IPython.notebook.cut_cell(); | |
108 | }); |
|
108 | }); | |
109 | this.element.find('#copy_cell').click(function () { |
|
109 | this.element.find('#copy_cell').click(function () { | |
110 | IPython.notebook.copy_cell(); |
|
110 | IPython.notebook.copy_cell(); | |
111 | }); |
|
111 | }); | |
112 | this.element.find('#delete_cell').click(function () { |
|
112 | this.element.find('#delete_cell').click(function () { | |
113 | IPython.notebook.delete_cell(); |
|
113 | IPython.notebook.delete_cell(); | |
114 | }); |
|
114 | }); | |
115 | this.element.find('#undelete_cell').click(function () { |
|
115 | this.element.find('#undelete_cell').click(function () { | |
116 | IPython.notebook.undelete(); |
|
116 | IPython.notebook.undelete(); | |
117 | }); |
|
117 | }); | |
118 | this.element.find('#split_cell').click(function () { |
|
118 | this.element.find('#split_cell').click(function () { | |
119 | IPython.notebook.split_cell(); |
|
119 | IPython.notebook.split_cell(); | |
120 | }); |
|
120 | }); | |
121 | this.element.find('#merge_cell_above').click(function () { |
|
121 | this.element.find('#merge_cell_above').click(function () { | |
122 | IPython.notebook.merge_cell_above(); |
|
122 | IPython.notebook.merge_cell_above(); | |
123 | }); |
|
123 | }); | |
124 | this.element.find('#merge_cell_below').click(function () { |
|
124 | this.element.find('#merge_cell_below').click(function () { | |
125 | IPython.notebook.merge_cell_below(); |
|
125 | IPython.notebook.merge_cell_below(); | |
126 | }); |
|
126 | }); | |
127 | this.element.find('#move_cell_up').click(function () { |
|
127 | this.element.find('#move_cell_up').click(function () { | |
128 | IPython.notebook.move_cell_up(); |
|
128 | IPython.notebook.move_cell_up(); | |
129 | }); |
|
129 | }); | |
130 | this.element.find('#move_cell_down').click(function () { |
|
130 | this.element.find('#move_cell_down').click(function () { | |
131 | IPython.notebook.move_cell_down(); |
|
131 | IPython.notebook.move_cell_down(); | |
132 | }); |
|
132 | }); | |
133 | this.element.find('#select_previous').click(function () { |
|
133 | this.element.find('#select_previous').click(function () { | |
134 | IPython.notebook.select_prev(); |
|
134 | IPython.notebook.select_prev(); | |
135 | }); |
|
135 | }); | |
136 | this.element.find('#select_next').click(function () { |
|
136 | this.element.find('#select_next').click(function () { | |
137 | IPython.notebook.select_next(); |
|
137 | IPython.notebook.select_next(); | |
138 | }); |
|
138 | }); | |
|
139 | this.element.find('#edit_nb_metadata').click(function () { | |||
|
140 | IPython.notebook.edit_metadata(); | |||
|
141 | }); | |||
|
142 | ||||
139 | // View |
|
143 | // View | |
140 | this.element.find('#toggle_header').click(function () { |
|
144 | this.element.find('#toggle_header').click(function () { | |
141 | $('div#header').toggle(); |
|
145 | $('div#header').toggle(); | |
142 | IPython.layout_manager.do_resize(); |
|
146 | IPython.layout_manager.do_resize(); | |
143 | }); |
|
147 | }); | |
144 | this.element.find('#toggle_toolbar').click(function () { |
|
148 | this.element.find('#toggle_toolbar').click(function () { | |
145 | $('div#maintoolbar').toggle(); |
|
149 | $('div#maintoolbar').toggle(); | |
146 | IPython.layout_manager.do_resize(); |
|
150 | IPython.layout_manager.do_resize(); | |
147 | }); |
|
151 | }); | |
148 | // Insert |
|
152 | // Insert | |
149 | this.element.find('#insert_cell_above').click(function () { |
|
153 | this.element.find('#insert_cell_above').click(function () { | |
150 | IPython.notebook.insert_cell_above('code'); |
|
154 | IPython.notebook.insert_cell_above('code'); | |
151 | }); |
|
155 | }); | |
152 | this.element.find('#insert_cell_below').click(function () { |
|
156 | this.element.find('#insert_cell_below').click(function () { | |
153 | IPython.notebook.insert_cell_below('code'); |
|
157 | IPython.notebook.insert_cell_below('code'); | |
154 | }); |
|
158 | }); | |
155 | // Cell |
|
159 | // Cell | |
156 | this.element.find('#run_cell').click(function () { |
|
160 | this.element.find('#run_cell').click(function () { | |
157 | IPython.notebook.execute_selected_cell(); |
|
161 | IPython.notebook.execute_selected_cell(); | |
158 | }); |
|
162 | }); | |
159 | this.element.find('#run_cell_in_place').click(function () { |
|
163 | this.element.find('#run_cell_in_place').click(function () { | |
160 | IPython.notebook.execute_selected_cell({terminal:true}); |
|
164 | IPython.notebook.execute_selected_cell({terminal:true}); | |
161 | }); |
|
165 | }); | |
162 | this.element.find('#run_all_cells').click(function () { |
|
166 | this.element.find('#run_all_cells').click(function () { | |
163 | IPython.notebook.execute_all_cells(); |
|
167 | IPython.notebook.execute_all_cells(); | |
164 | }).attr('title', 'Run all cells in the notebook'); |
|
168 | }).attr('title', 'Run all cells in the notebook'); | |
165 | this.element.find('#run_all_cells_above').click(function () { |
|
169 | this.element.find('#run_all_cells_above').click(function () { | |
166 | IPython.notebook.execute_cells_above(); |
|
170 | IPython.notebook.execute_cells_above(); | |
167 | }).attr('title', 'Run all cells above (but not including) this cell'); |
|
171 | }).attr('title', 'Run all cells above (but not including) this cell'); | |
168 | this.element.find('#run_all_cells_below').click(function () { |
|
172 | this.element.find('#run_all_cells_below').click(function () { | |
169 | IPython.notebook.execute_cells_below(); |
|
173 | IPython.notebook.execute_cells_below(); | |
170 | }).attr('title', 'Run this cell and all cells below it'); |
|
174 | }).attr('title', 'Run this cell and all cells below it'); | |
171 | this.element.find('#to_code').click(function () { |
|
175 | this.element.find('#to_code').click(function () { | |
172 | IPython.notebook.to_code(); |
|
176 | IPython.notebook.to_code(); | |
173 | }); |
|
177 | }); | |
174 | this.element.find('#to_markdown').click(function () { |
|
178 | this.element.find('#to_markdown').click(function () { | |
175 | IPython.notebook.to_markdown(); |
|
179 | IPython.notebook.to_markdown(); | |
176 | }); |
|
180 | }); | |
177 | this.element.find('#to_raw').click(function () { |
|
181 | this.element.find('#to_raw').click(function () { | |
178 | IPython.notebook.to_raw(); |
|
182 | IPython.notebook.to_raw(); | |
179 | }); |
|
183 | }); | |
180 | this.element.find('#to_heading1').click(function () { |
|
184 | this.element.find('#to_heading1').click(function () { | |
181 | IPython.notebook.to_heading(undefined, 1); |
|
185 | IPython.notebook.to_heading(undefined, 1); | |
182 | }); |
|
186 | }); | |
183 | this.element.find('#to_heading2').click(function () { |
|
187 | this.element.find('#to_heading2').click(function () { | |
184 | IPython.notebook.to_heading(undefined, 2); |
|
188 | IPython.notebook.to_heading(undefined, 2); | |
185 | }); |
|
189 | }); | |
186 | this.element.find('#to_heading3').click(function () { |
|
190 | this.element.find('#to_heading3').click(function () { | |
187 | IPython.notebook.to_heading(undefined, 3); |
|
191 | IPython.notebook.to_heading(undefined, 3); | |
188 | }); |
|
192 | }); | |
189 | this.element.find('#to_heading4').click(function () { |
|
193 | this.element.find('#to_heading4').click(function () { | |
190 | IPython.notebook.to_heading(undefined, 4); |
|
194 | IPython.notebook.to_heading(undefined, 4); | |
191 | }); |
|
195 | }); | |
192 | this.element.find('#to_heading5').click(function () { |
|
196 | this.element.find('#to_heading5').click(function () { | |
193 | IPython.notebook.to_heading(undefined, 5); |
|
197 | IPython.notebook.to_heading(undefined, 5); | |
194 | }); |
|
198 | }); | |
195 | this.element.find('#to_heading6').click(function () { |
|
199 | this.element.find('#to_heading6').click(function () { | |
196 | IPython.notebook.to_heading(undefined, 6); |
|
200 | IPython.notebook.to_heading(undefined, 6); | |
197 | }); |
|
201 | }); | |
198 | this.element.find('#toggle_output').click(function () { |
|
202 | this.element.find('#toggle_output').click(function () { | |
199 | IPython.notebook.toggle_output(); |
|
203 | IPython.notebook.toggle_output(); | |
200 | }); |
|
204 | }); | |
201 | this.element.find('#collapse_all_output').click(function () { |
|
205 | this.element.find('#collapse_all_output').click(function () { | |
202 | IPython.notebook.collapse_all_output(); |
|
206 | IPython.notebook.collapse_all_output(); | |
203 | }); |
|
207 | }); | |
204 | this.element.find('#scroll_all_output').click(function () { |
|
208 | this.element.find('#scroll_all_output').click(function () { | |
205 | IPython.notebook.scroll_all_output(); |
|
209 | IPython.notebook.scroll_all_output(); | |
206 | }); |
|
210 | }); | |
207 | this.element.find('#expand_all_output').click(function () { |
|
211 | this.element.find('#expand_all_output').click(function () { | |
208 | IPython.notebook.expand_all_output(); |
|
212 | IPython.notebook.expand_all_output(); | |
209 | }); |
|
213 | }); | |
210 | this.element.find('#clear_all_output').click(function () { |
|
214 | this.element.find('#clear_all_output').click(function () { | |
211 | IPython.notebook.clear_all_output(); |
|
215 | IPython.notebook.clear_all_output(); | |
212 | }); |
|
216 | }); | |
213 | // Kernel |
|
217 | // Kernel | |
214 | this.element.find('#int_kernel').click(function () { |
|
218 | this.element.find('#int_kernel').click(function () { | |
215 | IPython.notebook.kernel.interrupt(); |
|
219 | IPython.notebook.kernel.interrupt(); | |
216 | }); |
|
220 | }); | |
217 | this.element.find('#restart_kernel').click(function () { |
|
221 | this.element.find('#restart_kernel').click(function () { | |
218 | IPython.notebook.restart_kernel(); |
|
222 | IPython.notebook.restart_kernel(); | |
219 | }); |
|
223 | }); | |
220 | // Help |
|
224 | // Help | |
221 | this.element.find('#keyboard_shortcuts').click(function () { |
|
225 | this.element.find('#keyboard_shortcuts').click(function () { | |
222 | IPython.quick_help.show_keyboard_shortcuts(); |
|
226 | IPython.quick_help.show_keyboard_shortcuts(); | |
223 | }); |
|
227 | }); | |
224 |
|
228 | |||
225 | this.update_restore_checkpoint(null); |
|
229 | this.update_restore_checkpoint(null); | |
226 |
|
230 | |||
227 | $([IPython.events]).on('checkpoints_listed.Notebook', function (event, data) { |
|
231 | $([IPython.events]).on('checkpoints_listed.Notebook', function (event, data) { | |
228 | that.update_restore_checkpoint(IPython.notebook.checkpoints); |
|
232 | that.update_restore_checkpoint(IPython.notebook.checkpoints); | |
229 | }); |
|
233 | }); | |
230 |
|
234 | |||
231 | $([IPython.events]).on('checkpoint_created.Notebook', function (event, data) { |
|
235 | $([IPython.events]).on('checkpoint_created.Notebook', function (event, data) { | |
232 | that.update_restore_checkpoint(IPython.notebook.checkpoints); |
|
236 | that.update_restore_checkpoint(IPython.notebook.checkpoints); | |
233 | }); |
|
237 | }); | |
234 | }; |
|
238 | }; | |
235 |
|
239 | |||
236 | MenuBar.prototype.update_restore_checkpoint = function(checkpoints) { |
|
240 | MenuBar.prototype.update_restore_checkpoint = function(checkpoints) { | |
237 | var ul = this.element.find("#restore_checkpoint").find("ul"); |
|
241 | var ul = this.element.find("#restore_checkpoint").find("ul"); | |
238 | ul.empty(); |
|
242 | ul.empty(); | |
239 | if (! checkpoints || checkpoints.length == 0) { |
|
243 | if (! checkpoints || checkpoints.length == 0) { | |
240 | ul.append( |
|
244 | ul.append( | |
241 | $("<li/>") |
|
245 | $("<li/>") | |
242 | .addClass("disabled") |
|
246 | .addClass("disabled") | |
243 | .append( |
|
247 | .append( | |
244 | $("<a/>") |
|
248 | $("<a/>") | |
245 | .text("No checkpoints") |
|
249 | .text("No checkpoints") | |
246 | ) |
|
250 | ) | |
247 | ); |
|
251 | ); | |
248 | return; |
|
252 | return; | |
249 | }; |
|
253 | }; | |
250 |
|
254 | |||
251 | checkpoints.map(function (checkpoint) { |
|
255 | checkpoints.map(function (checkpoint) { | |
252 | var d = new Date(checkpoint.last_modified); |
|
256 | var d = new Date(checkpoint.last_modified); | |
253 | ul.append( |
|
257 | ul.append( | |
254 | $("<li/>").append( |
|
258 | $("<li/>").append( | |
255 | $("<a/>") |
|
259 | $("<a/>") | |
256 | .attr("href", "#") |
|
260 | .attr("href", "#") | |
257 | .text(d.format("mmm dd HH:MM:ss")) |
|
261 | .text(d.format("mmm dd HH:MM:ss")) | |
258 | .click(function () { |
|
262 | .click(function () { | |
259 | IPython.notebook.restore_checkpoint_dialog(checkpoint); |
|
263 | IPython.notebook.restore_checkpoint_dialog(checkpoint); | |
260 | }) |
|
264 | }) | |
261 | ) |
|
265 | ) | |
262 | ); |
|
266 | ); | |
263 | }); |
|
267 | }); | |
264 | }; |
|
268 | }; | |
265 |
|
269 | |||
266 | IPython.MenuBar = MenuBar; |
|
270 | IPython.MenuBar = MenuBar; | |
267 |
|
271 | |||
268 | return IPython; |
|
272 | return IPython; | |
269 |
|
273 | |||
270 | }(IPython)); |
|
274 | }(IPython)); |
@@ -1,2077 +1,2085 b'' | |||||
1 | //---------------------------------------------------------------------------- |
|
1 | //---------------------------------------------------------------------------- | |
2 | // Copyright (C) 2008-2011 The IPython Development Team |
|
2 | // Copyright (C) 2008-2011 The IPython Development Team | |
3 | // |
|
3 | // | |
4 | // Distributed under the terms of the BSD License. The full license is in |
|
4 | // Distributed under the terms of the BSD License. The full license is in | |
5 | // the file COPYING, distributed as part of this software. |
|
5 | // the file COPYING, distributed as part of this software. | |
6 | //---------------------------------------------------------------------------- |
|
6 | //---------------------------------------------------------------------------- | |
7 |
|
7 | |||
8 | //============================================================================ |
|
8 | //============================================================================ | |
9 | // Notebook |
|
9 | // Notebook | |
10 | //============================================================================ |
|
10 | //============================================================================ | |
11 |
|
11 | |||
12 | var IPython = (function (IPython) { |
|
12 | var IPython = (function (IPython) { | |
13 | "use strict"; |
|
13 | "use strict"; | |
14 |
|
14 | |||
15 | var utils = IPython.utils; |
|
15 | var utils = IPython.utils; | |
16 | var key = IPython.utils.keycodes; |
|
16 | var key = IPython.utils.keycodes; | |
17 |
|
17 | |||
18 | /** |
|
18 | /** | |
19 | * A notebook contains and manages cells. |
|
19 | * A notebook contains and manages cells. | |
20 | * |
|
20 | * | |
21 | * @class Notebook |
|
21 | * @class Notebook | |
22 | * @constructor |
|
22 | * @constructor | |
23 | * @param {String} selector A jQuery selector for the notebook's DOM element |
|
23 | * @param {String} selector A jQuery selector for the notebook's DOM element | |
24 | * @param {Object} [options] A config object |
|
24 | * @param {Object} [options] A config object | |
25 | */ |
|
25 | */ | |
26 | var Notebook = function (selector, options) { |
|
26 | var Notebook = function (selector, options) { | |
27 | var options = options || {}; |
|
27 | var options = options || {}; | |
28 | this._baseProjectUrl = options.baseProjectUrl; |
|
28 | this._baseProjectUrl = options.baseProjectUrl; | |
29 |
|
29 | |||
30 | this.element = $(selector); |
|
30 | this.element = $(selector); | |
31 | this.element.scroll(); |
|
31 | this.element.scroll(); | |
32 | this.element.data("notebook", this); |
|
32 | this.element.data("notebook", this); | |
33 | this.next_prompt_number = 1; |
|
33 | this.next_prompt_number = 1; | |
34 | this.kernel = null; |
|
34 | this.kernel = null; | |
35 | this.clipboard = null; |
|
35 | this.clipboard = null; | |
36 | this.undelete_backup = null; |
|
36 | this.undelete_backup = null; | |
37 | this.undelete_index = null; |
|
37 | this.undelete_index = null; | |
38 | this.undelete_below = false; |
|
38 | this.undelete_below = false; | |
39 | this.paste_enabled = false; |
|
39 | this.paste_enabled = false; | |
40 | this.set_dirty(false); |
|
40 | this.set_dirty(false); | |
41 | this.metadata = {}; |
|
41 | this.metadata = {}; | |
42 | this._checkpoint_after_save = false; |
|
42 | this._checkpoint_after_save = false; | |
43 | this.last_checkpoint = null; |
|
43 | this.last_checkpoint = null; | |
44 | this.checkpoints = []; |
|
44 | this.checkpoints = []; | |
45 | this.autosave_interval = 0; |
|
45 | this.autosave_interval = 0; | |
46 | this.autosave_timer = null; |
|
46 | this.autosave_timer = null; | |
47 | // autosave *at most* every two minutes |
|
47 | // autosave *at most* every two minutes | |
48 | this.minimum_autosave_interval = 120000; |
|
48 | this.minimum_autosave_interval = 120000; | |
49 | // single worksheet for now |
|
49 | // single worksheet for now | |
50 | this.worksheet_metadata = {}; |
|
50 | this.worksheet_metadata = {}; | |
51 | this.control_key_active = false; |
|
51 | this.control_key_active = false; | |
52 | this.notebook_id = null; |
|
52 | this.notebook_id = null; | |
53 | this.notebook_name = null; |
|
53 | this.notebook_name = null; | |
54 | this.notebook_name_blacklist_re = /[\/\\:]/; |
|
54 | this.notebook_name_blacklist_re = /[\/\\:]/; | |
55 | this.nbformat = 3 // Increment this when changing the nbformat |
|
55 | this.nbformat = 3 // Increment this when changing the nbformat | |
56 | this.nbformat_minor = 0 // Increment this when changing the nbformat |
|
56 | this.nbformat_minor = 0 // Increment this when changing the nbformat | |
57 | this.style(); |
|
57 | this.style(); | |
58 | this.create_elements(); |
|
58 | this.create_elements(); | |
59 | this.bind_events(); |
|
59 | this.bind_events(); | |
60 | }; |
|
60 | }; | |
61 |
|
61 | |||
62 | /** |
|
62 | /** | |
63 | * Tweak the notebook's CSS style. |
|
63 | * Tweak the notebook's CSS style. | |
64 | * |
|
64 | * | |
65 | * @method style |
|
65 | * @method style | |
66 | */ |
|
66 | */ | |
67 | Notebook.prototype.style = function () { |
|
67 | Notebook.prototype.style = function () { | |
68 | $('div#notebook').addClass('border-box-sizing'); |
|
68 | $('div#notebook').addClass('border-box-sizing'); | |
69 | }; |
|
69 | }; | |
70 |
|
70 | |||
71 | /** |
|
71 | /** | |
72 | * Get the root URL of the notebook server. |
|
72 | * Get the root URL of the notebook server. | |
73 | * |
|
73 | * | |
74 | * @method baseProjectUrl |
|
74 | * @method baseProjectUrl | |
75 | * @return {String} The base project URL |
|
75 | * @return {String} The base project URL | |
76 | */ |
|
76 | */ | |
77 | Notebook.prototype.baseProjectUrl = function(){ |
|
77 | Notebook.prototype.baseProjectUrl = function(){ | |
78 | return this._baseProjectUrl || $('body').data('baseProjectUrl'); |
|
78 | return this._baseProjectUrl || $('body').data('baseProjectUrl'); | |
79 | }; |
|
79 | }; | |
80 |
|
80 | |||
81 | /** |
|
81 | /** | |
82 | * Create an HTML and CSS representation of the notebook. |
|
82 | * Create an HTML and CSS representation of the notebook. | |
83 | * |
|
83 | * | |
84 | * @method create_elements |
|
84 | * @method create_elements | |
85 | */ |
|
85 | */ | |
86 | Notebook.prototype.create_elements = function () { |
|
86 | Notebook.prototype.create_elements = function () { | |
87 | // We add this end_space div to the end of the notebook div to: |
|
87 | // We add this end_space div to the end of the notebook div to: | |
88 | // i) provide a margin between the last cell and the end of the notebook |
|
88 | // i) provide a margin between the last cell and the end of the notebook | |
89 | // ii) to prevent the div from scrolling up when the last cell is being |
|
89 | // ii) to prevent the div from scrolling up when the last cell is being | |
90 | // edited, but is too low on the page, which browsers will do automatically. |
|
90 | // edited, but is too low on the page, which browsers will do automatically. | |
91 | var that = this; |
|
91 | var that = this; | |
92 | this.container = $("<div/>").addClass("container").attr("id", "notebook-container"); |
|
92 | this.container = $("<div/>").addClass("container").attr("id", "notebook-container"); | |
93 | var end_space = $('<div/>').addClass('end_space'); |
|
93 | var end_space = $('<div/>').addClass('end_space'); | |
94 | end_space.dblclick(function (e) { |
|
94 | end_space.dblclick(function (e) { | |
95 | var ncells = that.ncells(); |
|
95 | var ncells = that.ncells(); | |
96 | that.insert_cell_below('code',ncells-1); |
|
96 | that.insert_cell_below('code',ncells-1); | |
97 | }); |
|
97 | }); | |
98 | this.element.append(this.container); |
|
98 | this.element.append(this.container); | |
99 | this.container.append(end_space); |
|
99 | this.container.append(end_space); | |
100 | $('div#notebook').addClass('border-box-sizing'); |
|
100 | $('div#notebook').addClass('border-box-sizing'); | |
101 | }; |
|
101 | }; | |
102 |
|
102 | |||
103 | /** |
|
103 | /** | |
104 | * Bind JavaScript events: key presses and custom IPython events. |
|
104 | * Bind JavaScript events: key presses and custom IPython events. | |
105 | * |
|
105 | * | |
106 | * @method bind_events |
|
106 | * @method bind_events | |
107 | */ |
|
107 | */ | |
108 | Notebook.prototype.bind_events = function () { |
|
108 | Notebook.prototype.bind_events = function () { | |
109 | var that = this; |
|
109 | var that = this; | |
110 |
|
110 | |||
111 | $([IPython.events]).on('set_next_input.Notebook', function (event, data) { |
|
111 | $([IPython.events]).on('set_next_input.Notebook', function (event, data) { | |
112 | var index = that.find_cell_index(data.cell); |
|
112 | var index = that.find_cell_index(data.cell); | |
113 | var new_cell = that.insert_cell_below('code',index); |
|
113 | var new_cell = that.insert_cell_below('code',index); | |
114 | new_cell.set_text(data.text); |
|
114 | new_cell.set_text(data.text); | |
115 | that.dirty = true; |
|
115 | that.dirty = true; | |
116 | }); |
|
116 | }); | |
117 |
|
117 | |||
118 | $([IPython.events]).on('set_dirty.Notebook', function (event, data) { |
|
118 | $([IPython.events]).on('set_dirty.Notebook', function (event, data) { | |
119 | that.dirty = data.value; |
|
119 | that.dirty = data.value; | |
120 | }); |
|
120 | }); | |
121 |
|
121 | |||
122 | $([IPython.events]).on('select.Cell', function (event, data) { |
|
122 | $([IPython.events]).on('select.Cell', function (event, data) { | |
123 | var index = that.find_cell_index(data.cell); |
|
123 | var index = that.find_cell_index(data.cell); | |
124 | that.select(index); |
|
124 | that.select(index); | |
125 | }); |
|
125 | }); | |
126 |
|
126 | |||
127 | $([IPython.events]).on('status_autorestarting.Kernel', function () { |
|
127 | $([IPython.events]).on('status_autorestarting.Kernel', function () { | |
128 | IPython.dialog.modal({ |
|
128 | IPython.dialog.modal({ | |
129 | title: "Kernel Restarting", |
|
129 | title: "Kernel Restarting", | |
130 | body: "The kernel appears to have died. It will restart automatically.", |
|
130 | body: "The kernel appears to have died. It will restart automatically.", | |
131 | buttons: { |
|
131 | buttons: { | |
132 | OK : { |
|
132 | OK : { | |
133 | class : "btn-primary" |
|
133 | class : "btn-primary" | |
134 | } |
|
134 | } | |
135 | } |
|
135 | } | |
136 | }); |
|
136 | }); | |
137 | }); |
|
137 | }); | |
138 |
|
138 | |||
139 |
|
139 | |||
140 | $(document).keydown(function (event) { |
|
140 | $(document).keydown(function (event) { | |
141 |
|
141 | |||
142 | // Save (CTRL+S) or (AppleKey+S) |
|
142 | // Save (CTRL+S) or (AppleKey+S) | |
143 | //metaKey = applekey on mac |
|
143 | //metaKey = applekey on mac | |
144 | if ((event.ctrlKey || event.metaKey) && event.keyCode==83) { |
|
144 | if ((event.ctrlKey || event.metaKey) && event.keyCode==83) { | |
145 | that.save_checkpoint(); |
|
145 | that.save_checkpoint(); | |
146 | event.preventDefault(); |
|
146 | event.preventDefault(); | |
147 | return false; |
|
147 | return false; | |
148 | } else if (event.which === key.ESC) { |
|
148 | } else if (event.which === key.ESC) { | |
149 | // Intercept escape at highest level to avoid closing |
|
149 | // Intercept escape at highest level to avoid closing | |
150 | // websocket connection with firefox |
|
150 | // websocket connection with firefox | |
151 | IPython.pager.collapse(); |
|
151 | IPython.pager.collapse(); | |
152 | event.preventDefault(); |
|
152 | event.preventDefault(); | |
153 | } else if (event.which === key.SHIFT) { |
|
153 | } else if (event.which === key.SHIFT) { | |
154 | // ignore shift keydown |
|
154 | // ignore shift keydown | |
155 | return true; |
|
155 | return true; | |
156 | } |
|
156 | } | |
157 | if (event.which === key.UPARROW && !event.shiftKey) { |
|
157 | if (event.which === key.UPARROW && !event.shiftKey) { | |
158 | var cell = that.get_selected_cell(); |
|
158 | var cell = that.get_selected_cell(); | |
159 | if (cell && cell.at_top()) { |
|
159 | if (cell && cell.at_top()) { | |
160 | event.preventDefault(); |
|
160 | event.preventDefault(); | |
161 | that.select_prev(); |
|
161 | that.select_prev(); | |
162 | }; |
|
162 | }; | |
163 | } else if (event.which === key.DOWNARROW && !event.shiftKey) { |
|
163 | } else if (event.which === key.DOWNARROW && !event.shiftKey) { | |
164 | var cell = that.get_selected_cell(); |
|
164 | var cell = that.get_selected_cell(); | |
165 | if (cell && cell.at_bottom()) { |
|
165 | if (cell && cell.at_bottom()) { | |
166 | event.preventDefault(); |
|
166 | event.preventDefault(); | |
167 | that.select_next(); |
|
167 | that.select_next(); | |
168 | }; |
|
168 | }; | |
169 | } else if (event.which === key.ENTER && event.shiftKey) { |
|
169 | } else if (event.which === key.ENTER && event.shiftKey) { | |
170 | that.execute_selected_cell(); |
|
170 | that.execute_selected_cell(); | |
171 | return false; |
|
171 | return false; | |
172 | } else if (event.which === key.ENTER && event.altKey) { |
|
172 | } else if (event.which === key.ENTER && event.altKey) { | |
173 | // Execute code cell, and insert new in place |
|
173 | // Execute code cell, and insert new in place | |
174 | that.execute_selected_cell(); |
|
174 | that.execute_selected_cell(); | |
175 | // Only insert a new cell, if we ended up in an already populated cell |
|
175 | // Only insert a new cell, if we ended up in an already populated cell | |
176 | if (/\S/.test(that.get_selected_cell().get_text()) == true) { |
|
176 | if (/\S/.test(that.get_selected_cell().get_text()) == true) { | |
177 | that.insert_cell_above('code'); |
|
177 | that.insert_cell_above('code'); | |
178 | } |
|
178 | } | |
179 | return false; |
|
179 | return false; | |
180 | } else if (event.which === key.ENTER && event.ctrlKey) { |
|
180 | } else if (event.which === key.ENTER && event.ctrlKey) { | |
181 | that.execute_selected_cell({terminal:true}); |
|
181 | that.execute_selected_cell({terminal:true}); | |
182 | return false; |
|
182 | return false; | |
183 | } else if (event.which === 77 && event.ctrlKey && that.control_key_active == false) { |
|
183 | } else if (event.which === 77 && event.ctrlKey && that.control_key_active == false) { | |
184 | that.control_key_active = true; |
|
184 | that.control_key_active = true; | |
185 | return false; |
|
185 | return false; | |
186 | } else if (event.which === 88 && that.control_key_active) { |
|
186 | } else if (event.which === 88 && that.control_key_active) { | |
187 | // Cut selected cell = x |
|
187 | // Cut selected cell = x | |
188 | that.cut_cell(); |
|
188 | that.cut_cell(); | |
189 | that.control_key_active = false; |
|
189 | that.control_key_active = false; | |
190 | return false; |
|
190 | return false; | |
191 | } else if (event.which === 67 && that.control_key_active) { |
|
191 | } else if (event.which === 67 && that.control_key_active) { | |
192 | // Copy selected cell = c |
|
192 | // Copy selected cell = c | |
193 | that.copy_cell(); |
|
193 | that.copy_cell(); | |
194 | that.control_key_active = false; |
|
194 | that.control_key_active = false; | |
195 | return false; |
|
195 | return false; | |
196 | } else if (event.which === 86 && that.control_key_active) { |
|
196 | } else if (event.which === 86 && that.control_key_active) { | |
197 | // Paste below selected cell = v |
|
197 | // Paste below selected cell = v | |
198 | that.paste_cell_below(); |
|
198 | that.paste_cell_below(); | |
199 | that.control_key_active = false; |
|
199 | that.control_key_active = false; | |
200 | return false; |
|
200 | return false; | |
201 | } else if (event.which === 68 && that.control_key_active) { |
|
201 | } else if (event.which === 68 && that.control_key_active) { | |
202 | // Delete selected cell = d |
|
202 | // Delete selected cell = d | |
203 | that.delete_cell(); |
|
203 | that.delete_cell(); | |
204 | that.control_key_active = false; |
|
204 | that.control_key_active = false; | |
205 | return false; |
|
205 | return false; | |
206 | } else if (event.which === 65 && that.control_key_active) { |
|
206 | } else if (event.which === 65 && that.control_key_active) { | |
207 | // Insert code cell above selected = a |
|
207 | // Insert code cell above selected = a | |
208 | that.insert_cell_above('code'); |
|
208 | that.insert_cell_above('code'); | |
209 | that.control_key_active = false; |
|
209 | that.control_key_active = false; | |
210 | return false; |
|
210 | return false; | |
211 | } else if (event.which === 66 && that.control_key_active) { |
|
211 | } else if (event.which === 66 && that.control_key_active) { | |
212 | // Insert code cell below selected = b |
|
212 | // Insert code cell below selected = b | |
213 | that.insert_cell_below('code'); |
|
213 | that.insert_cell_below('code'); | |
214 | that.control_key_active = false; |
|
214 | that.control_key_active = false; | |
215 | return false; |
|
215 | return false; | |
216 | } else if (event.which === 89 && that.control_key_active) { |
|
216 | } else if (event.which === 89 && that.control_key_active) { | |
217 | // To code = y |
|
217 | // To code = y | |
218 | that.to_code(); |
|
218 | that.to_code(); | |
219 | that.control_key_active = false; |
|
219 | that.control_key_active = false; | |
220 | return false; |
|
220 | return false; | |
221 | } else if (event.which === 77 && that.control_key_active) { |
|
221 | } else if (event.which === 77 && that.control_key_active) { | |
222 | // To markdown = m |
|
222 | // To markdown = m | |
223 | that.to_markdown(); |
|
223 | that.to_markdown(); | |
224 | that.control_key_active = false; |
|
224 | that.control_key_active = false; | |
225 | return false; |
|
225 | return false; | |
226 | } else if (event.which === 84 && that.control_key_active) { |
|
226 | } else if (event.which === 84 && that.control_key_active) { | |
227 | // To Raw = t |
|
227 | // To Raw = t | |
228 | that.to_raw(); |
|
228 | that.to_raw(); | |
229 | that.control_key_active = false; |
|
229 | that.control_key_active = false; | |
230 | return false; |
|
230 | return false; | |
231 | } else if (event.which === 49 && that.control_key_active) { |
|
231 | } else if (event.which === 49 && that.control_key_active) { | |
232 | // To Heading 1 = 1 |
|
232 | // To Heading 1 = 1 | |
233 | that.to_heading(undefined, 1); |
|
233 | that.to_heading(undefined, 1); | |
234 | that.control_key_active = false; |
|
234 | that.control_key_active = false; | |
235 | return false; |
|
235 | return false; | |
236 | } else if (event.which === 50 && that.control_key_active) { |
|
236 | } else if (event.which === 50 && that.control_key_active) { | |
237 | // To Heading 2 = 2 |
|
237 | // To Heading 2 = 2 | |
238 | that.to_heading(undefined, 2); |
|
238 | that.to_heading(undefined, 2); | |
239 | that.control_key_active = false; |
|
239 | that.control_key_active = false; | |
240 | return false; |
|
240 | return false; | |
241 | } else if (event.which === 51 && that.control_key_active) { |
|
241 | } else if (event.which === 51 && that.control_key_active) { | |
242 | // To Heading 3 = 3 |
|
242 | // To Heading 3 = 3 | |
243 | that.to_heading(undefined, 3); |
|
243 | that.to_heading(undefined, 3); | |
244 | that.control_key_active = false; |
|
244 | that.control_key_active = false; | |
245 | return false; |
|
245 | return false; | |
246 | } else if (event.which === 52 && that.control_key_active) { |
|
246 | } else if (event.which === 52 && that.control_key_active) { | |
247 | // To Heading 4 = 4 |
|
247 | // To Heading 4 = 4 | |
248 | that.to_heading(undefined, 4); |
|
248 | that.to_heading(undefined, 4); | |
249 | that.control_key_active = false; |
|
249 | that.control_key_active = false; | |
250 | return false; |
|
250 | return false; | |
251 | } else if (event.which === 53 && that.control_key_active) { |
|
251 | } else if (event.which === 53 && that.control_key_active) { | |
252 | // To Heading 5 = 5 |
|
252 | // To Heading 5 = 5 | |
253 | that.to_heading(undefined, 5); |
|
253 | that.to_heading(undefined, 5); | |
254 | that.control_key_active = false; |
|
254 | that.control_key_active = false; | |
255 | return false; |
|
255 | return false; | |
256 | } else if (event.which === 54 && that.control_key_active) { |
|
256 | } else if (event.which === 54 && that.control_key_active) { | |
257 | // To Heading 6 = 6 |
|
257 | // To Heading 6 = 6 | |
258 | that.to_heading(undefined, 6); |
|
258 | that.to_heading(undefined, 6); | |
259 | that.control_key_active = false; |
|
259 | that.control_key_active = false; | |
260 | return false; |
|
260 | return false; | |
261 | } else if (event.which === 79 && that.control_key_active) { |
|
261 | } else if (event.which === 79 && that.control_key_active) { | |
262 | // Toggle output = o |
|
262 | // Toggle output = o | |
263 | if (event.shiftKey){ |
|
263 | if (event.shiftKey){ | |
264 | that.toggle_output_scroll(); |
|
264 | that.toggle_output_scroll(); | |
265 | } else { |
|
265 | } else { | |
266 | that.toggle_output(); |
|
266 | that.toggle_output(); | |
267 | } |
|
267 | } | |
268 | that.control_key_active = false; |
|
268 | that.control_key_active = false; | |
269 | return false; |
|
269 | return false; | |
270 | } else if (event.which === 83 && that.control_key_active) { |
|
270 | } else if (event.which === 83 && that.control_key_active) { | |
271 | // Save notebook = s |
|
271 | // Save notebook = s | |
272 | that.save_checkpoint(); |
|
272 | that.save_checkpoint(); | |
273 | that.control_key_active = false; |
|
273 | that.control_key_active = false; | |
274 | return false; |
|
274 | return false; | |
275 | } else if (event.which === 74 && that.control_key_active) { |
|
275 | } else if (event.which === 74 && that.control_key_active) { | |
276 | // Move cell down = j |
|
276 | // Move cell down = j | |
277 | that.move_cell_down(); |
|
277 | that.move_cell_down(); | |
278 | that.control_key_active = false; |
|
278 | that.control_key_active = false; | |
279 | return false; |
|
279 | return false; | |
280 | } else if (event.which === 75 && that.control_key_active) { |
|
280 | } else if (event.which === 75 && that.control_key_active) { | |
281 | // Move cell up = k |
|
281 | // Move cell up = k | |
282 | that.move_cell_up(); |
|
282 | that.move_cell_up(); | |
283 | that.control_key_active = false; |
|
283 | that.control_key_active = false; | |
284 | return false; |
|
284 | return false; | |
285 | } else if (event.which === 80 && that.control_key_active) { |
|
285 | } else if (event.which === 80 && that.control_key_active) { | |
286 | // Select previous = p |
|
286 | // Select previous = p | |
287 | that.select_prev(); |
|
287 | that.select_prev(); | |
288 | that.control_key_active = false; |
|
288 | that.control_key_active = false; | |
289 | return false; |
|
289 | return false; | |
290 | } else if (event.which === 78 && that.control_key_active) { |
|
290 | } else if (event.which === 78 && that.control_key_active) { | |
291 | // Select next = n |
|
291 | // Select next = n | |
292 | that.select_next(); |
|
292 | that.select_next(); | |
293 | that.control_key_active = false; |
|
293 | that.control_key_active = false; | |
294 | return false; |
|
294 | return false; | |
295 | } else if (event.which === 76 && that.control_key_active) { |
|
295 | } else if (event.which === 76 && that.control_key_active) { | |
296 | // Toggle line numbers = l |
|
296 | // Toggle line numbers = l | |
297 | that.cell_toggle_line_numbers(); |
|
297 | that.cell_toggle_line_numbers(); | |
298 | that.control_key_active = false; |
|
298 | that.control_key_active = false; | |
299 | return false; |
|
299 | return false; | |
300 | } else if (event.which === 73 && that.control_key_active) { |
|
300 | } else if (event.which === 73 && that.control_key_active) { | |
301 | // Interrupt kernel = i |
|
301 | // Interrupt kernel = i | |
302 | that.kernel.interrupt(); |
|
302 | that.kernel.interrupt(); | |
303 | that.control_key_active = false; |
|
303 | that.control_key_active = false; | |
304 | return false; |
|
304 | return false; | |
305 | } else if (event.which === 190 && that.control_key_active) { |
|
305 | } else if (event.which === 190 && that.control_key_active) { | |
306 | // Restart kernel = . # matches qt console |
|
306 | // Restart kernel = . # matches qt console | |
307 | that.restart_kernel(); |
|
307 | that.restart_kernel(); | |
308 | that.control_key_active = false; |
|
308 | that.control_key_active = false; | |
309 | return false; |
|
309 | return false; | |
310 | } else if (event.which === 72 && that.control_key_active) { |
|
310 | } else if (event.which === 72 && that.control_key_active) { | |
311 | // Show keyboard shortcuts = h |
|
311 | // Show keyboard shortcuts = h | |
312 | IPython.quick_help.show_keyboard_shortcuts(); |
|
312 | IPython.quick_help.show_keyboard_shortcuts(); | |
313 | that.control_key_active = false; |
|
313 | that.control_key_active = false; | |
314 | return false; |
|
314 | return false; | |
315 | } else if (event.which === 90 && that.control_key_active) { |
|
315 | } else if (event.which === 90 && that.control_key_active) { | |
316 | // Undo last cell delete = z |
|
316 | // Undo last cell delete = z | |
317 | that.undelete(); |
|
317 | that.undelete(); | |
318 | that.control_key_active = false; |
|
318 | that.control_key_active = false; | |
319 | return false; |
|
319 | return false; | |
320 | } else if (event.which === 189 && that.control_key_active) { |
|
320 | } else if (event.which === 189 && that.control_key_active) { | |
321 | // Split cell = - |
|
321 | // Split cell = - | |
322 | that.split_cell(); |
|
322 | that.split_cell(); | |
323 | that.control_key_active = false; |
|
323 | that.control_key_active = false; | |
324 | return false; |
|
324 | return false; | |
325 | } else if (that.control_key_active) { |
|
325 | } else if (that.control_key_active) { | |
326 | that.control_key_active = false; |
|
326 | that.control_key_active = false; | |
327 | return true; |
|
327 | return true; | |
328 | } |
|
328 | } | |
329 | return true; |
|
329 | return true; | |
330 | }); |
|
330 | }); | |
331 |
|
331 | |||
332 | var collapse_time = function(time){ |
|
332 | var collapse_time = function(time){ | |
333 | var app_height = $('#ipython-main-app').height(); // content height |
|
333 | var app_height = $('#ipython-main-app').height(); // content height | |
334 | var splitter_height = $('div#pager_splitter').outerHeight(true); |
|
334 | var splitter_height = $('div#pager_splitter').outerHeight(true); | |
335 | var new_height = app_height - splitter_height; |
|
335 | var new_height = app_height - splitter_height; | |
336 | that.element.animate({height : new_height + 'px'}, time); |
|
336 | that.element.animate({height : new_height + 'px'}, time); | |
337 | } |
|
337 | } | |
338 |
|
338 | |||
339 | this.element.bind('collapse_pager', function (event,extrap) { |
|
339 | this.element.bind('collapse_pager', function (event,extrap) { | |
340 | var time = (extrap != undefined) ? ((extrap.duration != undefined ) ? extrap.duration : 'fast') : 'fast'; |
|
340 | var time = (extrap != undefined) ? ((extrap.duration != undefined ) ? extrap.duration : 'fast') : 'fast'; | |
341 | collapse_time(time); |
|
341 | collapse_time(time); | |
342 | }); |
|
342 | }); | |
343 |
|
343 | |||
344 | var expand_time = function(time) { |
|
344 | var expand_time = function(time) { | |
345 | var app_height = $('#ipython-main-app').height(); // content height |
|
345 | var app_height = $('#ipython-main-app').height(); // content height | |
346 | var splitter_height = $('div#pager_splitter').outerHeight(true); |
|
346 | var splitter_height = $('div#pager_splitter').outerHeight(true); | |
347 | var pager_height = $('div#pager').outerHeight(true); |
|
347 | var pager_height = $('div#pager').outerHeight(true); | |
348 | var new_height = app_height - pager_height - splitter_height; |
|
348 | var new_height = app_height - pager_height - splitter_height; | |
349 | that.element.animate({height : new_height + 'px'}, time); |
|
349 | that.element.animate({height : new_height + 'px'}, time); | |
350 | } |
|
350 | } | |
351 |
|
351 | |||
352 | this.element.bind('expand_pager', function (event, extrap) { |
|
352 | this.element.bind('expand_pager', function (event, extrap) { | |
353 | var time = (extrap != undefined) ? ((extrap.duration != undefined ) ? extrap.duration : 'fast') : 'fast'; |
|
353 | var time = (extrap != undefined) ? ((extrap.duration != undefined ) ? extrap.duration : 'fast') : 'fast'; | |
354 | expand_time(time); |
|
354 | expand_time(time); | |
355 | }); |
|
355 | }); | |
356 |
|
356 | |||
357 | // Firefox 22 broke $(window).on("beforeunload") |
|
357 | // Firefox 22 broke $(window).on("beforeunload") | |
358 | // I'm not sure why or how. |
|
358 | // I'm not sure why or how. | |
359 | window.onbeforeunload = function (e) { |
|
359 | window.onbeforeunload = function (e) { | |
360 | // TODO: Make killing the kernel configurable. |
|
360 | // TODO: Make killing the kernel configurable. | |
361 | var kill_kernel = false; |
|
361 | var kill_kernel = false; | |
362 | if (kill_kernel) { |
|
362 | if (kill_kernel) { | |
363 | that.kernel.kill(); |
|
363 | that.kernel.kill(); | |
364 | } |
|
364 | } | |
365 | // if we are autosaving, trigger an autosave on nav-away. |
|
365 | // if we are autosaving, trigger an autosave on nav-away. | |
366 | // still warn, because if we don't the autosave may fail. |
|
366 | // still warn, because if we don't the autosave may fail. | |
367 | if (that.dirty) { |
|
367 | if (that.dirty) { | |
368 | if ( that.autosave_interval ) { |
|
368 | if ( that.autosave_interval ) { | |
369 | // schedule autosave in a timeout |
|
369 | // schedule autosave in a timeout | |
370 | // this gives you a chance to forcefully discard changes |
|
370 | // this gives you a chance to forcefully discard changes | |
371 | // by reloading the page if you *really* want to. |
|
371 | // by reloading the page if you *really* want to. | |
372 | // the timer doesn't start until you *dismiss* the dialog. |
|
372 | // the timer doesn't start until you *dismiss* the dialog. | |
373 | setTimeout(function () { |
|
373 | setTimeout(function () { | |
374 | if (that.dirty) { |
|
374 | if (that.dirty) { | |
375 | that.save_notebook(); |
|
375 | that.save_notebook(); | |
376 | } |
|
376 | } | |
377 | }, 1000); |
|
377 | }, 1000); | |
378 | return "Autosave in progress, latest changes may be lost."; |
|
378 | return "Autosave in progress, latest changes may be lost."; | |
379 | } else { |
|
379 | } else { | |
380 | return "Unsaved changes will be lost."; |
|
380 | return "Unsaved changes will be lost."; | |
381 | } |
|
381 | } | |
382 | }; |
|
382 | }; | |
383 | // Null is the *only* return value that will make the browser not |
|
383 | // Null is the *only* return value that will make the browser not | |
384 | // pop up the "don't leave" dialog. |
|
384 | // pop up the "don't leave" dialog. | |
385 | return null; |
|
385 | return null; | |
386 | }; |
|
386 | }; | |
387 | }; |
|
387 | }; | |
388 |
|
388 | |||
389 | /** |
|
389 | /** | |
390 | * Set the dirty flag, and trigger the set_dirty.Notebook event |
|
390 | * Set the dirty flag, and trigger the set_dirty.Notebook event | |
391 | * |
|
391 | * | |
392 | * @method set_dirty |
|
392 | * @method set_dirty | |
393 | */ |
|
393 | */ | |
394 | Notebook.prototype.set_dirty = function (value) { |
|
394 | Notebook.prototype.set_dirty = function (value) { | |
395 | if (value === undefined) { |
|
395 | if (value === undefined) { | |
396 | value = true; |
|
396 | value = true; | |
397 | } |
|
397 | } | |
398 | if (this.dirty == value) { |
|
398 | if (this.dirty == value) { | |
399 | return; |
|
399 | return; | |
400 | } |
|
400 | } | |
401 | $([IPython.events]).trigger('set_dirty.Notebook', {value: value}); |
|
401 | $([IPython.events]).trigger('set_dirty.Notebook', {value: value}); | |
402 | }; |
|
402 | }; | |
403 |
|
403 | |||
404 | /** |
|
404 | /** | |
405 | * Scroll the top of the page to a given cell. |
|
405 | * Scroll the top of the page to a given cell. | |
406 | * |
|
406 | * | |
407 | * @method scroll_to_cell |
|
407 | * @method scroll_to_cell | |
408 | * @param {Number} cell_number An index of the cell to view |
|
408 | * @param {Number} cell_number An index of the cell to view | |
409 | * @param {Number} time Animation time in milliseconds |
|
409 | * @param {Number} time Animation time in milliseconds | |
410 | * @return {Number} Pixel offset from the top of the container |
|
410 | * @return {Number} Pixel offset from the top of the container | |
411 | */ |
|
411 | */ | |
412 | Notebook.prototype.scroll_to_cell = function (cell_number, time) { |
|
412 | Notebook.prototype.scroll_to_cell = function (cell_number, time) { | |
413 | var cells = this.get_cells(); |
|
413 | var cells = this.get_cells(); | |
414 | var time = time || 0; |
|
414 | var time = time || 0; | |
415 | cell_number = Math.min(cells.length-1,cell_number); |
|
415 | cell_number = Math.min(cells.length-1,cell_number); | |
416 | cell_number = Math.max(0 ,cell_number); |
|
416 | cell_number = Math.max(0 ,cell_number); | |
417 | var scroll_value = cells[cell_number].element.position().top-cells[0].element.position().top ; |
|
417 | var scroll_value = cells[cell_number].element.position().top-cells[0].element.position().top ; | |
418 | this.element.animate({scrollTop:scroll_value}, time); |
|
418 | this.element.animate({scrollTop:scroll_value}, time); | |
419 | return scroll_value; |
|
419 | return scroll_value; | |
420 | }; |
|
420 | }; | |
421 |
|
421 | |||
422 | /** |
|
422 | /** | |
423 | * Scroll to the bottom of the page. |
|
423 | * Scroll to the bottom of the page. | |
424 | * |
|
424 | * | |
425 | * @method scroll_to_bottom |
|
425 | * @method scroll_to_bottom | |
426 | */ |
|
426 | */ | |
427 | Notebook.prototype.scroll_to_bottom = function () { |
|
427 | Notebook.prototype.scroll_to_bottom = function () { | |
428 | this.element.animate({scrollTop:this.element.get(0).scrollHeight}, 0); |
|
428 | this.element.animate({scrollTop:this.element.get(0).scrollHeight}, 0); | |
429 | }; |
|
429 | }; | |
430 |
|
430 | |||
431 | /** |
|
431 | /** | |
432 | * Scroll to the top of the page. |
|
432 | * Scroll to the top of the page. | |
433 | * |
|
433 | * | |
434 | * @method scroll_to_top |
|
434 | * @method scroll_to_top | |
435 | */ |
|
435 | */ | |
436 | Notebook.prototype.scroll_to_top = function () { |
|
436 | Notebook.prototype.scroll_to_top = function () { | |
437 | this.element.animate({scrollTop:0}, 0); |
|
437 | this.element.animate({scrollTop:0}, 0); | |
438 | }; |
|
438 | }; | |
439 |
|
439 | |||
|
440 | // Edit Notebook metadata | |||
|
441 | ||||
|
442 | Notebook.prototype.edit_metadata = function () { | |||
|
443 | var that = this; | |||
|
444 | IPython.dialog.edit_metadata(this.metadata, function (md) { | |||
|
445 | that.metadata = md; | |||
|
446 | }, 'Notebook'); | |||
|
447 | }; | |||
440 |
|
448 | |||
441 | // Cell indexing, retrieval, etc. |
|
449 | // Cell indexing, retrieval, etc. | |
442 |
|
450 | |||
443 | /** |
|
451 | /** | |
444 | * Get all cell elements in the notebook. |
|
452 | * Get all cell elements in the notebook. | |
445 | * |
|
453 | * | |
446 | * @method get_cell_elements |
|
454 | * @method get_cell_elements | |
447 | * @return {jQuery} A selector of all cell elements |
|
455 | * @return {jQuery} A selector of all cell elements | |
448 | */ |
|
456 | */ | |
449 | Notebook.prototype.get_cell_elements = function () { |
|
457 | Notebook.prototype.get_cell_elements = function () { | |
450 | return this.container.children("div.cell"); |
|
458 | return this.container.children("div.cell"); | |
451 | }; |
|
459 | }; | |
452 |
|
460 | |||
453 | /** |
|
461 | /** | |
454 | * Get a particular cell element. |
|
462 | * Get a particular cell element. | |
455 | * |
|
463 | * | |
456 | * @method get_cell_element |
|
464 | * @method get_cell_element | |
457 | * @param {Number} index An index of a cell to select |
|
465 | * @param {Number} index An index of a cell to select | |
458 | * @return {jQuery} A selector of the given cell. |
|
466 | * @return {jQuery} A selector of the given cell. | |
459 | */ |
|
467 | */ | |
460 | Notebook.prototype.get_cell_element = function (index) { |
|
468 | Notebook.prototype.get_cell_element = function (index) { | |
461 | var result = null; |
|
469 | var result = null; | |
462 | var e = this.get_cell_elements().eq(index); |
|
470 | var e = this.get_cell_elements().eq(index); | |
463 | if (e.length !== 0) { |
|
471 | if (e.length !== 0) { | |
464 | result = e; |
|
472 | result = e; | |
465 | } |
|
473 | } | |
466 | return result; |
|
474 | return result; | |
467 | }; |
|
475 | }; | |
468 |
|
476 | |||
469 | /** |
|
477 | /** | |
470 | * Count the cells in this notebook. |
|
478 | * Count the cells in this notebook. | |
471 | * |
|
479 | * | |
472 | * @method ncells |
|
480 | * @method ncells | |
473 | * @return {Number} The number of cells in this notebook |
|
481 | * @return {Number} The number of cells in this notebook | |
474 | */ |
|
482 | */ | |
475 | Notebook.prototype.ncells = function () { |
|
483 | Notebook.prototype.ncells = function () { | |
476 | return this.get_cell_elements().length; |
|
484 | return this.get_cell_elements().length; | |
477 | }; |
|
485 | }; | |
478 |
|
486 | |||
479 | /** |
|
487 | /** | |
480 | * Get all Cell objects in this notebook. |
|
488 | * Get all Cell objects in this notebook. | |
481 | * |
|
489 | * | |
482 | * @method get_cells |
|
490 | * @method get_cells | |
483 | * @return {Array} This notebook's Cell objects |
|
491 | * @return {Array} This notebook's Cell objects | |
484 | */ |
|
492 | */ | |
485 | // TODO: we are often calling cells as cells()[i], which we should optimize |
|
493 | // TODO: we are often calling cells as cells()[i], which we should optimize | |
486 | // to cells(i) or a new method. |
|
494 | // to cells(i) or a new method. | |
487 | Notebook.prototype.get_cells = function () { |
|
495 | Notebook.prototype.get_cells = function () { | |
488 | return this.get_cell_elements().toArray().map(function (e) { |
|
496 | return this.get_cell_elements().toArray().map(function (e) { | |
489 | return $(e).data("cell"); |
|
497 | return $(e).data("cell"); | |
490 | }); |
|
498 | }); | |
491 | }; |
|
499 | }; | |
492 |
|
500 | |||
493 | /** |
|
501 | /** | |
494 | * Get a Cell object from this notebook. |
|
502 | * Get a Cell object from this notebook. | |
495 | * |
|
503 | * | |
496 | * @method get_cell |
|
504 | * @method get_cell | |
497 | * @param {Number} index An index of a cell to retrieve |
|
505 | * @param {Number} index An index of a cell to retrieve | |
498 | * @return {Cell} A particular cell |
|
506 | * @return {Cell} A particular cell | |
499 | */ |
|
507 | */ | |
500 | Notebook.prototype.get_cell = function (index) { |
|
508 | Notebook.prototype.get_cell = function (index) { | |
501 | var result = null; |
|
509 | var result = null; | |
502 | var ce = this.get_cell_element(index); |
|
510 | var ce = this.get_cell_element(index); | |
503 | if (ce !== null) { |
|
511 | if (ce !== null) { | |
504 | result = ce.data('cell'); |
|
512 | result = ce.data('cell'); | |
505 | } |
|
513 | } | |
506 | return result; |
|
514 | return result; | |
507 | } |
|
515 | } | |
508 |
|
516 | |||
509 | /** |
|
517 | /** | |
510 | * Get the cell below a given cell. |
|
518 | * Get the cell below a given cell. | |
511 | * |
|
519 | * | |
512 | * @method get_next_cell |
|
520 | * @method get_next_cell | |
513 | * @param {Cell} cell The provided cell |
|
521 | * @param {Cell} cell The provided cell | |
514 | * @return {Cell} The next cell |
|
522 | * @return {Cell} The next cell | |
515 | */ |
|
523 | */ | |
516 | Notebook.prototype.get_next_cell = function (cell) { |
|
524 | Notebook.prototype.get_next_cell = function (cell) { | |
517 | var result = null; |
|
525 | var result = null; | |
518 | var index = this.find_cell_index(cell); |
|
526 | var index = this.find_cell_index(cell); | |
519 | if (this.is_valid_cell_index(index+1)) { |
|
527 | if (this.is_valid_cell_index(index+1)) { | |
520 | result = this.get_cell(index+1); |
|
528 | result = this.get_cell(index+1); | |
521 | } |
|
529 | } | |
522 | return result; |
|
530 | return result; | |
523 | } |
|
531 | } | |
524 |
|
532 | |||
525 | /** |
|
533 | /** | |
526 | * Get the cell above a given cell. |
|
534 | * Get the cell above a given cell. | |
527 | * |
|
535 | * | |
528 | * @method get_prev_cell |
|
536 | * @method get_prev_cell | |
529 | * @param {Cell} cell The provided cell |
|
537 | * @param {Cell} cell The provided cell | |
530 | * @return {Cell} The previous cell |
|
538 | * @return {Cell} The previous cell | |
531 | */ |
|
539 | */ | |
532 | Notebook.prototype.get_prev_cell = function (cell) { |
|
540 | Notebook.prototype.get_prev_cell = function (cell) { | |
533 | // TODO: off-by-one |
|
541 | // TODO: off-by-one | |
534 | // nb.get_prev_cell(nb.get_cell(1)) is null |
|
542 | // nb.get_prev_cell(nb.get_cell(1)) is null | |
535 | var result = null; |
|
543 | var result = null; | |
536 | var index = this.find_cell_index(cell); |
|
544 | var index = this.find_cell_index(cell); | |
537 | if (index !== null && index > 1) { |
|
545 | if (index !== null && index > 1) { | |
538 | result = this.get_cell(index-1); |
|
546 | result = this.get_cell(index-1); | |
539 | } |
|
547 | } | |
540 | return result; |
|
548 | return result; | |
541 | } |
|
549 | } | |
542 |
|
550 | |||
543 | /** |
|
551 | /** | |
544 | * Get the numeric index of a given cell. |
|
552 | * Get the numeric index of a given cell. | |
545 | * |
|
553 | * | |
546 | * @method find_cell_index |
|
554 | * @method find_cell_index | |
547 | * @param {Cell} cell The provided cell |
|
555 | * @param {Cell} cell The provided cell | |
548 | * @return {Number} The cell's numeric index |
|
556 | * @return {Number} The cell's numeric index | |
549 | */ |
|
557 | */ | |
550 | Notebook.prototype.find_cell_index = function (cell) { |
|
558 | Notebook.prototype.find_cell_index = function (cell) { | |
551 | var result = null; |
|
559 | var result = null; | |
552 | this.get_cell_elements().filter(function (index) { |
|
560 | this.get_cell_elements().filter(function (index) { | |
553 | if ($(this).data("cell") === cell) { |
|
561 | if ($(this).data("cell") === cell) { | |
554 | result = index; |
|
562 | result = index; | |
555 | }; |
|
563 | }; | |
556 | }); |
|
564 | }); | |
557 | return result; |
|
565 | return result; | |
558 | }; |
|
566 | }; | |
559 |
|
567 | |||
560 | /** |
|
568 | /** | |
561 | * Get a given index , or the selected index if none is provided. |
|
569 | * Get a given index , or the selected index if none is provided. | |
562 | * |
|
570 | * | |
563 | * @method index_or_selected |
|
571 | * @method index_or_selected | |
564 | * @param {Number} index A cell's index |
|
572 | * @param {Number} index A cell's index | |
565 | * @return {Number} The given index, or selected index if none is provided. |
|
573 | * @return {Number} The given index, or selected index if none is provided. | |
566 | */ |
|
574 | */ | |
567 | Notebook.prototype.index_or_selected = function (index) { |
|
575 | Notebook.prototype.index_or_selected = function (index) { | |
568 | var i; |
|
576 | var i; | |
569 | if (index === undefined || index === null) { |
|
577 | if (index === undefined || index === null) { | |
570 | i = this.get_selected_index(); |
|
578 | i = this.get_selected_index(); | |
571 | if (i === null) { |
|
579 | if (i === null) { | |
572 | i = 0; |
|
580 | i = 0; | |
573 | } |
|
581 | } | |
574 | } else { |
|
582 | } else { | |
575 | i = index; |
|
583 | i = index; | |
576 | } |
|
584 | } | |
577 | return i; |
|
585 | return i; | |
578 | }; |
|
586 | }; | |
579 |
|
587 | |||
580 | /** |
|
588 | /** | |
581 | * Get the currently selected cell. |
|
589 | * Get the currently selected cell. | |
582 | * @method get_selected_cell |
|
590 | * @method get_selected_cell | |
583 | * @return {Cell} The selected cell |
|
591 | * @return {Cell} The selected cell | |
584 | */ |
|
592 | */ | |
585 | Notebook.prototype.get_selected_cell = function () { |
|
593 | Notebook.prototype.get_selected_cell = function () { | |
586 | var index = this.get_selected_index(); |
|
594 | var index = this.get_selected_index(); | |
587 | return this.get_cell(index); |
|
595 | return this.get_cell(index); | |
588 | }; |
|
596 | }; | |
589 |
|
597 | |||
590 | /** |
|
598 | /** | |
591 | * Check whether a cell index is valid. |
|
599 | * Check whether a cell index is valid. | |
592 | * |
|
600 | * | |
593 | * @method is_valid_cell_index |
|
601 | * @method is_valid_cell_index | |
594 | * @param {Number} index A cell index |
|
602 | * @param {Number} index A cell index | |
595 | * @return True if the index is valid, false otherwise |
|
603 | * @return True if the index is valid, false otherwise | |
596 | */ |
|
604 | */ | |
597 | Notebook.prototype.is_valid_cell_index = function (index) { |
|
605 | Notebook.prototype.is_valid_cell_index = function (index) { | |
598 | if (index !== null && index >= 0 && index < this.ncells()) { |
|
606 | if (index !== null && index >= 0 && index < this.ncells()) { | |
599 | return true; |
|
607 | return true; | |
600 | } else { |
|
608 | } else { | |
601 | return false; |
|
609 | return false; | |
602 | }; |
|
610 | }; | |
603 | } |
|
611 | } | |
604 |
|
612 | |||
605 | /** |
|
613 | /** | |
606 | * Get the index of the currently selected cell. |
|
614 | * Get the index of the currently selected cell. | |
607 |
|
615 | |||
608 | * @method get_selected_index |
|
616 | * @method get_selected_index | |
609 | * @return {Number} The selected cell's numeric index |
|
617 | * @return {Number} The selected cell's numeric index | |
610 | */ |
|
618 | */ | |
611 | Notebook.prototype.get_selected_index = function () { |
|
619 | Notebook.prototype.get_selected_index = function () { | |
612 | var result = null; |
|
620 | var result = null; | |
613 | this.get_cell_elements().filter(function (index) { |
|
621 | this.get_cell_elements().filter(function (index) { | |
614 | if ($(this).data("cell").selected === true) { |
|
622 | if ($(this).data("cell").selected === true) { | |
615 | result = index; |
|
623 | result = index; | |
616 | }; |
|
624 | }; | |
617 | }); |
|
625 | }); | |
618 | return result; |
|
626 | return result; | |
619 | }; |
|
627 | }; | |
620 |
|
628 | |||
621 |
|
629 | |||
622 | // Cell selection. |
|
630 | // Cell selection. | |
623 |
|
631 | |||
624 | /** |
|
632 | /** | |
625 | * Programmatically select a cell. |
|
633 | * Programmatically select a cell. | |
626 | * |
|
634 | * | |
627 | * @method select |
|
635 | * @method select | |
628 | * @param {Number} index A cell's index |
|
636 | * @param {Number} index A cell's index | |
629 | * @return {Notebook} This notebook |
|
637 | * @return {Notebook} This notebook | |
630 | */ |
|
638 | */ | |
631 | Notebook.prototype.select = function (index) { |
|
639 | Notebook.prototype.select = function (index) { | |
632 | if (this.is_valid_cell_index(index)) { |
|
640 | if (this.is_valid_cell_index(index)) { | |
633 | var sindex = this.get_selected_index() |
|
641 | var sindex = this.get_selected_index() | |
634 | if (sindex !== null && index !== sindex) { |
|
642 | if (sindex !== null && index !== sindex) { | |
635 | this.get_cell(sindex).unselect(); |
|
643 | this.get_cell(sindex).unselect(); | |
636 | }; |
|
644 | }; | |
637 | var cell = this.get_cell(index); |
|
645 | var cell = this.get_cell(index); | |
638 | cell.select(); |
|
646 | cell.select(); | |
639 | if (cell.cell_type === 'heading') { |
|
647 | if (cell.cell_type === 'heading') { | |
640 | $([IPython.events]).trigger('selected_cell_type_changed.Notebook', |
|
648 | $([IPython.events]).trigger('selected_cell_type_changed.Notebook', | |
641 | {'cell_type':cell.cell_type,level:cell.level} |
|
649 | {'cell_type':cell.cell_type,level:cell.level} | |
642 | ); |
|
650 | ); | |
643 | } else { |
|
651 | } else { | |
644 | $([IPython.events]).trigger('selected_cell_type_changed.Notebook', |
|
652 | $([IPython.events]).trigger('selected_cell_type_changed.Notebook', | |
645 | {'cell_type':cell.cell_type} |
|
653 | {'cell_type':cell.cell_type} | |
646 | ); |
|
654 | ); | |
647 | }; |
|
655 | }; | |
648 | }; |
|
656 | }; | |
649 | return this; |
|
657 | return this; | |
650 | }; |
|
658 | }; | |
651 |
|
659 | |||
652 | /** |
|
660 | /** | |
653 | * Programmatically select the next cell. |
|
661 | * Programmatically select the next cell. | |
654 | * |
|
662 | * | |
655 | * @method select_next |
|
663 | * @method select_next | |
656 | * @return {Notebook} This notebook |
|
664 | * @return {Notebook} This notebook | |
657 | */ |
|
665 | */ | |
658 | Notebook.prototype.select_next = function () { |
|
666 | Notebook.prototype.select_next = function () { | |
659 | var index = this.get_selected_index(); |
|
667 | var index = this.get_selected_index(); | |
660 | this.select(index+1); |
|
668 | this.select(index+1); | |
661 | return this; |
|
669 | return this; | |
662 | }; |
|
670 | }; | |
663 |
|
671 | |||
664 | /** |
|
672 | /** | |
665 | * Programmatically select the previous cell. |
|
673 | * Programmatically select the previous cell. | |
666 | * |
|
674 | * | |
667 | * @method select_prev |
|
675 | * @method select_prev | |
668 | * @return {Notebook} This notebook |
|
676 | * @return {Notebook} This notebook | |
669 | */ |
|
677 | */ | |
670 | Notebook.prototype.select_prev = function () { |
|
678 | Notebook.prototype.select_prev = function () { | |
671 | var index = this.get_selected_index(); |
|
679 | var index = this.get_selected_index(); | |
672 | this.select(index-1); |
|
680 | this.select(index-1); | |
673 | return this; |
|
681 | return this; | |
674 | }; |
|
682 | }; | |
675 |
|
683 | |||
676 |
|
684 | |||
677 | // Cell movement |
|
685 | // Cell movement | |
678 |
|
686 | |||
679 | /** |
|
687 | /** | |
680 | * Move given (or selected) cell up and select it. |
|
688 | * Move given (or selected) cell up and select it. | |
681 | * |
|
689 | * | |
682 | * @method move_cell_up |
|
690 | * @method move_cell_up | |
683 | * @param [index] {integer} cell index |
|
691 | * @param [index] {integer} cell index | |
684 | * @return {Notebook} This notebook |
|
692 | * @return {Notebook} This notebook | |
685 | **/ |
|
693 | **/ | |
686 | Notebook.prototype.move_cell_up = function (index) { |
|
694 | Notebook.prototype.move_cell_up = function (index) { | |
687 | var i = this.index_or_selected(index); |
|
695 | var i = this.index_or_selected(index); | |
688 | if (this.is_valid_cell_index(i) && i > 0) { |
|
696 | if (this.is_valid_cell_index(i) && i > 0) { | |
689 | var pivot = this.get_cell_element(i-1); |
|
697 | var pivot = this.get_cell_element(i-1); | |
690 | var tomove = this.get_cell_element(i); |
|
698 | var tomove = this.get_cell_element(i); | |
691 | if (pivot !== null && tomove !== null) { |
|
699 | if (pivot !== null && tomove !== null) { | |
692 | tomove.detach(); |
|
700 | tomove.detach(); | |
693 | pivot.before(tomove); |
|
701 | pivot.before(tomove); | |
694 | this.select(i-1); |
|
702 | this.select(i-1); | |
695 | }; |
|
703 | }; | |
696 | this.set_dirty(true); |
|
704 | this.set_dirty(true); | |
697 | }; |
|
705 | }; | |
698 | return this; |
|
706 | return this; | |
699 | }; |
|
707 | }; | |
700 |
|
708 | |||
701 |
|
709 | |||
702 | /** |
|
710 | /** | |
703 | * Move given (or selected) cell down and select it |
|
711 | * Move given (or selected) cell down and select it | |
704 | * |
|
712 | * | |
705 | * @method move_cell_down |
|
713 | * @method move_cell_down | |
706 | * @param [index] {integer} cell index |
|
714 | * @param [index] {integer} cell index | |
707 | * @return {Notebook} This notebook |
|
715 | * @return {Notebook} This notebook | |
708 | **/ |
|
716 | **/ | |
709 | Notebook.prototype.move_cell_down = function (index) { |
|
717 | Notebook.prototype.move_cell_down = function (index) { | |
710 | var i = this.index_or_selected(index); |
|
718 | var i = this.index_or_selected(index); | |
711 | if ( this.is_valid_cell_index(i) && this.is_valid_cell_index(i+1)) { |
|
719 | if ( this.is_valid_cell_index(i) && this.is_valid_cell_index(i+1)) { | |
712 | var pivot = this.get_cell_element(i+1); |
|
720 | var pivot = this.get_cell_element(i+1); | |
713 | var tomove = this.get_cell_element(i); |
|
721 | var tomove = this.get_cell_element(i); | |
714 | if (pivot !== null && tomove !== null) { |
|
722 | if (pivot !== null && tomove !== null) { | |
715 | tomove.detach(); |
|
723 | tomove.detach(); | |
716 | pivot.after(tomove); |
|
724 | pivot.after(tomove); | |
717 | this.select(i+1); |
|
725 | this.select(i+1); | |
718 | }; |
|
726 | }; | |
719 | }; |
|
727 | }; | |
720 | this.set_dirty(); |
|
728 | this.set_dirty(); | |
721 | return this; |
|
729 | return this; | |
722 | }; |
|
730 | }; | |
723 |
|
731 | |||
724 |
|
732 | |||
725 | // Insertion, deletion. |
|
733 | // Insertion, deletion. | |
726 |
|
734 | |||
727 | /** |
|
735 | /** | |
728 | * Delete a cell from the notebook. |
|
736 | * Delete a cell from the notebook. | |
729 | * |
|
737 | * | |
730 | * @method delete_cell |
|
738 | * @method delete_cell | |
731 | * @param [index] A cell's numeric index |
|
739 | * @param [index] A cell's numeric index | |
732 | * @return {Notebook} This notebook |
|
740 | * @return {Notebook} This notebook | |
733 | */ |
|
741 | */ | |
734 | Notebook.prototype.delete_cell = function (index) { |
|
742 | Notebook.prototype.delete_cell = function (index) { | |
735 | var i = this.index_or_selected(index); |
|
743 | var i = this.index_or_selected(index); | |
736 | var cell = this.get_selected_cell(); |
|
744 | var cell = this.get_selected_cell(); | |
737 | this.undelete_backup = cell.toJSON(); |
|
745 | this.undelete_backup = cell.toJSON(); | |
738 | $('#undelete_cell').removeClass('disabled'); |
|
746 | $('#undelete_cell').removeClass('disabled'); | |
739 | if (this.is_valid_cell_index(i)) { |
|
747 | if (this.is_valid_cell_index(i)) { | |
740 | var ce = this.get_cell_element(i); |
|
748 | var ce = this.get_cell_element(i); | |
741 | ce.remove(); |
|
749 | ce.remove(); | |
742 | if (i === (this.ncells())) { |
|
750 | if (i === (this.ncells())) { | |
743 | this.select(i-1); |
|
751 | this.select(i-1); | |
744 | this.undelete_index = i - 1; |
|
752 | this.undelete_index = i - 1; | |
745 | this.undelete_below = true; |
|
753 | this.undelete_below = true; | |
746 | } else { |
|
754 | } else { | |
747 | this.select(i); |
|
755 | this.select(i); | |
748 | this.undelete_index = i; |
|
756 | this.undelete_index = i; | |
749 | this.undelete_below = false; |
|
757 | this.undelete_below = false; | |
750 | }; |
|
758 | }; | |
751 | $([IPython.events]).trigger('delete.Cell', {'cell': cell, 'index': i}); |
|
759 | $([IPython.events]).trigger('delete.Cell', {'cell': cell, 'index': i}); | |
752 | this.set_dirty(true); |
|
760 | this.set_dirty(true); | |
753 | }; |
|
761 | }; | |
754 | return this; |
|
762 | return this; | |
755 | }; |
|
763 | }; | |
756 |
|
764 | |||
757 | /** |
|
765 | /** | |
758 | * Insert a cell so that after insertion the cell is at given index. |
|
766 | * Insert a cell so that after insertion the cell is at given index. | |
759 | * |
|
767 | * | |
760 | * Similar to insert_above, but index parameter is mandatory |
|
768 | * Similar to insert_above, but index parameter is mandatory | |
761 | * |
|
769 | * | |
762 | * Index will be brought back into the accissible range [0,n] |
|
770 | * Index will be brought back into the accissible range [0,n] | |
763 | * |
|
771 | * | |
764 | * @method insert_cell_at_index |
|
772 | * @method insert_cell_at_index | |
765 | * @param type {string} in ['code','markdown','heading'] |
|
773 | * @param type {string} in ['code','markdown','heading'] | |
766 | * @param [index] {int} a valid index where to inser cell |
|
774 | * @param [index] {int} a valid index where to inser cell | |
767 | * |
|
775 | * | |
768 | * @return cell {cell|null} created cell or null |
|
776 | * @return cell {cell|null} created cell or null | |
769 | **/ |
|
777 | **/ | |
770 | Notebook.prototype.insert_cell_at_index = function(type, index){ |
|
778 | Notebook.prototype.insert_cell_at_index = function(type, index){ | |
771 |
|
779 | |||
772 | var ncells = this.ncells(); |
|
780 | var ncells = this.ncells(); | |
773 | var index = Math.min(index,ncells); |
|
781 | var index = Math.min(index,ncells); | |
774 | index = Math.max(index,0); |
|
782 | index = Math.max(index,0); | |
775 | var cell = null; |
|
783 | var cell = null; | |
776 |
|
784 | |||
777 | if (ncells === 0 || this.is_valid_cell_index(index) || index === ncells) { |
|
785 | if (ncells === 0 || this.is_valid_cell_index(index) || index === ncells) { | |
778 | if (type === 'code') { |
|
786 | if (type === 'code') { | |
779 | cell = new IPython.CodeCell(this.kernel); |
|
787 | cell = new IPython.CodeCell(this.kernel); | |
780 | cell.set_input_prompt(); |
|
788 | cell.set_input_prompt(); | |
781 | } else if (type === 'markdown') { |
|
789 | } else if (type === 'markdown') { | |
782 | cell = new IPython.MarkdownCell(); |
|
790 | cell = new IPython.MarkdownCell(); | |
783 | } else if (type === 'raw') { |
|
791 | } else if (type === 'raw') { | |
784 | cell = new IPython.RawCell(); |
|
792 | cell = new IPython.RawCell(); | |
785 | } else if (type === 'heading') { |
|
793 | } else if (type === 'heading') { | |
786 | cell = new IPython.HeadingCell(); |
|
794 | cell = new IPython.HeadingCell(); | |
787 | } |
|
795 | } | |
788 |
|
796 | |||
789 | if(this._insert_element_at_index(cell.element,index)){ |
|
797 | if(this._insert_element_at_index(cell.element,index)){ | |
790 | cell.render(); |
|
798 | cell.render(); | |
791 | this.select(this.find_cell_index(cell)); |
|
799 | this.select(this.find_cell_index(cell)); | |
792 | $([IPython.events]).trigger('create.Cell', {'cell': cell, 'index': index}); |
|
800 | $([IPython.events]).trigger('create.Cell', {'cell': cell, 'index': index}); | |
793 | this.set_dirty(true); |
|
801 | this.set_dirty(true); | |
794 | } |
|
802 | } | |
795 | } |
|
803 | } | |
796 | return cell; |
|
804 | return cell; | |
797 |
|
805 | |||
798 | }; |
|
806 | }; | |
799 |
|
807 | |||
800 | /** |
|
808 | /** | |
801 | * Insert an element at given cell index. |
|
809 | * Insert an element at given cell index. | |
802 | * |
|
810 | * | |
803 | * @method _insert_element_at_index |
|
811 | * @method _insert_element_at_index | |
804 | * @param element {dom element} a cell element |
|
812 | * @param element {dom element} a cell element | |
805 | * @param [index] {int} a valid index where to inser cell |
|
813 | * @param [index] {int} a valid index where to inser cell | |
806 | * @private |
|
814 | * @private | |
807 | * |
|
815 | * | |
808 | * return true if everything whent fine. |
|
816 | * return true if everything whent fine. | |
809 | **/ |
|
817 | **/ | |
810 | Notebook.prototype._insert_element_at_index = function(element, index){ |
|
818 | Notebook.prototype._insert_element_at_index = function(element, index){ | |
811 | if (element === undefined){ |
|
819 | if (element === undefined){ | |
812 | return false; |
|
820 | return false; | |
813 | } |
|
821 | } | |
814 |
|
822 | |||
815 | var ncells = this.ncells(); |
|
823 | var ncells = this.ncells(); | |
816 |
|
824 | |||
817 | if (ncells === 0) { |
|
825 | if (ncells === 0) { | |
818 | // special case append if empty |
|
826 | // special case append if empty | |
819 | this.element.find('div.end_space').before(element); |
|
827 | this.element.find('div.end_space').before(element); | |
820 | } else if ( ncells === index ) { |
|
828 | } else if ( ncells === index ) { | |
821 | // special case append it the end, but not empty |
|
829 | // special case append it the end, but not empty | |
822 | this.get_cell_element(index-1).after(element); |
|
830 | this.get_cell_element(index-1).after(element); | |
823 | } else if (this.is_valid_cell_index(index)) { |
|
831 | } else if (this.is_valid_cell_index(index)) { | |
824 | // otherwise always somewhere to append to |
|
832 | // otherwise always somewhere to append to | |
825 | this.get_cell_element(index).before(element); |
|
833 | this.get_cell_element(index).before(element); | |
826 | } else { |
|
834 | } else { | |
827 | return false; |
|
835 | return false; | |
828 | } |
|
836 | } | |
829 |
|
837 | |||
830 | if (this.undelete_index !== null && index <= this.undelete_index) { |
|
838 | if (this.undelete_index !== null && index <= this.undelete_index) { | |
831 | this.undelete_index = this.undelete_index + 1; |
|
839 | this.undelete_index = this.undelete_index + 1; | |
832 | this.set_dirty(true); |
|
840 | this.set_dirty(true); | |
833 | } |
|
841 | } | |
834 | return true; |
|
842 | return true; | |
835 | }; |
|
843 | }; | |
836 |
|
844 | |||
837 | /** |
|
845 | /** | |
838 | * Insert a cell of given type above given index, or at top |
|
846 | * Insert a cell of given type above given index, or at top | |
839 | * of notebook if index smaller than 0. |
|
847 | * of notebook if index smaller than 0. | |
840 | * |
|
848 | * | |
841 | * default index value is the one of currently selected cell |
|
849 | * default index value is the one of currently selected cell | |
842 | * |
|
850 | * | |
843 | * @method insert_cell_above |
|
851 | * @method insert_cell_above | |
844 | * @param type {string} cell type |
|
852 | * @param type {string} cell type | |
845 | * @param [index] {integer} |
|
853 | * @param [index] {integer} | |
846 | * |
|
854 | * | |
847 | * @return handle to created cell or null |
|
855 | * @return handle to created cell or null | |
848 | **/ |
|
856 | **/ | |
849 | Notebook.prototype.insert_cell_above = function (type, index) { |
|
857 | Notebook.prototype.insert_cell_above = function (type, index) { | |
850 | index = this.index_or_selected(index); |
|
858 | index = this.index_or_selected(index); | |
851 | return this.insert_cell_at_index(type, index); |
|
859 | return this.insert_cell_at_index(type, index); | |
852 | }; |
|
860 | }; | |
853 |
|
861 | |||
854 | /** |
|
862 | /** | |
855 | * Insert a cell of given type below given index, or at bottom |
|
863 | * Insert a cell of given type below given index, or at bottom | |
856 | * of notebook if index greater thatn number of cell |
|
864 | * of notebook if index greater thatn number of cell | |
857 | * |
|
865 | * | |
858 | * default index value is the one of currently selected cell |
|
866 | * default index value is the one of currently selected cell | |
859 | * |
|
867 | * | |
860 | * @method insert_cell_below |
|
868 | * @method insert_cell_below | |
861 | * @param type {string} cell type |
|
869 | * @param type {string} cell type | |
862 | * @param [index] {integer} |
|
870 | * @param [index] {integer} | |
863 | * |
|
871 | * | |
864 | * @return handle to created cell or null |
|
872 | * @return handle to created cell or null | |
865 | * |
|
873 | * | |
866 | **/ |
|
874 | **/ | |
867 | Notebook.prototype.insert_cell_below = function (type, index) { |
|
875 | Notebook.prototype.insert_cell_below = function (type, index) { | |
868 | index = this.index_or_selected(index); |
|
876 | index = this.index_or_selected(index); | |
869 | return this.insert_cell_at_index(type, index+1); |
|
877 | return this.insert_cell_at_index(type, index+1); | |
870 | }; |
|
878 | }; | |
871 |
|
879 | |||
872 |
|
880 | |||
873 | /** |
|
881 | /** | |
874 | * Insert cell at end of notebook |
|
882 | * Insert cell at end of notebook | |
875 | * |
|
883 | * | |
876 | * @method insert_cell_at_bottom |
|
884 | * @method insert_cell_at_bottom | |
877 | * @param {String} type cell type |
|
885 | * @param {String} type cell type | |
878 | * |
|
886 | * | |
879 | * @return the added cell; or null |
|
887 | * @return the added cell; or null | |
880 | **/ |
|
888 | **/ | |
881 | Notebook.prototype.insert_cell_at_bottom = function (type){ |
|
889 | Notebook.prototype.insert_cell_at_bottom = function (type){ | |
882 | var len = this.ncells(); |
|
890 | var len = this.ncells(); | |
883 | return this.insert_cell_below(type,len-1); |
|
891 | return this.insert_cell_below(type,len-1); | |
884 | }; |
|
892 | }; | |
885 |
|
893 | |||
886 | /** |
|
894 | /** | |
887 | * Turn a cell into a code cell. |
|
895 | * Turn a cell into a code cell. | |
888 | * |
|
896 | * | |
889 | * @method to_code |
|
897 | * @method to_code | |
890 | * @param {Number} [index] A cell's index |
|
898 | * @param {Number} [index] A cell's index | |
891 | */ |
|
899 | */ | |
892 | Notebook.prototype.to_code = function (index) { |
|
900 | Notebook.prototype.to_code = function (index) { | |
893 | var i = this.index_or_selected(index); |
|
901 | var i = this.index_or_selected(index); | |
894 | if (this.is_valid_cell_index(i)) { |
|
902 | if (this.is_valid_cell_index(i)) { | |
895 | var source_element = this.get_cell_element(i); |
|
903 | var source_element = this.get_cell_element(i); | |
896 | var source_cell = source_element.data("cell"); |
|
904 | var source_cell = source_element.data("cell"); | |
897 | if (!(source_cell instanceof IPython.CodeCell)) { |
|
905 | if (!(source_cell instanceof IPython.CodeCell)) { | |
898 | var target_cell = this.insert_cell_below('code',i); |
|
906 | var target_cell = this.insert_cell_below('code',i); | |
899 | var text = source_cell.get_text(); |
|
907 | var text = source_cell.get_text(); | |
900 | if (text === source_cell.placeholder) { |
|
908 | if (text === source_cell.placeholder) { | |
901 | text = ''; |
|
909 | text = ''; | |
902 | } |
|
910 | } | |
903 | target_cell.set_text(text); |
|
911 | target_cell.set_text(text); | |
904 | // make this value the starting point, so that we can only undo |
|
912 | // make this value the starting point, so that we can only undo | |
905 | // to this state, instead of a blank cell |
|
913 | // to this state, instead of a blank cell | |
906 | target_cell.code_mirror.clearHistory(); |
|
914 | target_cell.code_mirror.clearHistory(); | |
907 | source_element.remove(); |
|
915 | source_element.remove(); | |
908 | this.set_dirty(true); |
|
916 | this.set_dirty(true); | |
909 | }; |
|
917 | }; | |
910 | }; |
|
918 | }; | |
911 | }; |
|
919 | }; | |
912 |
|
920 | |||
913 | /** |
|
921 | /** | |
914 | * Turn a cell into a Markdown cell. |
|
922 | * Turn a cell into a Markdown cell. | |
915 | * |
|
923 | * | |
916 | * @method to_markdown |
|
924 | * @method to_markdown | |
917 | * @param {Number} [index] A cell's index |
|
925 | * @param {Number} [index] A cell's index | |
918 | */ |
|
926 | */ | |
919 | Notebook.prototype.to_markdown = function (index) { |
|
927 | Notebook.prototype.to_markdown = function (index) { | |
920 | var i = this.index_or_selected(index); |
|
928 | var i = this.index_or_selected(index); | |
921 | if (this.is_valid_cell_index(i)) { |
|
929 | if (this.is_valid_cell_index(i)) { | |
922 | var source_element = this.get_cell_element(i); |
|
930 | var source_element = this.get_cell_element(i); | |
923 | var source_cell = source_element.data("cell"); |
|
931 | var source_cell = source_element.data("cell"); | |
924 | if (!(source_cell instanceof IPython.MarkdownCell)) { |
|
932 | if (!(source_cell instanceof IPython.MarkdownCell)) { | |
925 | var target_cell = this.insert_cell_below('markdown',i); |
|
933 | var target_cell = this.insert_cell_below('markdown',i); | |
926 | var text = source_cell.get_text(); |
|
934 | var text = source_cell.get_text(); | |
927 | if (text === source_cell.placeholder) { |
|
935 | if (text === source_cell.placeholder) { | |
928 | text = ''; |
|
936 | text = ''; | |
929 | }; |
|
937 | }; | |
930 | // The edit must come before the set_text. |
|
938 | // The edit must come before the set_text. | |
931 | target_cell.edit(); |
|
939 | target_cell.edit(); | |
932 | target_cell.set_text(text); |
|
940 | target_cell.set_text(text); | |
933 | // make this value the starting point, so that we can only undo |
|
941 | // make this value the starting point, so that we can only undo | |
934 | // to this state, instead of a blank cell |
|
942 | // to this state, instead of a blank cell | |
935 | target_cell.code_mirror.clearHistory(); |
|
943 | target_cell.code_mirror.clearHistory(); | |
936 | source_element.remove(); |
|
944 | source_element.remove(); | |
937 | this.set_dirty(true); |
|
945 | this.set_dirty(true); | |
938 | }; |
|
946 | }; | |
939 | }; |
|
947 | }; | |
940 | }; |
|
948 | }; | |
941 |
|
949 | |||
942 | /** |
|
950 | /** | |
943 | * Turn a cell into a raw text cell. |
|
951 | * Turn a cell into a raw text cell. | |
944 | * |
|
952 | * | |
945 | * @method to_raw |
|
953 | * @method to_raw | |
946 | * @param {Number} [index] A cell's index |
|
954 | * @param {Number} [index] A cell's index | |
947 | */ |
|
955 | */ | |
948 | Notebook.prototype.to_raw = function (index) { |
|
956 | Notebook.prototype.to_raw = function (index) { | |
949 | var i = this.index_or_selected(index); |
|
957 | var i = this.index_or_selected(index); | |
950 | if (this.is_valid_cell_index(i)) { |
|
958 | if (this.is_valid_cell_index(i)) { | |
951 | var source_element = this.get_cell_element(i); |
|
959 | var source_element = this.get_cell_element(i); | |
952 | var source_cell = source_element.data("cell"); |
|
960 | var source_cell = source_element.data("cell"); | |
953 | var target_cell = null; |
|
961 | var target_cell = null; | |
954 | if (!(source_cell instanceof IPython.RawCell)) { |
|
962 | if (!(source_cell instanceof IPython.RawCell)) { | |
955 | target_cell = this.insert_cell_below('raw',i); |
|
963 | target_cell = this.insert_cell_below('raw',i); | |
956 | var text = source_cell.get_text(); |
|
964 | var text = source_cell.get_text(); | |
957 | if (text === source_cell.placeholder) { |
|
965 | if (text === source_cell.placeholder) { | |
958 | text = ''; |
|
966 | text = ''; | |
959 | }; |
|
967 | }; | |
960 | // The edit must come before the set_text. |
|
968 | // The edit must come before the set_text. | |
961 | target_cell.edit(); |
|
969 | target_cell.edit(); | |
962 | target_cell.set_text(text); |
|
970 | target_cell.set_text(text); | |
963 | // make this value the starting point, so that we can only undo |
|
971 | // make this value the starting point, so that we can only undo | |
964 | // to this state, instead of a blank cell |
|
972 | // to this state, instead of a blank cell | |
965 | target_cell.code_mirror.clearHistory(); |
|
973 | target_cell.code_mirror.clearHistory(); | |
966 | source_element.remove(); |
|
974 | source_element.remove(); | |
967 | this.set_dirty(true); |
|
975 | this.set_dirty(true); | |
968 | }; |
|
976 | }; | |
969 | }; |
|
977 | }; | |
970 | }; |
|
978 | }; | |
971 |
|
979 | |||
972 | /** |
|
980 | /** | |
973 | * Turn a cell into a heading cell. |
|
981 | * Turn a cell into a heading cell. | |
974 | * |
|
982 | * | |
975 | * @method to_heading |
|
983 | * @method to_heading | |
976 | * @param {Number} [index] A cell's index |
|
984 | * @param {Number} [index] A cell's index | |
977 | * @param {Number} [level] A heading level (e.g., 1 becomes <h1>) |
|
985 | * @param {Number} [level] A heading level (e.g., 1 becomes <h1>) | |
978 | */ |
|
986 | */ | |
979 | Notebook.prototype.to_heading = function (index, level) { |
|
987 | Notebook.prototype.to_heading = function (index, level) { | |
980 | level = level || 1; |
|
988 | level = level || 1; | |
981 | var i = this.index_or_selected(index); |
|
989 | var i = this.index_or_selected(index); | |
982 | if (this.is_valid_cell_index(i)) { |
|
990 | if (this.is_valid_cell_index(i)) { | |
983 | var source_element = this.get_cell_element(i); |
|
991 | var source_element = this.get_cell_element(i); | |
984 | var source_cell = source_element.data("cell"); |
|
992 | var source_cell = source_element.data("cell"); | |
985 | var target_cell = null; |
|
993 | var target_cell = null; | |
986 | if (source_cell instanceof IPython.HeadingCell) { |
|
994 | if (source_cell instanceof IPython.HeadingCell) { | |
987 | source_cell.set_level(level); |
|
995 | source_cell.set_level(level); | |
988 | } else { |
|
996 | } else { | |
989 | target_cell = this.insert_cell_below('heading',i); |
|
997 | target_cell = this.insert_cell_below('heading',i); | |
990 | var text = source_cell.get_text(); |
|
998 | var text = source_cell.get_text(); | |
991 | if (text === source_cell.placeholder) { |
|
999 | if (text === source_cell.placeholder) { | |
992 | text = ''; |
|
1000 | text = ''; | |
993 | }; |
|
1001 | }; | |
994 | // The edit must come before the set_text. |
|
1002 | // The edit must come before the set_text. | |
995 | target_cell.set_level(level); |
|
1003 | target_cell.set_level(level); | |
996 | target_cell.edit(); |
|
1004 | target_cell.edit(); | |
997 | target_cell.set_text(text); |
|
1005 | target_cell.set_text(text); | |
998 | // make this value the starting point, so that we can only undo |
|
1006 | // make this value the starting point, so that we can only undo | |
999 | // to this state, instead of a blank cell |
|
1007 | // to this state, instead of a blank cell | |
1000 | target_cell.code_mirror.clearHistory(); |
|
1008 | target_cell.code_mirror.clearHistory(); | |
1001 | source_element.remove(); |
|
1009 | source_element.remove(); | |
1002 | this.set_dirty(true); |
|
1010 | this.set_dirty(true); | |
1003 | }; |
|
1011 | }; | |
1004 | $([IPython.events]).trigger('selected_cell_type_changed.Notebook', |
|
1012 | $([IPython.events]).trigger('selected_cell_type_changed.Notebook', | |
1005 | {'cell_type':'heading',level:level} |
|
1013 | {'cell_type':'heading',level:level} | |
1006 | ); |
|
1014 | ); | |
1007 | }; |
|
1015 | }; | |
1008 | }; |
|
1016 | }; | |
1009 |
|
1017 | |||
1010 |
|
1018 | |||
1011 | // Cut/Copy/Paste |
|
1019 | // Cut/Copy/Paste | |
1012 |
|
1020 | |||
1013 | /** |
|
1021 | /** | |
1014 | * Enable UI elements for pasting cells. |
|
1022 | * Enable UI elements for pasting cells. | |
1015 | * |
|
1023 | * | |
1016 | * @method enable_paste |
|
1024 | * @method enable_paste | |
1017 | */ |
|
1025 | */ | |
1018 | Notebook.prototype.enable_paste = function () { |
|
1026 | Notebook.prototype.enable_paste = function () { | |
1019 | var that = this; |
|
1027 | var that = this; | |
1020 | if (!this.paste_enabled) { |
|
1028 | if (!this.paste_enabled) { | |
1021 | $('#paste_cell_replace').removeClass('disabled') |
|
1029 | $('#paste_cell_replace').removeClass('disabled') | |
1022 | .on('click', function () {that.paste_cell_replace();}); |
|
1030 | .on('click', function () {that.paste_cell_replace();}); | |
1023 | $('#paste_cell_above').removeClass('disabled') |
|
1031 | $('#paste_cell_above').removeClass('disabled') | |
1024 | .on('click', function () {that.paste_cell_above();}); |
|
1032 | .on('click', function () {that.paste_cell_above();}); | |
1025 | $('#paste_cell_below').removeClass('disabled') |
|
1033 | $('#paste_cell_below').removeClass('disabled') | |
1026 | .on('click', function () {that.paste_cell_below();}); |
|
1034 | .on('click', function () {that.paste_cell_below();}); | |
1027 | this.paste_enabled = true; |
|
1035 | this.paste_enabled = true; | |
1028 | }; |
|
1036 | }; | |
1029 | }; |
|
1037 | }; | |
1030 |
|
1038 | |||
1031 | /** |
|
1039 | /** | |
1032 | * Disable UI elements for pasting cells. |
|
1040 | * Disable UI elements for pasting cells. | |
1033 | * |
|
1041 | * | |
1034 | * @method disable_paste |
|
1042 | * @method disable_paste | |
1035 | */ |
|
1043 | */ | |
1036 | Notebook.prototype.disable_paste = function () { |
|
1044 | Notebook.prototype.disable_paste = function () { | |
1037 | if (this.paste_enabled) { |
|
1045 | if (this.paste_enabled) { | |
1038 | $('#paste_cell_replace').addClass('disabled').off('click'); |
|
1046 | $('#paste_cell_replace').addClass('disabled').off('click'); | |
1039 | $('#paste_cell_above').addClass('disabled').off('click'); |
|
1047 | $('#paste_cell_above').addClass('disabled').off('click'); | |
1040 | $('#paste_cell_below').addClass('disabled').off('click'); |
|
1048 | $('#paste_cell_below').addClass('disabled').off('click'); | |
1041 | this.paste_enabled = false; |
|
1049 | this.paste_enabled = false; | |
1042 | }; |
|
1050 | }; | |
1043 | }; |
|
1051 | }; | |
1044 |
|
1052 | |||
1045 | /** |
|
1053 | /** | |
1046 | * Cut a cell. |
|
1054 | * Cut a cell. | |
1047 | * |
|
1055 | * | |
1048 | * @method cut_cell |
|
1056 | * @method cut_cell | |
1049 | */ |
|
1057 | */ | |
1050 | Notebook.prototype.cut_cell = function () { |
|
1058 | Notebook.prototype.cut_cell = function () { | |
1051 | this.copy_cell(); |
|
1059 | this.copy_cell(); | |
1052 | this.delete_cell(); |
|
1060 | this.delete_cell(); | |
1053 | } |
|
1061 | } | |
1054 |
|
1062 | |||
1055 | /** |
|
1063 | /** | |
1056 | * Copy a cell. |
|
1064 | * Copy a cell. | |
1057 | * |
|
1065 | * | |
1058 | * @method copy_cell |
|
1066 | * @method copy_cell | |
1059 | */ |
|
1067 | */ | |
1060 | Notebook.prototype.copy_cell = function () { |
|
1068 | Notebook.prototype.copy_cell = function () { | |
1061 | var cell = this.get_selected_cell(); |
|
1069 | var cell = this.get_selected_cell(); | |
1062 | this.clipboard = cell.toJSON(); |
|
1070 | this.clipboard = cell.toJSON(); | |
1063 | this.enable_paste(); |
|
1071 | this.enable_paste(); | |
1064 | }; |
|
1072 | }; | |
1065 |
|
1073 | |||
1066 | /** |
|
1074 | /** | |
1067 | * Replace the selected cell with a cell in the clipboard. |
|
1075 | * Replace the selected cell with a cell in the clipboard. | |
1068 | * |
|
1076 | * | |
1069 | * @method paste_cell_replace |
|
1077 | * @method paste_cell_replace | |
1070 | */ |
|
1078 | */ | |
1071 | Notebook.prototype.paste_cell_replace = function () { |
|
1079 | Notebook.prototype.paste_cell_replace = function () { | |
1072 | if (this.clipboard !== null && this.paste_enabled) { |
|
1080 | if (this.clipboard !== null && this.paste_enabled) { | |
1073 | var cell_data = this.clipboard; |
|
1081 | var cell_data = this.clipboard; | |
1074 | var new_cell = this.insert_cell_above(cell_data.cell_type); |
|
1082 | var new_cell = this.insert_cell_above(cell_data.cell_type); | |
1075 | new_cell.fromJSON(cell_data); |
|
1083 | new_cell.fromJSON(cell_data); | |
1076 | var old_cell = this.get_next_cell(new_cell); |
|
1084 | var old_cell = this.get_next_cell(new_cell); | |
1077 | this.delete_cell(this.find_cell_index(old_cell)); |
|
1085 | this.delete_cell(this.find_cell_index(old_cell)); | |
1078 | this.select(this.find_cell_index(new_cell)); |
|
1086 | this.select(this.find_cell_index(new_cell)); | |
1079 | }; |
|
1087 | }; | |
1080 | }; |
|
1088 | }; | |
1081 |
|
1089 | |||
1082 | /** |
|
1090 | /** | |
1083 | * Paste a cell from the clipboard above the selected cell. |
|
1091 | * Paste a cell from the clipboard above the selected cell. | |
1084 | * |
|
1092 | * | |
1085 | * @method paste_cell_above |
|
1093 | * @method paste_cell_above | |
1086 | */ |
|
1094 | */ | |
1087 | Notebook.prototype.paste_cell_above = function () { |
|
1095 | Notebook.prototype.paste_cell_above = function () { | |
1088 | if (this.clipboard !== null && this.paste_enabled) { |
|
1096 | if (this.clipboard !== null && this.paste_enabled) { | |
1089 | var cell_data = this.clipboard; |
|
1097 | var cell_data = this.clipboard; | |
1090 | var new_cell = this.insert_cell_above(cell_data.cell_type); |
|
1098 | var new_cell = this.insert_cell_above(cell_data.cell_type); | |
1091 | new_cell.fromJSON(cell_data); |
|
1099 | new_cell.fromJSON(cell_data); | |
1092 | }; |
|
1100 | }; | |
1093 | }; |
|
1101 | }; | |
1094 |
|
1102 | |||
1095 | /** |
|
1103 | /** | |
1096 | * Paste a cell from the clipboard below the selected cell. |
|
1104 | * Paste a cell from the clipboard below the selected cell. | |
1097 | * |
|
1105 | * | |
1098 | * @method paste_cell_below |
|
1106 | * @method paste_cell_below | |
1099 | */ |
|
1107 | */ | |
1100 | Notebook.prototype.paste_cell_below = function () { |
|
1108 | Notebook.prototype.paste_cell_below = function () { | |
1101 | if (this.clipboard !== null && this.paste_enabled) { |
|
1109 | if (this.clipboard !== null && this.paste_enabled) { | |
1102 | var cell_data = this.clipboard; |
|
1110 | var cell_data = this.clipboard; | |
1103 | var new_cell = this.insert_cell_below(cell_data.cell_type); |
|
1111 | var new_cell = this.insert_cell_below(cell_data.cell_type); | |
1104 | new_cell.fromJSON(cell_data); |
|
1112 | new_cell.fromJSON(cell_data); | |
1105 | }; |
|
1113 | }; | |
1106 | }; |
|
1114 | }; | |
1107 |
|
1115 | |||
1108 | // Cell undelete |
|
1116 | // Cell undelete | |
1109 |
|
1117 | |||
1110 | /** |
|
1118 | /** | |
1111 | * Restore the most recently deleted cell. |
|
1119 | * Restore the most recently deleted cell. | |
1112 | * |
|
1120 | * | |
1113 | * @method undelete |
|
1121 | * @method undelete | |
1114 | */ |
|
1122 | */ | |
1115 | Notebook.prototype.undelete = function() { |
|
1123 | Notebook.prototype.undelete = function() { | |
1116 | if (this.undelete_backup !== null && this.undelete_index !== null) { |
|
1124 | if (this.undelete_backup !== null && this.undelete_index !== null) { | |
1117 | var current_index = this.get_selected_index(); |
|
1125 | var current_index = this.get_selected_index(); | |
1118 | if (this.undelete_index < current_index) { |
|
1126 | if (this.undelete_index < current_index) { | |
1119 | current_index = current_index + 1; |
|
1127 | current_index = current_index + 1; | |
1120 | } |
|
1128 | } | |
1121 | if (this.undelete_index >= this.ncells()) { |
|
1129 | if (this.undelete_index >= this.ncells()) { | |
1122 | this.select(this.ncells() - 1); |
|
1130 | this.select(this.ncells() - 1); | |
1123 | } |
|
1131 | } | |
1124 | else { |
|
1132 | else { | |
1125 | this.select(this.undelete_index); |
|
1133 | this.select(this.undelete_index); | |
1126 | } |
|
1134 | } | |
1127 | var cell_data = this.undelete_backup; |
|
1135 | var cell_data = this.undelete_backup; | |
1128 | var new_cell = null; |
|
1136 | var new_cell = null; | |
1129 | if (this.undelete_below) { |
|
1137 | if (this.undelete_below) { | |
1130 | new_cell = this.insert_cell_below(cell_data.cell_type); |
|
1138 | new_cell = this.insert_cell_below(cell_data.cell_type); | |
1131 | } else { |
|
1139 | } else { | |
1132 | new_cell = this.insert_cell_above(cell_data.cell_type); |
|
1140 | new_cell = this.insert_cell_above(cell_data.cell_type); | |
1133 | } |
|
1141 | } | |
1134 | new_cell.fromJSON(cell_data); |
|
1142 | new_cell.fromJSON(cell_data); | |
1135 | this.select(current_index); |
|
1143 | this.select(current_index); | |
1136 | this.undelete_backup = null; |
|
1144 | this.undelete_backup = null; | |
1137 | this.undelete_index = null; |
|
1145 | this.undelete_index = null; | |
1138 | } |
|
1146 | } | |
1139 | $('#undelete_cell').addClass('disabled'); |
|
1147 | $('#undelete_cell').addClass('disabled'); | |
1140 | } |
|
1148 | } | |
1141 |
|
1149 | |||
1142 | // Split/merge |
|
1150 | // Split/merge | |
1143 |
|
1151 | |||
1144 | /** |
|
1152 | /** | |
1145 | * Split the selected cell into two, at the cursor. |
|
1153 | * Split the selected cell into two, at the cursor. | |
1146 | * |
|
1154 | * | |
1147 | * @method split_cell |
|
1155 | * @method split_cell | |
1148 | */ |
|
1156 | */ | |
1149 | Notebook.prototype.split_cell = function () { |
|
1157 | Notebook.prototype.split_cell = function () { | |
1150 | // Todo: implement spliting for other cell types. |
|
1158 | // Todo: implement spliting for other cell types. | |
1151 | var cell = this.get_selected_cell(); |
|
1159 | var cell = this.get_selected_cell(); | |
1152 | if (cell.is_splittable()) { |
|
1160 | if (cell.is_splittable()) { | |
1153 | var texta = cell.get_pre_cursor(); |
|
1161 | var texta = cell.get_pre_cursor(); | |
1154 | var textb = cell.get_post_cursor(); |
|
1162 | var textb = cell.get_post_cursor(); | |
1155 | if (cell instanceof IPython.CodeCell) { |
|
1163 | if (cell instanceof IPython.CodeCell) { | |
1156 | cell.set_text(texta); |
|
1164 | cell.set_text(texta); | |
1157 | var new_cell = this.insert_cell_below('code'); |
|
1165 | var new_cell = this.insert_cell_below('code'); | |
1158 | new_cell.set_text(textb); |
|
1166 | new_cell.set_text(textb); | |
1159 | } else if (cell instanceof IPython.MarkdownCell) { |
|
1167 | } else if (cell instanceof IPython.MarkdownCell) { | |
1160 | cell.set_text(texta); |
|
1168 | cell.set_text(texta); | |
1161 | cell.render(); |
|
1169 | cell.render(); | |
1162 | var new_cell = this.insert_cell_below('markdown'); |
|
1170 | var new_cell = this.insert_cell_below('markdown'); | |
1163 | new_cell.edit(); // editor must be visible to call set_text |
|
1171 | new_cell.edit(); // editor must be visible to call set_text | |
1164 | new_cell.set_text(textb); |
|
1172 | new_cell.set_text(textb); | |
1165 | new_cell.render(); |
|
1173 | new_cell.render(); | |
1166 | } |
|
1174 | } | |
1167 | }; |
|
1175 | }; | |
1168 | }; |
|
1176 | }; | |
1169 |
|
1177 | |||
1170 | /** |
|
1178 | /** | |
1171 | * Combine the selected cell into the cell above it. |
|
1179 | * Combine the selected cell into the cell above it. | |
1172 | * |
|
1180 | * | |
1173 | * @method merge_cell_above |
|
1181 | * @method merge_cell_above | |
1174 | */ |
|
1182 | */ | |
1175 | Notebook.prototype.merge_cell_above = function () { |
|
1183 | Notebook.prototype.merge_cell_above = function () { | |
1176 | var index = this.get_selected_index(); |
|
1184 | var index = this.get_selected_index(); | |
1177 | var cell = this.get_cell(index); |
|
1185 | var cell = this.get_cell(index); | |
1178 | if (!cell.is_mergeable()) { |
|
1186 | if (!cell.is_mergeable()) { | |
1179 | return; |
|
1187 | return; | |
1180 | } |
|
1188 | } | |
1181 | if (index > 0) { |
|
1189 | if (index > 0) { | |
1182 | var upper_cell = this.get_cell(index-1); |
|
1190 | var upper_cell = this.get_cell(index-1); | |
1183 | if (!upper_cell.is_mergeable()) { |
|
1191 | if (!upper_cell.is_mergeable()) { | |
1184 | return; |
|
1192 | return; | |
1185 | } |
|
1193 | } | |
1186 | var upper_text = upper_cell.get_text(); |
|
1194 | var upper_text = upper_cell.get_text(); | |
1187 | var text = cell.get_text(); |
|
1195 | var text = cell.get_text(); | |
1188 | if (cell instanceof IPython.CodeCell) { |
|
1196 | if (cell instanceof IPython.CodeCell) { | |
1189 | cell.set_text(upper_text+'\n'+text); |
|
1197 | cell.set_text(upper_text+'\n'+text); | |
1190 | } else if (cell instanceof IPython.MarkdownCell) { |
|
1198 | } else if (cell instanceof IPython.MarkdownCell) { | |
1191 | cell.edit(); |
|
1199 | cell.edit(); | |
1192 | cell.set_text(upper_text+'\n'+text); |
|
1200 | cell.set_text(upper_text+'\n'+text); | |
1193 | cell.render(); |
|
1201 | cell.render(); | |
1194 | }; |
|
1202 | }; | |
1195 | this.delete_cell(index-1); |
|
1203 | this.delete_cell(index-1); | |
1196 | this.select(this.find_cell_index(cell)); |
|
1204 | this.select(this.find_cell_index(cell)); | |
1197 | }; |
|
1205 | }; | |
1198 | }; |
|
1206 | }; | |
1199 |
|
1207 | |||
1200 | /** |
|
1208 | /** | |
1201 | * Combine the selected cell into the cell below it. |
|
1209 | * Combine the selected cell into the cell below it. | |
1202 | * |
|
1210 | * | |
1203 | * @method merge_cell_below |
|
1211 | * @method merge_cell_below | |
1204 | */ |
|
1212 | */ | |
1205 | Notebook.prototype.merge_cell_below = function () { |
|
1213 | Notebook.prototype.merge_cell_below = function () { | |
1206 | var index = this.get_selected_index(); |
|
1214 | var index = this.get_selected_index(); | |
1207 | var cell = this.get_cell(index); |
|
1215 | var cell = this.get_cell(index); | |
1208 | if (!cell.is_mergeable()) { |
|
1216 | if (!cell.is_mergeable()) { | |
1209 | return; |
|
1217 | return; | |
1210 | } |
|
1218 | } | |
1211 | if (index < this.ncells()-1) { |
|
1219 | if (index < this.ncells()-1) { | |
1212 | var lower_cell = this.get_cell(index+1); |
|
1220 | var lower_cell = this.get_cell(index+1); | |
1213 | if (!lower_cell.is_mergeable()) { |
|
1221 | if (!lower_cell.is_mergeable()) { | |
1214 | return; |
|
1222 | return; | |
1215 | } |
|
1223 | } | |
1216 | var lower_text = lower_cell.get_text(); |
|
1224 | var lower_text = lower_cell.get_text(); | |
1217 | var text = cell.get_text(); |
|
1225 | var text = cell.get_text(); | |
1218 | if (cell instanceof IPython.CodeCell) { |
|
1226 | if (cell instanceof IPython.CodeCell) { | |
1219 | cell.set_text(text+'\n'+lower_text); |
|
1227 | cell.set_text(text+'\n'+lower_text); | |
1220 | } else if (cell instanceof IPython.MarkdownCell) { |
|
1228 | } else if (cell instanceof IPython.MarkdownCell) { | |
1221 | cell.edit(); |
|
1229 | cell.edit(); | |
1222 | cell.set_text(text+'\n'+lower_text); |
|
1230 | cell.set_text(text+'\n'+lower_text); | |
1223 | cell.render(); |
|
1231 | cell.render(); | |
1224 | }; |
|
1232 | }; | |
1225 | this.delete_cell(index+1); |
|
1233 | this.delete_cell(index+1); | |
1226 | this.select(this.find_cell_index(cell)); |
|
1234 | this.select(this.find_cell_index(cell)); | |
1227 | }; |
|
1235 | }; | |
1228 | }; |
|
1236 | }; | |
1229 |
|
1237 | |||
1230 |
|
1238 | |||
1231 | // Cell collapsing and output clearing |
|
1239 | // Cell collapsing and output clearing | |
1232 |
|
1240 | |||
1233 | /** |
|
1241 | /** | |
1234 | * Hide a cell's output. |
|
1242 | * Hide a cell's output. | |
1235 | * |
|
1243 | * | |
1236 | * @method collapse |
|
1244 | * @method collapse | |
1237 | * @param {Number} index A cell's numeric index |
|
1245 | * @param {Number} index A cell's numeric index | |
1238 | */ |
|
1246 | */ | |
1239 | Notebook.prototype.collapse = function (index) { |
|
1247 | Notebook.prototype.collapse = function (index) { | |
1240 | var i = this.index_or_selected(index); |
|
1248 | var i = this.index_or_selected(index); | |
1241 | this.get_cell(i).collapse(); |
|
1249 | this.get_cell(i).collapse(); | |
1242 | this.set_dirty(true); |
|
1250 | this.set_dirty(true); | |
1243 | }; |
|
1251 | }; | |
1244 |
|
1252 | |||
1245 | /** |
|
1253 | /** | |
1246 | * Show a cell's output. |
|
1254 | * Show a cell's output. | |
1247 | * |
|
1255 | * | |
1248 | * @method expand |
|
1256 | * @method expand | |
1249 | * @param {Number} index A cell's numeric index |
|
1257 | * @param {Number} index A cell's numeric index | |
1250 | */ |
|
1258 | */ | |
1251 | Notebook.prototype.expand = function (index) { |
|
1259 | Notebook.prototype.expand = function (index) { | |
1252 | var i = this.index_or_selected(index); |
|
1260 | var i = this.index_or_selected(index); | |
1253 | this.get_cell(i).expand(); |
|
1261 | this.get_cell(i).expand(); | |
1254 | this.set_dirty(true); |
|
1262 | this.set_dirty(true); | |
1255 | }; |
|
1263 | }; | |
1256 |
|
1264 | |||
1257 | /** Toggle whether a cell's output is collapsed or expanded. |
|
1265 | /** Toggle whether a cell's output is collapsed or expanded. | |
1258 | * |
|
1266 | * | |
1259 | * @method toggle_output |
|
1267 | * @method toggle_output | |
1260 | * @param {Number} index A cell's numeric index |
|
1268 | * @param {Number} index A cell's numeric index | |
1261 | */ |
|
1269 | */ | |
1262 | Notebook.prototype.toggle_output = function (index) { |
|
1270 | Notebook.prototype.toggle_output = function (index) { | |
1263 | var i = this.index_or_selected(index); |
|
1271 | var i = this.index_or_selected(index); | |
1264 | this.get_cell(i).toggle_output(); |
|
1272 | this.get_cell(i).toggle_output(); | |
1265 | this.set_dirty(true); |
|
1273 | this.set_dirty(true); | |
1266 | }; |
|
1274 | }; | |
1267 |
|
1275 | |||
1268 | /** |
|
1276 | /** | |
1269 | * Toggle a scrollbar for long cell outputs. |
|
1277 | * Toggle a scrollbar for long cell outputs. | |
1270 | * |
|
1278 | * | |
1271 | * @method toggle_output_scroll |
|
1279 | * @method toggle_output_scroll | |
1272 | * @param {Number} index A cell's numeric index |
|
1280 | * @param {Number} index A cell's numeric index | |
1273 | */ |
|
1281 | */ | |
1274 | Notebook.prototype.toggle_output_scroll = function (index) { |
|
1282 | Notebook.prototype.toggle_output_scroll = function (index) { | |
1275 | var i = this.index_or_selected(index); |
|
1283 | var i = this.index_or_selected(index); | |
1276 | this.get_cell(i).toggle_output_scroll(); |
|
1284 | this.get_cell(i).toggle_output_scroll(); | |
1277 | }; |
|
1285 | }; | |
1278 |
|
1286 | |||
1279 | /** |
|
1287 | /** | |
1280 | * Hide each code cell's output area. |
|
1288 | * Hide each code cell's output area. | |
1281 | * |
|
1289 | * | |
1282 | * @method collapse_all_output |
|
1290 | * @method collapse_all_output | |
1283 | */ |
|
1291 | */ | |
1284 | Notebook.prototype.collapse_all_output = function () { |
|
1292 | Notebook.prototype.collapse_all_output = function () { | |
1285 | var ncells = this.ncells(); |
|
1293 | var ncells = this.ncells(); | |
1286 | var cells = this.get_cells(); |
|
1294 | var cells = this.get_cells(); | |
1287 | for (var i=0; i<ncells; i++) { |
|
1295 | for (var i=0; i<ncells; i++) { | |
1288 | if (cells[i] instanceof IPython.CodeCell) { |
|
1296 | if (cells[i] instanceof IPython.CodeCell) { | |
1289 | cells[i].output_area.collapse(); |
|
1297 | cells[i].output_area.collapse(); | |
1290 | } |
|
1298 | } | |
1291 | }; |
|
1299 | }; | |
1292 | // this should not be set if the `collapse` key is removed from nbformat |
|
1300 | // this should not be set if the `collapse` key is removed from nbformat | |
1293 | this.set_dirty(true); |
|
1301 | this.set_dirty(true); | |
1294 | }; |
|
1302 | }; | |
1295 |
|
1303 | |||
1296 | /** |
|
1304 | /** | |
1297 | * Expand each code cell's output area, and add a scrollbar for long output. |
|
1305 | * Expand each code cell's output area, and add a scrollbar for long output. | |
1298 | * |
|
1306 | * | |
1299 | * @method scroll_all_output |
|
1307 | * @method scroll_all_output | |
1300 | */ |
|
1308 | */ | |
1301 | Notebook.prototype.scroll_all_output = function () { |
|
1309 | Notebook.prototype.scroll_all_output = function () { | |
1302 | var ncells = this.ncells(); |
|
1310 | var ncells = this.ncells(); | |
1303 | var cells = this.get_cells(); |
|
1311 | var cells = this.get_cells(); | |
1304 | for (var i=0; i<ncells; i++) { |
|
1312 | for (var i=0; i<ncells; i++) { | |
1305 | if (cells[i] instanceof IPython.CodeCell) { |
|
1313 | if (cells[i] instanceof IPython.CodeCell) { | |
1306 | cells[i].output_area.expand(); |
|
1314 | cells[i].output_area.expand(); | |
1307 | cells[i].output_area.scroll_if_long(); |
|
1315 | cells[i].output_area.scroll_if_long(); | |
1308 | } |
|
1316 | } | |
1309 | }; |
|
1317 | }; | |
1310 | // this should not be set if the `collapse` key is removed from nbformat |
|
1318 | // this should not be set if the `collapse` key is removed from nbformat | |
1311 | this.set_dirty(true); |
|
1319 | this.set_dirty(true); | |
1312 | }; |
|
1320 | }; | |
1313 |
|
1321 | |||
1314 | /** |
|
1322 | /** | |
1315 | * Expand each code cell's output area, and remove scrollbars. |
|
1323 | * Expand each code cell's output area, and remove scrollbars. | |
1316 | * |
|
1324 | * | |
1317 | * @method expand_all_output |
|
1325 | * @method expand_all_output | |
1318 | */ |
|
1326 | */ | |
1319 | Notebook.prototype.expand_all_output = function () { |
|
1327 | Notebook.prototype.expand_all_output = function () { | |
1320 | var ncells = this.ncells(); |
|
1328 | var ncells = this.ncells(); | |
1321 | var cells = this.get_cells(); |
|
1329 | var cells = this.get_cells(); | |
1322 | for (var i=0; i<ncells; i++) { |
|
1330 | for (var i=0; i<ncells; i++) { | |
1323 | if (cells[i] instanceof IPython.CodeCell) { |
|
1331 | if (cells[i] instanceof IPython.CodeCell) { | |
1324 | cells[i].output_area.expand(); |
|
1332 | cells[i].output_area.expand(); | |
1325 | cells[i].output_area.unscroll_area(); |
|
1333 | cells[i].output_area.unscroll_area(); | |
1326 | } |
|
1334 | } | |
1327 | }; |
|
1335 | }; | |
1328 | // this should not be set if the `collapse` key is removed from nbformat |
|
1336 | // this should not be set if the `collapse` key is removed from nbformat | |
1329 | this.set_dirty(true); |
|
1337 | this.set_dirty(true); | |
1330 | }; |
|
1338 | }; | |
1331 |
|
1339 | |||
1332 | /** |
|
1340 | /** | |
1333 | * Clear each code cell's output area. |
|
1341 | * Clear each code cell's output area. | |
1334 | * |
|
1342 | * | |
1335 | * @method clear_all_output |
|
1343 | * @method clear_all_output | |
1336 | */ |
|
1344 | */ | |
1337 | Notebook.prototype.clear_all_output = function () { |
|
1345 | Notebook.prototype.clear_all_output = function () { | |
1338 | var ncells = this.ncells(); |
|
1346 | var ncells = this.ncells(); | |
1339 | var cells = this.get_cells(); |
|
1347 | var cells = this.get_cells(); | |
1340 | for (var i=0; i<ncells; i++) { |
|
1348 | for (var i=0; i<ncells; i++) { | |
1341 | if (cells[i] instanceof IPython.CodeCell) { |
|
1349 | if (cells[i] instanceof IPython.CodeCell) { | |
1342 | cells[i].clear_output(); |
|
1350 | cells[i].clear_output(); | |
1343 | // Make all In[] prompts blank, as well |
|
1351 | // Make all In[] prompts blank, as well | |
1344 | // TODO: make this configurable (via checkbox?) |
|
1352 | // TODO: make this configurable (via checkbox?) | |
1345 | cells[i].set_input_prompt(); |
|
1353 | cells[i].set_input_prompt(); | |
1346 | } |
|
1354 | } | |
1347 | }; |
|
1355 | }; | |
1348 | this.set_dirty(true); |
|
1356 | this.set_dirty(true); | |
1349 | }; |
|
1357 | }; | |
1350 |
|
1358 | |||
1351 |
|
1359 | |||
1352 | // Other cell functions: line numbers, ... |
|
1360 | // Other cell functions: line numbers, ... | |
1353 |
|
1361 | |||
1354 | /** |
|
1362 | /** | |
1355 | * Toggle line numbers in the selected cell's input area. |
|
1363 | * Toggle line numbers in the selected cell's input area. | |
1356 | * |
|
1364 | * | |
1357 | * @method cell_toggle_line_numbers |
|
1365 | * @method cell_toggle_line_numbers | |
1358 | */ |
|
1366 | */ | |
1359 | Notebook.prototype.cell_toggle_line_numbers = function() { |
|
1367 | Notebook.prototype.cell_toggle_line_numbers = function() { | |
1360 | this.get_selected_cell().toggle_line_numbers(); |
|
1368 | this.get_selected_cell().toggle_line_numbers(); | |
1361 | }; |
|
1369 | }; | |
1362 |
|
1370 | |||
1363 | // Kernel related things |
|
1371 | // Kernel related things | |
1364 |
|
1372 | |||
1365 | /** |
|
1373 | /** | |
1366 | * Start a new kernel and set it on each code cell. |
|
1374 | * Start a new kernel and set it on each code cell. | |
1367 | * |
|
1375 | * | |
1368 | * @method start_kernel |
|
1376 | * @method start_kernel | |
1369 | */ |
|
1377 | */ | |
1370 | Notebook.prototype.start_kernel = function () { |
|
1378 | Notebook.prototype.start_kernel = function () { | |
1371 | var base_url = $('body').data('baseKernelUrl') + "kernels"; |
|
1379 | var base_url = $('body').data('baseKernelUrl') + "kernels"; | |
1372 | this.kernel = new IPython.Kernel(base_url); |
|
1380 | this.kernel = new IPython.Kernel(base_url); | |
1373 | this.kernel.start({notebook: this.notebook_id}); |
|
1381 | this.kernel.start({notebook: this.notebook_id}); | |
1374 | // Now that the kernel has been created, tell the CodeCells about it. |
|
1382 | // Now that the kernel has been created, tell the CodeCells about it. | |
1375 | var ncells = this.ncells(); |
|
1383 | var ncells = this.ncells(); | |
1376 | for (var i=0; i<ncells; i++) { |
|
1384 | for (var i=0; i<ncells; i++) { | |
1377 | var cell = this.get_cell(i); |
|
1385 | var cell = this.get_cell(i); | |
1378 | if (cell instanceof IPython.CodeCell) { |
|
1386 | if (cell instanceof IPython.CodeCell) { | |
1379 | cell.set_kernel(this.kernel) |
|
1387 | cell.set_kernel(this.kernel) | |
1380 | }; |
|
1388 | }; | |
1381 | }; |
|
1389 | }; | |
1382 | }; |
|
1390 | }; | |
1383 |
|
1391 | |||
1384 | /** |
|
1392 | /** | |
1385 | * Prompt the user to restart the IPython kernel. |
|
1393 | * Prompt the user to restart the IPython kernel. | |
1386 | * |
|
1394 | * | |
1387 | * @method restart_kernel |
|
1395 | * @method restart_kernel | |
1388 | */ |
|
1396 | */ | |
1389 | Notebook.prototype.restart_kernel = function () { |
|
1397 | Notebook.prototype.restart_kernel = function () { | |
1390 | var that = this; |
|
1398 | var that = this; | |
1391 | IPython.dialog.modal({ |
|
1399 | IPython.dialog.modal({ | |
1392 | title : "Restart kernel or continue running?", |
|
1400 | title : "Restart kernel or continue running?", | |
1393 | body : $("<p/>").html( |
|
1401 | body : $("<p/>").html( | |
1394 | 'Do you want to restart the current kernel? You will lose all variables defined in it.' |
|
1402 | 'Do you want to restart the current kernel? You will lose all variables defined in it.' | |
1395 | ), |
|
1403 | ), | |
1396 | buttons : { |
|
1404 | buttons : { | |
1397 | "Continue running" : {}, |
|
1405 | "Continue running" : {}, | |
1398 | "Restart" : { |
|
1406 | "Restart" : { | |
1399 | "class" : "btn-danger", |
|
1407 | "class" : "btn-danger", | |
1400 | "click" : function() { |
|
1408 | "click" : function() { | |
1401 | that.kernel.restart(); |
|
1409 | that.kernel.restart(); | |
1402 | } |
|
1410 | } | |
1403 | } |
|
1411 | } | |
1404 | } |
|
1412 | } | |
1405 | }); |
|
1413 | }); | |
1406 | }; |
|
1414 | }; | |
1407 |
|
1415 | |||
1408 | /** |
|
1416 | /** | |
1409 | * Run the selected cell. |
|
1417 | * Run the selected cell. | |
1410 | * |
|
1418 | * | |
1411 | * Execute or render cell outputs. |
|
1419 | * Execute or render cell outputs. | |
1412 | * |
|
1420 | * | |
1413 | * @method execute_selected_cell |
|
1421 | * @method execute_selected_cell | |
1414 | * @param {Object} options Customize post-execution behavior |
|
1422 | * @param {Object} options Customize post-execution behavior | |
1415 | */ |
|
1423 | */ | |
1416 | Notebook.prototype.execute_selected_cell = function (options) { |
|
1424 | Notebook.prototype.execute_selected_cell = function (options) { | |
1417 | // add_new: should a new cell be added if we are at the end of the nb |
|
1425 | // add_new: should a new cell be added if we are at the end of the nb | |
1418 | // terminal: execute in terminal mode, which stays in the current cell |
|
1426 | // terminal: execute in terminal mode, which stays in the current cell | |
1419 | var default_options = {terminal: false, add_new: true}; |
|
1427 | var default_options = {terminal: false, add_new: true}; | |
1420 | $.extend(default_options, options); |
|
1428 | $.extend(default_options, options); | |
1421 | var that = this; |
|
1429 | var that = this; | |
1422 | var cell = that.get_selected_cell(); |
|
1430 | var cell = that.get_selected_cell(); | |
1423 | var cell_index = that.find_cell_index(cell); |
|
1431 | var cell_index = that.find_cell_index(cell); | |
1424 | if (cell instanceof IPython.CodeCell) { |
|
1432 | if (cell instanceof IPython.CodeCell) { | |
1425 | cell.execute(); |
|
1433 | cell.execute(); | |
1426 | } |
|
1434 | } | |
1427 | if (default_options.terminal) { |
|
1435 | if (default_options.terminal) { | |
1428 | cell.select_all(); |
|
1436 | cell.select_all(); | |
1429 | } else { |
|
1437 | } else { | |
1430 | if ((cell_index === (that.ncells()-1)) && default_options.add_new) { |
|
1438 | if ((cell_index === (that.ncells()-1)) && default_options.add_new) { | |
1431 | that.insert_cell_below('code'); |
|
1439 | that.insert_cell_below('code'); | |
1432 | // If we are adding a new cell at the end, scroll down to show it. |
|
1440 | // If we are adding a new cell at the end, scroll down to show it. | |
1433 | that.scroll_to_bottom(); |
|
1441 | that.scroll_to_bottom(); | |
1434 | } else { |
|
1442 | } else { | |
1435 | that.select(cell_index+1); |
|
1443 | that.select(cell_index+1); | |
1436 | }; |
|
1444 | }; | |
1437 | }; |
|
1445 | }; | |
1438 | this.set_dirty(true); |
|
1446 | this.set_dirty(true); | |
1439 | }; |
|
1447 | }; | |
1440 |
|
1448 | |||
1441 | /** |
|
1449 | /** | |
1442 | * Execute all cells below the selected cell. |
|
1450 | * Execute all cells below the selected cell. | |
1443 | * |
|
1451 | * | |
1444 | * @method execute_cells_below |
|
1452 | * @method execute_cells_below | |
1445 | */ |
|
1453 | */ | |
1446 | Notebook.prototype.execute_cells_below = function () { |
|
1454 | Notebook.prototype.execute_cells_below = function () { | |
1447 | this.execute_cell_range(this.get_selected_index(), this.ncells()); |
|
1455 | this.execute_cell_range(this.get_selected_index(), this.ncells()); | |
1448 | this.scroll_to_bottom(); |
|
1456 | this.scroll_to_bottom(); | |
1449 | }; |
|
1457 | }; | |
1450 |
|
1458 | |||
1451 | /** |
|
1459 | /** | |
1452 | * Execute all cells above the selected cell. |
|
1460 | * Execute all cells above the selected cell. | |
1453 | * |
|
1461 | * | |
1454 | * @method execute_cells_above |
|
1462 | * @method execute_cells_above | |
1455 | */ |
|
1463 | */ | |
1456 | Notebook.prototype.execute_cells_above = function () { |
|
1464 | Notebook.prototype.execute_cells_above = function () { | |
1457 | this.execute_cell_range(0, this.get_selected_index()); |
|
1465 | this.execute_cell_range(0, this.get_selected_index()); | |
1458 | }; |
|
1466 | }; | |
1459 |
|
1467 | |||
1460 | /** |
|
1468 | /** | |
1461 | * Execute all cells. |
|
1469 | * Execute all cells. | |
1462 | * |
|
1470 | * | |
1463 | * @method execute_all_cells |
|
1471 | * @method execute_all_cells | |
1464 | */ |
|
1472 | */ | |
1465 | Notebook.prototype.execute_all_cells = function () { |
|
1473 | Notebook.prototype.execute_all_cells = function () { | |
1466 | this.execute_cell_range(0, this.ncells()); |
|
1474 | this.execute_cell_range(0, this.ncells()); | |
1467 | this.scroll_to_bottom(); |
|
1475 | this.scroll_to_bottom(); | |
1468 | }; |
|
1476 | }; | |
1469 |
|
1477 | |||
1470 | /** |
|
1478 | /** | |
1471 | * Execute a contiguous range of cells. |
|
1479 | * Execute a contiguous range of cells. | |
1472 | * |
|
1480 | * | |
1473 | * @method execute_cell_range |
|
1481 | * @method execute_cell_range | |
1474 | * @param {Number} start Index of the first cell to execute (inclusive) |
|
1482 | * @param {Number} start Index of the first cell to execute (inclusive) | |
1475 | * @param {Number} end Index of the last cell to execute (exclusive) |
|
1483 | * @param {Number} end Index of the last cell to execute (exclusive) | |
1476 | */ |
|
1484 | */ | |
1477 | Notebook.prototype.execute_cell_range = function (start, end) { |
|
1485 | Notebook.prototype.execute_cell_range = function (start, end) { | |
1478 | for (var i=start; i<end; i++) { |
|
1486 | for (var i=start; i<end; i++) { | |
1479 | this.select(i); |
|
1487 | this.select(i); | |
1480 | this.execute_selected_cell({add_new:false}); |
|
1488 | this.execute_selected_cell({add_new:false}); | |
1481 | }; |
|
1489 | }; | |
1482 | }; |
|
1490 | }; | |
1483 |
|
1491 | |||
1484 | // Persistance and loading |
|
1492 | // Persistance and loading | |
1485 |
|
1493 | |||
1486 | /** |
|
1494 | /** | |
1487 | * Getter method for this notebook's ID. |
|
1495 | * Getter method for this notebook's ID. | |
1488 | * |
|
1496 | * | |
1489 | * @method get_notebook_id |
|
1497 | * @method get_notebook_id | |
1490 | * @return {String} This notebook's ID |
|
1498 | * @return {String} This notebook's ID | |
1491 | */ |
|
1499 | */ | |
1492 | Notebook.prototype.get_notebook_id = function () { |
|
1500 | Notebook.prototype.get_notebook_id = function () { | |
1493 | return this.notebook_id; |
|
1501 | return this.notebook_id; | |
1494 | }; |
|
1502 | }; | |
1495 |
|
1503 | |||
1496 | /** |
|
1504 | /** | |
1497 | * Getter method for this notebook's name. |
|
1505 | * Getter method for this notebook's name. | |
1498 | * |
|
1506 | * | |
1499 | * @method get_notebook_name |
|
1507 | * @method get_notebook_name | |
1500 | * @return {String} This notebook's name |
|
1508 | * @return {String} This notebook's name | |
1501 | */ |
|
1509 | */ | |
1502 | Notebook.prototype.get_notebook_name = function () { |
|
1510 | Notebook.prototype.get_notebook_name = function () { | |
1503 | return this.notebook_name; |
|
1511 | return this.notebook_name; | |
1504 | }; |
|
1512 | }; | |
1505 |
|
1513 | |||
1506 | /** |
|
1514 | /** | |
1507 | * Setter method for this notebook's name. |
|
1515 | * Setter method for this notebook's name. | |
1508 | * |
|
1516 | * | |
1509 | * @method set_notebook_name |
|
1517 | * @method set_notebook_name | |
1510 | * @param {String} name A new name for this notebook |
|
1518 | * @param {String} name A new name for this notebook | |
1511 | */ |
|
1519 | */ | |
1512 | Notebook.prototype.set_notebook_name = function (name) { |
|
1520 | Notebook.prototype.set_notebook_name = function (name) { | |
1513 | this.notebook_name = name; |
|
1521 | this.notebook_name = name; | |
1514 | }; |
|
1522 | }; | |
1515 |
|
1523 | |||
1516 | /** |
|
1524 | /** | |
1517 | * Check that a notebook's name is valid. |
|
1525 | * Check that a notebook's name is valid. | |
1518 | * |
|
1526 | * | |
1519 | * @method test_notebook_name |
|
1527 | * @method test_notebook_name | |
1520 | * @param {String} nbname A name for this notebook |
|
1528 | * @param {String} nbname A name for this notebook | |
1521 | * @return {Boolean} True if the name is valid, false if invalid |
|
1529 | * @return {Boolean} True if the name is valid, false if invalid | |
1522 | */ |
|
1530 | */ | |
1523 | Notebook.prototype.test_notebook_name = function (nbname) { |
|
1531 | Notebook.prototype.test_notebook_name = function (nbname) { | |
1524 | nbname = nbname || ''; |
|
1532 | nbname = nbname || ''; | |
1525 | if (this.notebook_name_blacklist_re.test(nbname) == false && nbname.length>0) { |
|
1533 | if (this.notebook_name_blacklist_re.test(nbname) == false && nbname.length>0) { | |
1526 | return true; |
|
1534 | return true; | |
1527 | } else { |
|
1535 | } else { | |
1528 | return false; |
|
1536 | return false; | |
1529 | }; |
|
1537 | }; | |
1530 | }; |
|
1538 | }; | |
1531 |
|
1539 | |||
1532 | /** |
|
1540 | /** | |
1533 | * Load a notebook from JSON (.ipynb). |
|
1541 | * Load a notebook from JSON (.ipynb). | |
1534 | * |
|
1542 | * | |
1535 | * This currently handles one worksheet: others are deleted. |
|
1543 | * This currently handles one worksheet: others are deleted. | |
1536 | * |
|
1544 | * | |
1537 | * @method fromJSON |
|
1545 | * @method fromJSON | |
1538 | * @param {Object} data JSON representation of a notebook |
|
1546 | * @param {Object} data JSON representation of a notebook | |
1539 | */ |
|
1547 | */ | |
1540 | Notebook.prototype.fromJSON = function (data) { |
|
1548 | Notebook.prototype.fromJSON = function (data) { | |
1541 | var ncells = this.ncells(); |
|
1549 | var ncells = this.ncells(); | |
1542 | var i; |
|
1550 | var i; | |
1543 | for (i=0; i<ncells; i++) { |
|
1551 | for (i=0; i<ncells; i++) { | |
1544 | // Always delete cell 0 as they get renumbered as they are deleted. |
|
1552 | // Always delete cell 0 as they get renumbered as they are deleted. | |
1545 | this.delete_cell(0); |
|
1553 | this.delete_cell(0); | |
1546 | }; |
|
1554 | }; | |
1547 | // Save the metadata and name. |
|
1555 | // Save the metadata and name. | |
1548 | this.metadata = data.metadata; |
|
1556 | this.metadata = data.metadata; | |
1549 | this.notebook_name = data.metadata.name; |
|
1557 | this.notebook_name = data.metadata.name; | |
1550 | // Only handle 1 worksheet for now. |
|
1558 | // Only handle 1 worksheet for now. | |
1551 | var worksheet = data.worksheets[0]; |
|
1559 | var worksheet = data.worksheets[0]; | |
1552 | if (worksheet !== undefined) { |
|
1560 | if (worksheet !== undefined) { | |
1553 | if (worksheet.metadata) { |
|
1561 | if (worksheet.metadata) { | |
1554 | this.worksheet_metadata = worksheet.metadata; |
|
1562 | this.worksheet_metadata = worksheet.metadata; | |
1555 | } |
|
1563 | } | |
1556 | var new_cells = worksheet.cells; |
|
1564 | var new_cells = worksheet.cells; | |
1557 | ncells = new_cells.length; |
|
1565 | ncells = new_cells.length; | |
1558 | var cell_data = null; |
|
1566 | var cell_data = null; | |
1559 | var new_cell = null; |
|
1567 | var new_cell = null; | |
1560 | for (i=0; i<ncells; i++) { |
|
1568 | for (i=0; i<ncells; i++) { | |
1561 | cell_data = new_cells[i]; |
|
1569 | cell_data = new_cells[i]; | |
1562 | // VERSIONHACK: plaintext -> raw |
|
1570 | // VERSIONHACK: plaintext -> raw | |
1563 | // handle never-released plaintext name for raw cells |
|
1571 | // handle never-released plaintext name for raw cells | |
1564 | if (cell_data.cell_type === 'plaintext'){ |
|
1572 | if (cell_data.cell_type === 'plaintext'){ | |
1565 | cell_data.cell_type = 'raw'; |
|
1573 | cell_data.cell_type = 'raw'; | |
1566 | } |
|
1574 | } | |
1567 |
|
1575 | |||
1568 | new_cell = this.insert_cell_below(cell_data.cell_type); |
|
1576 | new_cell = this.insert_cell_below(cell_data.cell_type); | |
1569 | new_cell.fromJSON(cell_data); |
|
1577 | new_cell.fromJSON(cell_data); | |
1570 | }; |
|
1578 | }; | |
1571 | }; |
|
1579 | }; | |
1572 | if (data.worksheets.length > 1) { |
|
1580 | if (data.worksheets.length > 1) { | |
1573 | IPython.dialog.modal({ |
|
1581 | IPython.dialog.modal({ | |
1574 | title : "Multiple worksheets", |
|
1582 | title : "Multiple worksheets", | |
1575 | body : "This notebook has " + data.worksheets.length + " worksheets, " + |
|
1583 | body : "This notebook has " + data.worksheets.length + " worksheets, " + | |
1576 | "but this version of IPython can only handle the first. " + |
|
1584 | "but this version of IPython can only handle the first. " + | |
1577 | "If you save this notebook, worksheets after the first will be lost.", |
|
1585 | "If you save this notebook, worksheets after the first will be lost.", | |
1578 | buttons : { |
|
1586 | buttons : { | |
1579 | OK : { |
|
1587 | OK : { | |
1580 | class : "btn-danger" |
|
1588 | class : "btn-danger" | |
1581 | } |
|
1589 | } | |
1582 | } |
|
1590 | } | |
1583 | }); |
|
1591 | }); | |
1584 | } |
|
1592 | } | |
1585 | }; |
|
1593 | }; | |
1586 |
|
1594 | |||
1587 | /** |
|
1595 | /** | |
1588 | * Dump this notebook into a JSON-friendly object. |
|
1596 | * Dump this notebook into a JSON-friendly object. | |
1589 | * |
|
1597 | * | |
1590 | * @method toJSON |
|
1598 | * @method toJSON | |
1591 | * @return {Object} A JSON-friendly representation of this notebook. |
|
1599 | * @return {Object} A JSON-friendly representation of this notebook. | |
1592 | */ |
|
1600 | */ | |
1593 | Notebook.prototype.toJSON = function () { |
|
1601 | Notebook.prototype.toJSON = function () { | |
1594 | var cells = this.get_cells(); |
|
1602 | var cells = this.get_cells(); | |
1595 | var ncells = cells.length; |
|
1603 | var ncells = cells.length; | |
1596 | var cell_array = new Array(ncells); |
|
1604 | var cell_array = new Array(ncells); | |
1597 | for (var i=0; i<ncells; i++) { |
|
1605 | for (var i=0; i<ncells; i++) { | |
1598 | cell_array[i] = cells[i].toJSON(); |
|
1606 | cell_array[i] = cells[i].toJSON(); | |
1599 | }; |
|
1607 | }; | |
1600 | var data = { |
|
1608 | var data = { | |
1601 | // Only handle 1 worksheet for now. |
|
1609 | // Only handle 1 worksheet for now. | |
1602 | worksheets : [{ |
|
1610 | worksheets : [{ | |
1603 | cells: cell_array, |
|
1611 | cells: cell_array, | |
1604 | metadata: this.worksheet_metadata |
|
1612 | metadata: this.worksheet_metadata | |
1605 | }], |
|
1613 | }], | |
1606 | metadata : this.metadata |
|
1614 | metadata : this.metadata | |
1607 | }; |
|
1615 | }; | |
1608 | return data; |
|
1616 | return data; | |
1609 | }; |
|
1617 | }; | |
1610 |
|
1618 | |||
1611 | /** |
|
1619 | /** | |
1612 | * Start an autosave timer, for periodically saving the notebook. |
|
1620 | * Start an autosave timer, for periodically saving the notebook. | |
1613 | * |
|
1621 | * | |
1614 | * @method set_autosave_interval |
|
1622 | * @method set_autosave_interval | |
1615 | * @param {Integer} interval the autosave interval in milliseconds |
|
1623 | * @param {Integer} interval the autosave interval in milliseconds | |
1616 | */ |
|
1624 | */ | |
1617 | Notebook.prototype.set_autosave_interval = function (interval) { |
|
1625 | Notebook.prototype.set_autosave_interval = function (interval) { | |
1618 | var that = this; |
|
1626 | var that = this; | |
1619 | // clear previous interval, so we don't get simultaneous timers |
|
1627 | // clear previous interval, so we don't get simultaneous timers | |
1620 | if (this.autosave_timer) { |
|
1628 | if (this.autosave_timer) { | |
1621 | clearInterval(this.autosave_timer); |
|
1629 | clearInterval(this.autosave_timer); | |
1622 | } |
|
1630 | } | |
1623 |
|
1631 | |||
1624 | this.autosave_interval = this.minimum_autosave_interval = interval; |
|
1632 | this.autosave_interval = this.minimum_autosave_interval = interval; | |
1625 | if (interval) { |
|
1633 | if (interval) { | |
1626 | this.autosave_timer = setInterval(function() { |
|
1634 | this.autosave_timer = setInterval(function() { | |
1627 | if (that.dirty) { |
|
1635 | if (that.dirty) { | |
1628 | that.save_notebook(); |
|
1636 | that.save_notebook(); | |
1629 | } |
|
1637 | } | |
1630 | }, interval); |
|
1638 | }, interval); | |
1631 | $([IPython.events]).trigger("autosave_enabled.Notebook", interval); |
|
1639 | $([IPython.events]).trigger("autosave_enabled.Notebook", interval); | |
1632 | } else { |
|
1640 | } else { | |
1633 | this.autosave_timer = null; |
|
1641 | this.autosave_timer = null; | |
1634 | $([IPython.events]).trigger("autosave_disabled.Notebook"); |
|
1642 | $([IPython.events]).trigger("autosave_disabled.Notebook"); | |
1635 | }; |
|
1643 | }; | |
1636 | }; |
|
1644 | }; | |
1637 |
|
1645 | |||
1638 | /** |
|
1646 | /** | |
1639 | * Save this notebook on the server. |
|
1647 | * Save this notebook on the server. | |
1640 | * |
|
1648 | * | |
1641 | * @method save_notebook |
|
1649 | * @method save_notebook | |
1642 | */ |
|
1650 | */ | |
1643 | Notebook.prototype.save_notebook = function () { |
|
1651 | Notebook.prototype.save_notebook = function () { | |
1644 | // We may want to move the name/id/nbformat logic inside toJSON? |
|
1652 | // We may want to move the name/id/nbformat logic inside toJSON? | |
1645 | var data = this.toJSON(); |
|
1653 | var data = this.toJSON(); | |
1646 | data.metadata.name = this.notebook_name; |
|
1654 | data.metadata.name = this.notebook_name; | |
1647 | data.nbformat = this.nbformat; |
|
1655 | data.nbformat = this.nbformat; | |
1648 | data.nbformat_minor = this.nbformat_minor; |
|
1656 | data.nbformat_minor = this.nbformat_minor; | |
1649 |
|
1657 | |||
1650 | // time the ajax call for autosave tuning purposes. |
|
1658 | // time the ajax call for autosave tuning purposes. | |
1651 | var start = new Date().getTime(); |
|
1659 | var start = new Date().getTime(); | |
1652 |
|
1660 | |||
1653 | // We do the call with settings so we can set cache to false. |
|
1661 | // We do the call with settings so we can set cache to false. | |
1654 | var settings = { |
|
1662 | var settings = { | |
1655 | processData : false, |
|
1663 | processData : false, | |
1656 | cache : false, |
|
1664 | cache : false, | |
1657 | type : "PUT", |
|
1665 | type : "PUT", | |
1658 | data : JSON.stringify(data), |
|
1666 | data : JSON.stringify(data), | |
1659 | headers : {'Content-Type': 'application/json'}, |
|
1667 | headers : {'Content-Type': 'application/json'}, | |
1660 | success : $.proxy(this.save_notebook_success, this, start), |
|
1668 | success : $.proxy(this.save_notebook_success, this, start), | |
1661 | error : $.proxy(this.save_notebook_error, this) |
|
1669 | error : $.proxy(this.save_notebook_error, this) | |
1662 | }; |
|
1670 | }; | |
1663 | $([IPython.events]).trigger('notebook_saving.Notebook'); |
|
1671 | $([IPython.events]).trigger('notebook_saving.Notebook'); | |
1664 | var url = this.baseProjectUrl() + 'notebooks/' + this.notebook_id; |
|
1672 | var url = this.baseProjectUrl() + 'notebooks/' + this.notebook_id; | |
1665 | $.ajax(url, settings); |
|
1673 | $.ajax(url, settings); | |
1666 | }; |
|
1674 | }; | |
1667 |
|
1675 | |||
1668 | /** |
|
1676 | /** | |
1669 | * Success callback for saving a notebook. |
|
1677 | * Success callback for saving a notebook. | |
1670 | * |
|
1678 | * | |
1671 | * @method save_notebook_success |
|
1679 | * @method save_notebook_success | |
1672 | * @param {Integer} start the time when the save request started |
|
1680 | * @param {Integer} start the time when the save request started | |
1673 | * @param {Object} data JSON representation of a notebook |
|
1681 | * @param {Object} data JSON representation of a notebook | |
1674 | * @param {String} status Description of response status |
|
1682 | * @param {String} status Description of response status | |
1675 | * @param {jqXHR} xhr jQuery Ajax object |
|
1683 | * @param {jqXHR} xhr jQuery Ajax object | |
1676 | */ |
|
1684 | */ | |
1677 | Notebook.prototype.save_notebook_success = function (start, data, status, xhr) { |
|
1685 | Notebook.prototype.save_notebook_success = function (start, data, status, xhr) { | |
1678 | this.set_dirty(false); |
|
1686 | this.set_dirty(false); | |
1679 | $([IPython.events]).trigger('notebook_saved.Notebook'); |
|
1687 | $([IPython.events]).trigger('notebook_saved.Notebook'); | |
1680 | this._update_autosave_interval(start); |
|
1688 | this._update_autosave_interval(start); | |
1681 | if (this._checkpoint_after_save) { |
|
1689 | if (this._checkpoint_after_save) { | |
1682 | this.create_checkpoint(); |
|
1690 | this.create_checkpoint(); | |
1683 | this._checkpoint_after_save = false; |
|
1691 | this._checkpoint_after_save = false; | |
1684 | }; |
|
1692 | }; | |
1685 | }; |
|
1693 | }; | |
1686 |
|
1694 | |||
1687 | /** |
|
1695 | /** | |
1688 | * update the autosave interval based on how long the last save took |
|
1696 | * update the autosave interval based on how long the last save took | |
1689 | * |
|
1697 | * | |
1690 | * @method _update_autosave_interval |
|
1698 | * @method _update_autosave_interval | |
1691 | * @param {Integer} timestamp when the save request started |
|
1699 | * @param {Integer} timestamp when the save request started | |
1692 | */ |
|
1700 | */ | |
1693 | Notebook.prototype._update_autosave_interval = function (start) { |
|
1701 | Notebook.prototype._update_autosave_interval = function (start) { | |
1694 | var duration = (new Date().getTime() - start); |
|
1702 | var duration = (new Date().getTime() - start); | |
1695 | if (this.autosave_interval) { |
|
1703 | if (this.autosave_interval) { | |
1696 | // new save interval: higher of 10x save duration or parameter (default 30 seconds) |
|
1704 | // new save interval: higher of 10x save duration or parameter (default 30 seconds) | |
1697 | var interval = Math.max(10 * duration, this.minimum_autosave_interval); |
|
1705 | var interval = Math.max(10 * duration, this.minimum_autosave_interval); | |
1698 | // round to 10 seconds, otherwise we will be setting a new interval too often |
|
1706 | // round to 10 seconds, otherwise we will be setting a new interval too often | |
1699 | interval = 10000 * Math.round(interval / 10000); |
|
1707 | interval = 10000 * Math.round(interval / 10000); | |
1700 | // set new interval, if it's changed |
|
1708 | // set new interval, if it's changed | |
1701 | if (interval != this.autosave_interval) { |
|
1709 | if (interval != this.autosave_interval) { | |
1702 | this.set_autosave_interval(interval); |
|
1710 | this.set_autosave_interval(interval); | |
1703 | } |
|
1711 | } | |
1704 | } |
|
1712 | } | |
1705 | }; |
|
1713 | }; | |
1706 |
|
1714 | |||
1707 | /** |
|
1715 | /** | |
1708 | * Failure callback for saving a notebook. |
|
1716 | * Failure callback for saving a notebook. | |
1709 | * |
|
1717 | * | |
1710 | * @method save_notebook_error |
|
1718 | * @method save_notebook_error | |
1711 | * @param {jqXHR} xhr jQuery Ajax object |
|
1719 | * @param {jqXHR} xhr jQuery Ajax object | |
1712 | * @param {String} status Description of response status |
|
1720 | * @param {String} status Description of response status | |
1713 | * @param {String} error_msg HTTP error message |
|
1721 | * @param {String} error_msg HTTP error message | |
1714 | */ |
|
1722 | */ | |
1715 | Notebook.prototype.save_notebook_error = function (xhr, status, error_msg) { |
|
1723 | Notebook.prototype.save_notebook_error = function (xhr, status, error_msg) { | |
1716 | $([IPython.events]).trigger('notebook_save_failed.Notebook'); |
|
1724 | $([IPython.events]).trigger('notebook_save_failed.Notebook'); | |
1717 | }; |
|
1725 | }; | |
1718 |
|
1726 | |||
1719 | /** |
|
1727 | /** | |
1720 | * Request a notebook's data from the server. |
|
1728 | * Request a notebook's data from the server. | |
1721 | * |
|
1729 | * | |
1722 | * @method load_notebook |
|
1730 | * @method load_notebook | |
1723 | * @param {String} notebook_id A notebook to load |
|
1731 | * @param {String} notebook_id A notebook to load | |
1724 | */ |
|
1732 | */ | |
1725 | Notebook.prototype.load_notebook = function (notebook_id) { |
|
1733 | Notebook.prototype.load_notebook = function (notebook_id) { | |
1726 | var that = this; |
|
1734 | var that = this; | |
1727 | this.notebook_id = notebook_id; |
|
1735 | this.notebook_id = notebook_id; | |
1728 | // We do the call with settings so we can set cache to false. |
|
1736 | // We do the call with settings so we can set cache to false. | |
1729 | var settings = { |
|
1737 | var settings = { | |
1730 | processData : false, |
|
1738 | processData : false, | |
1731 | cache : false, |
|
1739 | cache : false, | |
1732 | type : "GET", |
|
1740 | type : "GET", | |
1733 | dataType : "json", |
|
1741 | dataType : "json", | |
1734 | success : $.proxy(this.load_notebook_success,this), |
|
1742 | success : $.proxy(this.load_notebook_success,this), | |
1735 | error : $.proxy(this.load_notebook_error,this), |
|
1743 | error : $.proxy(this.load_notebook_error,this), | |
1736 | }; |
|
1744 | }; | |
1737 | $([IPython.events]).trigger('notebook_loading.Notebook'); |
|
1745 | $([IPython.events]).trigger('notebook_loading.Notebook'); | |
1738 | var url = this.baseProjectUrl() + 'notebooks/' + this.notebook_id; |
|
1746 | var url = this.baseProjectUrl() + 'notebooks/' + this.notebook_id; | |
1739 | $.ajax(url, settings); |
|
1747 | $.ajax(url, settings); | |
1740 | }; |
|
1748 | }; | |
1741 |
|
1749 | |||
1742 | /** |
|
1750 | /** | |
1743 | * Success callback for loading a notebook from the server. |
|
1751 | * Success callback for loading a notebook from the server. | |
1744 | * |
|
1752 | * | |
1745 | * Load notebook data from the JSON response. |
|
1753 | * Load notebook data from the JSON response. | |
1746 | * |
|
1754 | * | |
1747 | * @method load_notebook_success |
|
1755 | * @method load_notebook_success | |
1748 | * @param {Object} data JSON representation of a notebook |
|
1756 | * @param {Object} data JSON representation of a notebook | |
1749 | * @param {String} status Description of response status |
|
1757 | * @param {String} status Description of response status | |
1750 | * @param {jqXHR} xhr jQuery Ajax object |
|
1758 | * @param {jqXHR} xhr jQuery Ajax object | |
1751 | */ |
|
1759 | */ | |
1752 | Notebook.prototype.load_notebook_success = function (data, status, xhr) { |
|
1760 | Notebook.prototype.load_notebook_success = function (data, status, xhr) { | |
1753 | this.fromJSON(data); |
|
1761 | this.fromJSON(data); | |
1754 | if (this.ncells() === 0) { |
|
1762 | if (this.ncells() === 0) { | |
1755 | this.insert_cell_below('code'); |
|
1763 | this.insert_cell_below('code'); | |
1756 | }; |
|
1764 | }; | |
1757 | this.set_dirty(false); |
|
1765 | this.set_dirty(false); | |
1758 | this.select(0); |
|
1766 | this.select(0); | |
1759 | this.scroll_to_top(); |
|
1767 | this.scroll_to_top(); | |
1760 | if (data.orig_nbformat !== undefined && data.nbformat !== data.orig_nbformat) { |
|
1768 | if (data.orig_nbformat !== undefined && data.nbformat !== data.orig_nbformat) { | |
1761 | var msg = "This notebook has been converted from an older " + |
|
1769 | var msg = "This notebook has been converted from an older " + | |
1762 | "notebook format (v"+data.orig_nbformat+") to the current notebook " + |
|
1770 | "notebook format (v"+data.orig_nbformat+") to the current notebook " + | |
1763 | "format (v"+data.nbformat+"). The next time you save this notebook, the " + |
|
1771 | "format (v"+data.nbformat+"). The next time you save this notebook, the " + | |
1764 | "newer notebook format will be used and older versions of IPython " + |
|
1772 | "newer notebook format will be used and older versions of IPython " + | |
1765 | "may not be able to read it. To keep the older version, close the " + |
|
1773 | "may not be able to read it. To keep the older version, close the " + | |
1766 | "notebook without saving it."; |
|
1774 | "notebook without saving it."; | |
1767 | IPython.dialog.modal({ |
|
1775 | IPython.dialog.modal({ | |
1768 | title : "Notebook converted", |
|
1776 | title : "Notebook converted", | |
1769 | body : msg, |
|
1777 | body : msg, | |
1770 | buttons : { |
|
1778 | buttons : { | |
1771 | OK : { |
|
1779 | OK : { | |
1772 | class : "btn-primary" |
|
1780 | class : "btn-primary" | |
1773 | } |
|
1781 | } | |
1774 | } |
|
1782 | } | |
1775 | }); |
|
1783 | }); | |
1776 | } else if (data.orig_nbformat_minor !== undefined && data.nbformat_minor !== data.orig_nbformat_minor) { |
|
1784 | } else if (data.orig_nbformat_minor !== undefined && data.nbformat_minor !== data.orig_nbformat_minor) { | |
1777 | var that = this; |
|
1785 | var that = this; | |
1778 | var orig_vs = 'v' + data.nbformat + '.' + data.orig_nbformat_minor; |
|
1786 | var orig_vs = 'v' + data.nbformat + '.' + data.orig_nbformat_minor; | |
1779 | var this_vs = 'v' + data.nbformat + '.' + this.nbformat_minor; |
|
1787 | var this_vs = 'v' + data.nbformat + '.' + this.nbformat_minor; | |
1780 | var msg = "This notebook is version " + orig_vs + ", but we only fully support up to " + |
|
1788 | var msg = "This notebook is version " + orig_vs + ", but we only fully support up to " + | |
1781 | this_vs + ". You can still work with this notebook, but some features " + |
|
1789 | this_vs + ". You can still work with this notebook, but some features " + | |
1782 | "introduced in later notebook versions may not be available." |
|
1790 | "introduced in later notebook versions may not be available." | |
1783 |
|
1791 | |||
1784 | IPython.dialog.modal({ |
|
1792 | IPython.dialog.modal({ | |
1785 | title : "Newer Notebook", |
|
1793 | title : "Newer Notebook", | |
1786 | body : msg, |
|
1794 | body : msg, | |
1787 | buttons : { |
|
1795 | buttons : { | |
1788 | OK : { |
|
1796 | OK : { | |
1789 | class : "btn-danger" |
|
1797 | class : "btn-danger" | |
1790 | } |
|
1798 | } | |
1791 | } |
|
1799 | } | |
1792 | }); |
|
1800 | }); | |
1793 |
|
1801 | |||
1794 | } |
|
1802 | } | |
1795 |
|
1803 | |||
1796 | // Create the kernel after the notebook is completely loaded to prevent |
|
1804 | // Create the kernel after the notebook is completely loaded to prevent | |
1797 | // code execution upon loading, which is a security risk. |
|
1805 | // code execution upon loading, which is a security risk. | |
1798 | this.start_kernel(); |
|
1806 | this.start_kernel(); | |
1799 | // load our checkpoint list |
|
1807 | // load our checkpoint list | |
1800 | IPython.notebook.list_checkpoints(); |
|
1808 | IPython.notebook.list_checkpoints(); | |
1801 |
|
1809 | |||
1802 | $([IPython.events]).trigger('notebook_loaded.Notebook'); |
|
1810 | $([IPython.events]).trigger('notebook_loaded.Notebook'); | |
1803 | }; |
|
1811 | }; | |
1804 |
|
1812 | |||
1805 | /** |
|
1813 | /** | |
1806 | * Failure callback for loading a notebook from the server. |
|
1814 | * Failure callback for loading a notebook from the server. | |
1807 | * |
|
1815 | * | |
1808 | * @method load_notebook_error |
|
1816 | * @method load_notebook_error | |
1809 | * @param {jqXHR} xhr jQuery Ajax object |
|
1817 | * @param {jqXHR} xhr jQuery Ajax object | |
1810 | * @param {String} textStatus Description of response status |
|
1818 | * @param {String} textStatus Description of response status | |
1811 | * @param {String} errorThrow HTTP error message |
|
1819 | * @param {String} errorThrow HTTP error message | |
1812 | */ |
|
1820 | */ | |
1813 | Notebook.prototype.load_notebook_error = function (xhr, textStatus, errorThrow) { |
|
1821 | Notebook.prototype.load_notebook_error = function (xhr, textStatus, errorThrow) { | |
1814 | if (xhr.status === 400) { |
|
1822 | if (xhr.status === 400) { | |
1815 | var msg = errorThrow; |
|
1823 | var msg = errorThrow; | |
1816 | } else if (xhr.status === 500) { |
|
1824 | } else if (xhr.status === 500) { | |
1817 | var msg = "An unknown error occurred while loading this notebook. " + |
|
1825 | var msg = "An unknown error occurred while loading this notebook. " + | |
1818 | "This version can load notebook formats " + |
|
1826 | "This version can load notebook formats " + | |
1819 | "v" + this.nbformat + " or earlier."; |
|
1827 | "v" + this.nbformat + " or earlier."; | |
1820 | } |
|
1828 | } | |
1821 | IPython.dialog.modal({ |
|
1829 | IPython.dialog.modal({ | |
1822 | title: "Error loading notebook", |
|
1830 | title: "Error loading notebook", | |
1823 | body : msg, |
|
1831 | body : msg, | |
1824 | buttons : { |
|
1832 | buttons : { | |
1825 | "OK": {} |
|
1833 | "OK": {} | |
1826 | } |
|
1834 | } | |
1827 | }); |
|
1835 | }); | |
1828 | } |
|
1836 | } | |
1829 |
|
1837 | |||
1830 | /********************* checkpoint-related *********************/ |
|
1838 | /********************* checkpoint-related *********************/ | |
1831 |
|
1839 | |||
1832 | /** |
|
1840 | /** | |
1833 | * Save the notebook then immediately create a checkpoint. |
|
1841 | * Save the notebook then immediately create a checkpoint. | |
1834 | * |
|
1842 | * | |
1835 | * @method save_checkpoint |
|
1843 | * @method save_checkpoint | |
1836 | */ |
|
1844 | */ | |
1837 | Notebook.prototype.save_checkpoint = function () { |
|
1845 | Notebook.prototype.save_checkpoint = function () { | |
1838 | this._checkpoint_after_save = true; |
|
1846 | this._checkpoint_after_save = true; | |
1839 | this.save_notebook(); |
|
1847 | this.save_notebook(); | |
1840 | }; |
|
1848 | }; | |
1841 |
|
1849 | |||
1842 | /** |
|
1850 | /** | |
1843 | * Add a checkpoint for this notebook. |
|
1851 | * Add a checkpoint for this notebook. | |
1844 | * for use as a callback from checkpoint creation. |
|
1852 | * for use as a callback from checkpoint creation. | |
1845 | * |
|
1853 | * | |
1846 | * @method add_checkpoint |
|
1854 | * @method add_checkpoint | |
1847 | */ |
|
1855 | */ | |
1848 | Notebook.prototype.add_checkpoint = function (checkpoint) { |
|
1856 | Notebook.prototype.add_checkpoint = function (checkpoint) { | |
1849 | var found = false; |
|
1857 | var found = false; | |
1850 | for (var i = 0; i < this.checkpoints.length; i++) { |
|
1858 | for (var i = 0; i < this.checkpoints.length; i++) { | |
1851 | var existing = this.checkpoints[i]; |
|
1859 | var existing = this.checkpoints[i]; | |
1852 | if (existing.checkpoint_id == checkpoint.checkpoint_id) { |
|
1860 | if (existing.checkpoint_id == checkpoint.checkpoint_id) { | |
1853 | found = true; |
|
1861 | found = true; | |
1854 | this.checkpoints[i] = checkpoint; |
|
1862 | this.checkpoints[i] = checkpoint; | |
1855 | break; |
|
1863 | break; | |
1856 | } |
|
1864 | } | |
1857 | } |
|
1865 | } | |
1858 | if (!found) { |
|
1866 | if (!found) { | |
1859 | this.checkpoints.push(checkpoint); |
|
1867 | this.checkpoints.push(checkpoint); | |
1860 | } |
|
1868 | } | |
1861 | this.last_checkpoint = this.checkpoints[this.checkpoints.length - 1]; |
|
1869 | this.last_checkpoint = this.checkpoints[this.checkpoints.length - 1]; | |
1862 | }; |
|
1870 | }; | |
1863 |
|
1871 | |||
1864 | /** |
|
1872 | /** | |
1865 | * List checkpoints for this notebook. |
|
1873 | * List checkpoints for this notebook. | |
1866 | * |
|
1874 | * | |
1867 | * @method list_checkpoints |
|
1875 | * @method list_checkpoints | |
1868 | */ |
|
1876 | */ | |
1869 | Notebook.prototype.list_checkpoints = function () { |
|
1877 | Notebook.prototype.list_checkpoints = function () { | |
1870 | var url = this.baseProjectUrl() + 'notebooks/' + this.notebook_id + '/checkpoints'; |
|
1878 | var url = this.baseProjectUrl() + 'notebooks/' + this.notebook_id + '/checkpoints'; | |
1871 | $.get(url).done( |
|
1879 | $.get(url).done( | |
1872 | $.proxy(this.list_checkpoints_success, this) |
|
1880 | $.proxy(this.list_checkpoints_success, this) | |
1873 | ).fail( |
|
1881 | ).fail( | |
1874 | $.proxy(this.list_checkpoints_error, this) |
|
1882 | $.proxy(this.list_checkpoints_error, this) | |
1875 | ); |
|
1883 | ); | |
1876 | }; |
|
1884 | }; | |
1877 |
|
1885 | |||
1878 | /** |
|
1886 | /** | |
1879 | * Success callback for listing checkpoints. |
|
1887 | * Success callback for listing checkpoints. | |
1880 | * |
|
1888 | * | |
1881 | * @method list_checkpoint_success |
|
1889 | * @method list_checkpoint_success | |
1882 | * @param {Object} data JSON representation of a checkpoint |
|
1890 | * @param {Object} data JSON representation of a checkpoint | |
1883 | * @param {String} status Description of response status |
|
1891 | * @param {String} status Description of response status | |
1884 | * @param {jqXHR} xhr jQuery Ajax object |
|
1892 | * @param {jqXHR} xhr jQuery Ajax object | |
1885 | */ |
|
1893 | */ | |
1886 | Notebook.prototype.list_checkpoints_success = function (data, status, xhr) { |
|
1894 | Notebook.prototype.list_checkpoints_success = function (data, status, xhr) { | |
1887 | var data = $.parseJSON(data); |
|
1895 | var data = $.parseJSON(data); | |
1888 | this.checkpoints = data; |
|
1896 | this.checkpoints = data; | |
1889 | if (data.length) { |
|
1897 | if (data.length) { | |
1890 | this.last_checkpoint = data[data.length - 1]; |
|
1898 | this.last_checkpoint = data[data.length - 1]; | |
1891 | } else { |
|
1899 | } else { | |
1892 | this.last_checkpoint = null; |
|
1900 | this.last_checkpoint = null; | |
1893 | } |
|
1901 | } | |
1894 | $([IPython.events]).trigger('checkpoints_listed.Notebook', [data]); |
|
1902 | $([IPython.events]).trigger('checkpoints_listed.Notebook', [data]); | |
1895 | }; |
|
1903 | }; | |
1896 |
|
1904 | |||
1897 | /** |
|
1905 | /** | |
1898 | * Failure callback for listing a checkpoint. |
|
1906 | * Failure callback for listing a checkpoint. | |
1899 | * |
|
1907 | * | |
1900 | * @method list_checkpoint_error |
|
1908 | * @method list_checkpoint_error | |
1901 | * @param {jqXHR} xhr jQuery Ajax object |
|
1909 | * @param {jqXHR} xhr jQuery Ajax object | |
1902 | * @param {String} status Description of response status |
|
1910 | * @param {String} status Description of response status | |
1903 | * @param {String} error_msg HTTP error message |
|
1911 | * @param {String} error_msg HTTP error message | |
1904 | */ |
|
1912 | */ | |
1905 | Notebook.prototype.list_checkpoints_error = function (xhr, status, error_msg) { |
|
1913 | Notebook.prototype.list_checkpoints_error = function (xhr, status, error_msg) { | |
1906 | $([IPython.events]).trigger('list_checkpoints_failed.Notebook'); |
|
1914 | $([IPython.events]).trigger('list_checkpoints_failed.Notebook'); | |
1907 | }; |
|
1915 | }; | |
1908 |
|
1916 | |||
1909 | /** |
|
1917 | /** | |
1910 | * Create a checkpoint of this notebook on the server from the most recent save. |
|
1918 | * Create a checkpoint of this notebook on the server from the most recent save. | |
1911 | * |
|
1919 | * | |
1912 | * @method create_checkpoint |
|
1920 | * @method create_checkpoint | |
1913 | */ |
|
1921 | */ | |
1914 | Notebook.prototype.create_checkpoint = function () { |
|
1922 | Notebook.prototype.create_checkpoint = function () { | |
1915 | var url = this.baseProjectUrl() + 'notebooks/' + this.notebook_id + '/checkpoints'; |
|
1923 | var url = this.baseProjectUrl() + 'notebooks/' + this.notebook_id + '/checkpoints'; | |
1916 | $.post(url).done( |
|
1924 | $.post(url).done( | |
1917 | $.proxy(this.create_checkpoint_success, this) |
|
1925 | $.proxy(this.create_checkpoint_success, this) | |
1918 | ).fail( |
|
1926 | ).fail( | |
1919 | $.proxy(this.create_checkpoint_error, this) |
|
1927 | $.proxy(this.create_checkpoint_error, this) | |
1920 | ); |
|
1928 | ); | |
1921 | }; |
|
1929 | }; | |
1922 |
|
1930 | |||
1923 | /** |
|
1931 | /** | |
1924 | * Success callback for creating a checkpoint. |
|
1932 | * Success callback for creating a checkpoint. | |
1925 | * |
|
1933 | * | |
1926 | * @method create_checkpoint_success |
|
1934 | * @method create_checkpoint_success | |
1927 | * @param {Object} data JSON representation of a checkpoint |
|
1935 | * @param {Object} data JSON representation of a checkpoint | |
1928 | * @param {String} status Description of response status |
|
1936 | * @param {String} status Description of response status | |
1929 | * @param {jqXHR} xhr jQuery Ajax object |
|
1937 | * @param {jqXHR} xhr jQuery Ajax object | |
1930 | */ |
|
1938 | */ | |
1931 | Notebook.prototype.create_checkpoint_success = function (data, status, xhr) { |
|
1939 | Notebook.prototype.create_checkpoint_success = function (data, status, xhr) { | |
1932 | var data = $.parseJSON(data); |
|
1940 | var data = $.parseJSON(data); | |
1933 | this.add_checkpoint(data); |
|
1941 | this.add_checkpoint(data); | |
1934 | $([IPython.events]).trigger('checkpoint_created.Notebook', data); |
|
1942 | $([IPython.events]).trigger('checkpoint_created.Notebook', data); | |
1935 | }; |
|
1943 | }; | |
1936 |
|
1944 | |||
1937 | /** |
|
1945 | /** | |
1938 | * Failure callback for creating a checkpoint. |
|
1946 | * Failure callback for creating a checkpoint. | |
1939 | * |
|
1947 | * | |
1940 | * @method create_checkpoint_error |
|
1948 | * @method create_checkpoint_error | |
1941 | * @param {jqXHR} xhr jQuery Ajax object |
|
1949 | * @param {jqXHR} xhr jQuery Ajax object | |
1942 | * @param {String} status Description of response status |
|
1950 | * @param {String} status Description of response status | |
1943 | * @param {String} error_msg HTTP error message |
|
1951 | * @param {String} error_msg HTTP error message | |
1944 | */ |
|
1952 | */ | |
1945 | Notebook.prototype.create_checkpoint_error = function (xhr, status, error_msg) { |
|
1953 | Notebook.prototype.create_checkpoint_error = function (xhr, status, error_msg) { | |
1946 | $([IPython.events]).trigger('checkpoint_failed.Notebook'); |
|
1954 | $([IPython.events]).trigger('checkpoint_failed.Notebook'); | |
1947 | }; |
|
1955 | }; | |
1948 |
|
1956 | |||
1949 | Notebook.prototype.restore_checkpoint_dialog = function (checkpoint) { |
|
1957 | Notebook.prototype.restore_checkpoint_dialog = function (checkpoint) { | |
1950 | var that = this; |
|
1958 | var that = this; | |
1951 | var checkpoint = checkpoint || this.last_checkpoint; |
|
1959 | var checkpoint = checkpoint || this.last_checkpoint; | |
1952 | if ( ! checkpoint ) { |
|
1960 | if ( ! checkpoint ) { | |
1953 | console.log("restore dialog, but no checkpoint to restore to!"); |
|
1961 | console.log("restore dialog, but no checkpoint to restore to!"); | |
1954 | return; |
|
1962 | return; | |
1955 | } |
|
1963 | } | |
1956 | var body = $('<div/>').append( |
|
1964 | var body = $('<div/>').append( | |
1957 | $('<p/>').addClass("p-space").text( |
|
1965 | $('<p/>').addClass("p-space").text( | |
1958 | "Are you sure you want to revert the notebook to " + |
|
1966 | "Are you sure you want to revert the notebook to " + | |
1959 | "the latest checkpoint?" |
|
1967 | "the latest checkpoint?" | |
1960 | ).append( |
|
1968 | ).append( | |
1961 | $("<strong/>").text( |
|
1969 | $("<strong/>").text( | |
1962 | " This cannot be undone." |
|
1970 | " This cannot be undone." | |
1963 | ) |
|
1971 | ) | |
1964 | ) |
|
1972 | ) | |
1965 | ).append( |
|
1973 | ).append( | |
1966 | $('<p/>').addClass("p-space").text("The checkpoint was last updated at:") |
|
1974 | $('<p/>').addClass("p-space").text("The checkpoint was last updated at:") | |
1967 | ).append( |
|
1975 | ).append( | |
1968 | $('<p/>').addClass("p-space").text( |
|
1976 | $('<p/>').addClass("p-space").text( | |
1969 | Date(checkpoint.last_modified) |
|
1977 | Date(checkpoint.last_modified) | |
1970 | ).css("text-align", "center") |
|
1978 | ).css("text-align", "center") | |
1971 | ); |
|
1979 | ); | |
1972 |
|
1980 | |||
1973 | IPython.dialog.modal({ |
|
1981 | IPython.dialog.modal({ | |
1974 | title : "Revert notebook to checkpoint", |
|
1982 | title : "Revert notebook to checkpoint", | |
1975 | body : body, |
|
1983 | body : body, | |
1976 | buttons : { |
|
1984 | buttons : { | |
1977 | Revert : { |
|
1985 | Revert : { | |
1978 | class : "btn-danger", |
|
1986 | class : "btn-danger", | |
1979 | click : function () { |
|
1987 | click : function () { | |
1980 | that.restore_checkpoint(checkpoint.checkpoint_id); |
|
1988 | that.restore_checkpoint(checkpoint.checkpoint_id); | |
1981 | } |
|
1989 | } | |
1982 | }, |
|
1990 | }, | |
1983 | Cancel : {} |
|
1991 | Cancel : {} | |
1984 | } |
|
1992 | } | |
1985 | }); |
|
1993 | }); | |
1986 | } |
|
1994 | } | |
1987 |
|
1995 | |||
1988 | /** |
|
1996 | /** | |
1989 | * Restore the notebook to a checkpoint state. |
|
1997 | * Restore the notebook to a checkpoint state. | |
1990 | * |
|
1998 | * | |
1991 | * @method restore_checkpoint |
|
1999 | * @method restore_checkpoint | |
1992 | * @param {String} checkpoint ID |
|
2000 | * @param {String} checkpoint ID | |
1993 | */ |
|
2001 | */ | |
1994 | Notebook.prototype.restore_checkpoint = function (checkpoint) { |
|
2002 | Notebook.prototype.restore_checkpoint = function (checkpoint) { | |
1995 | $([IPython.events]).trigger('checkpoint_restoring.Notebook', checkpoint); |
|
2003 | $([IPython.events]).trigger('checkpoint_restoring.Notebook', checkpoint); | |
1996 | var url = this.baseProjectUrl() + 'notebooks/' + this.notebook_id + '/checkpoints/' + checkpoint; |
|
2004 | var url = this.baseProjectUrl() + 'notebooks/' + this.notebook_id + '/checkpoints/' + checkpoint; | |
1997 | $.post(url).done( |
|
2005 | $.post(url).done( | |
1998 | $.proxy(this.restore_checkpoint_success, this) |
|
2006 | $.proxy(this.restore_checkpoint_success, this) | |
1999 | ).fail( |
|
2007 | ).fail( | |
2000 | $.proxy(this.restore_checkpoint_error, this) |
|
2008 | $.proxy(this.restore_checkpoint_error, this) | |
2001 | ); |
|
2009 | ); | |
2002 | }; |
|
2010 | }; | |
2003 |
|
2011 | |||
2004 | /** |
|
2012 | /** | |
2005 | * Success callback for restoring a notebook to a checkpoint. |
|
2013 | * Success callback for restoring a notebook to a checkpoint. | |
2006 | * |
|
2014 | * | |
2007 | * @method restore_checkpoint_success |
|
2015 | * @method restore_checkpoint_success | |
2008 | * @param {Object} data (ignored, should be empty) |
|
2016 | * @param {Object} data (ignored, should be empty) | |
2009 | * @param {String} status Description of response status |
|
2017 | * @param {String} status Description of response status | |
2010 | * @param {jqXHR} xhr jQuery Ajax object |
|
2018 | * @param {jqXHR} xhr jQuery Ajax object | |
2011 | */ |
|
2019 | */ | |
2012 | Notebook.prototype.restore_checkpoint_success = function (data, status, xhr) { |
|
2020 | Notebook.prototype.restore_checkpoint_success = function (data, status, xhr) { | |
2013 | $([IPython.events]).trigger('checkpoint_restored.Notebook'); |
|
2021 | $([IPython.events]).trigger('checkpoint_restored.Notebook'); | |
2014 | this.load_notebook(this.notebook_id); |
|
2022 | this.load_notebook(this.notebook_id); | |
2015 | }; |
|
2023 | }; | |
2016 |
|
2024 | |||
2017 | /** |
|
2025 | /** | |
2018 | * Failure callback for restoring a notebook to a checkpoint. |
|
2026 | * Failure callback for restoring a notebook to a checkpoint. | |
2019 | * |
|
2027 | * | |
2020 | * @method restore_checkpoint_error |
|
2028 | * @method restore_checkpoint_error | |
2021 | * @param {jqXHR} xhr jQuery Ajax object |
|
2029 | * @param {jqXHR} xhr jQuery Ajax object | |
2022 | * @param {String} status Description of response status |
|
2030 | * @param {String} status Description of response status | |
2023 | * @param {String} error_msg HTTP error message |
|
2031 | * @param {String} error_msg HTTP error message | |
2024 | */ |
|
2032 | */ | |
2025 | Notebook.prototype.restore_checkpoint_error = function (xhr, status, error_msg) { |
|
2033 | Notebook.prototype.restore_checkpoint_error = function (xhr, status, error_msg) { | |
2026 | $([IPython.events]).trigger('checkpoint_restore_failed.Notebook'); |
|
2034 | $([IPython.events]).trigger('checkpoint_restore_failed.Notebook'); | |
2027 | }; |
|
2035 | }; | |
2028 |
|
2036 | |||
2029 | /** |
|
2037 | /** | |
2030 | * Delete a notebook checkpoint. |
|
2038 | * Delete a notebook checkpoint. | |
2031 | * |
|
2039 | * | |
2032 | * @method delete_checkpoint |
|
2040 | * @method delete_checkpoint | |
2033 | * @param {String} checkpoint ID |
|
2041 | * @param {String} checkpoint ID | |
2034 | */ |
|
2042 | */ | |
2035 | Notebook.prototype.delete_checkpoint = function (checkpoint) { |
|
2043 | Notebook.prototype.delete_checkpoint = function (checkpoint) { | |
2036 | $([IPython.events]).trigger('checkpoint_deleting.Notebook', checkpoint); |
|
2044 | $([IPython.events]).trigger('checkpoint_deleting.Notebook', checkpoint); | |
2037 | var url = this.baseProjectUrl() + 'notebooks/' + this.notebook_id + '/checkpoints/' + checkpoint; |
|
2045 | var url = this.baseProjectUrl() + 'notebooks/' + this.notebook_id + '/checkpoints/' + checkpoint; | |
2038 | $.ajax(url, { |
|
2046 | $.ajax(url, { | |
2039 | type: 'DELETE', |
|
2047 | type: 'DELETE', | |
2040 | success: $.proxy(this.delete_checkpoint_success, this), |
|
2048 | success: $.proxy(this.delete_checkpoint_success, this), | |
2041 | error: $.proxy(this.delete_notebook_error,this) |
|
2049 | error: $.proxy(this.delete_notebook_error,this) | |
2042 | }); |
|
2050 | }); | |
2043 | }; |
|
2051 | }; | |
2044 |
|
2052 | |||
2045 | /** |
|
2053 | /** | |
2046 | * Success callback for deleting a notebook checkpoint |
|
2054 | * Success callback for deleting a notebook checkpoint | |
2047 | * |
|
2055 | * | |
2048 | * @method delete_checkpoint_success |
|
2056 | * @method delete_checkpoint_success | |
2049 | * @param {Object} data (ignored, should be empty) |
|
2057 | * @param {Object} data (ignored, should be empty) | |
2050 | * @param {String} status Description of response status |
|
2058 | * @param {String} status Description of response status | |
2051 | * @param {jqXHR} xhr jQuery Ajax object |
|
2059 | * @param {jqXHR} xhr jQuery Ajax object | |
2052 | */ |
|
2060 | */ | |
2053 | Notebook.prototype.delete_checkpoint_success = function (data, status, xhr) { |
|
2061 | Notebook.prototype.delete_checkpoint_success = function (data, status, xhr) { | |
2054 | $([IPython.events]).trigger('checkpoint_deleted.Notebook', data); |
|
2062 | $([IPython.events]).trigger('checkpoint_deleted.Notebook', data); | |
2055 | this.load_notebook(this.notebook_id); |
|
2063 | this.load_notebook(this.notebook_id); | |
2056 | }; |
|
2064 | }; | |
2057 |
|
2065 | |||
2058 | /** |
|
2066 | /** | |
2059 | * Failure callback for deleting a notebook checkpoint. |
|
2067 | * Failure callback for deleting a notebook checkpoint. | |
2060 | * |
|
2068 | * | |
2061 | * @method delete_checkpoint_error |
|
2069 | * @method delete_checkpoint_error | |
2062 | * @param {jqXHR} xhr jQuery Ajax object |
|
2070 | * @param {jqXHR} xhr jQuery Ajax object | |
2063 | * @param {String} status Description of response status |
|
2071 | * @param {String} status Description of response status | |
2064 | * @param {String} error_msg HTTP error message |
|
2072 | * @param {String} error_msg HTTP error message | |
2065 | */ |
|
2073 | */ | |
2066 | Notebook.prototype.delete_checkpoint_error = function (xhr, status, error_msg) { |
|
2074 | Notebook.prototype.delete_checkpoint_error = function (xhr, status, error_msg) { | |
2067 | $([IPython.events]).trigger('checkpoint_delete_failed.Notebook'); |
|
2075 | $([IPython.events]).trigger('checkpoint_delete_failed.Notebook'); | |
2068 | }; |
|
2076 | }; | |
2069 |
|
2077 | |||
2070 |
|
2078 | |||
2071 | IPython.Notebook = Notebook; |
|
2079 | IPython.Notebook = Notebook; | |
2072 |
|
2080 | |||
2073 |
|
2081 | |||
2074 | return IPython; |
|
2082 | return IPython; | |
2075 |
|
2083 | |||
2076 | }(IPython)); |
|
2084 | }(IPython)); | |
2077 |
|
2085 |
@@ -1,259 +1,261 b'' | |||||
1 | {% extends "page.html" %} |
|
1 | {% extends "page.html" %} | |
2 |
|
2 | |||
3 | {% block stylesheet %} |
|
3 | {% block stylesheet %} | |
4 |
|
4 | |||
5 | {% if mathjax_url %} |
|
5 | {% if mathjax_url %} | |
6 | <script type="text/javascript" src="{{mathjax_url}}?config=TeX-AMS_HTML-full&delayStartupUntil=configured" charset="utf-8"></script> |
|
6 | <script type="text/javascript" src="{{mathjax_url}}?config=TeX-AMS_HTML-full&delayStartupUntil=configured" charset="utf-8"></script> | |
7 | {% endif %} |
|
7 | {% endif %} | |
8 | <script type="text/javascript"> |
|
8 | <script type="text/javascript"> | |
9 | // MathJax disabled, set as null to distingish from *missing* MathJax, |
|
9 | // MathJax disabled, set as null to distingish from *missing* MathJax, | |
10 | // where it will be undefined, and should prompt a dialog later. |
|
10 | // where it will be undefined, and should prompt a dialog later. | |
11 | window.mathjax_url = "{{mathjax_url}}"; |
|
11 | window.mathjax_url = "{{mathjax_url}}"; | |
12 | </script> |
|
12 | </script> | |
13 |
|
13 | |||
14 | <link rel="stylesheet" href="{{ static_url("components/codemirror/lib/codemirror.css") }}"> |
|
14 | <link rel="stylesheet" href="{{ static_url("components/codemirror/lib/codemirror.css") }}"> | |
15 |
|
15 | |||
16 | {{super()}} |
|
16 | {{super()}} | |
17 |
|
17 | |||
18 | <link rel="stylesheet" href="{{ static_url("notebook/css/override.css") }}" type="text/css" /> |
|
18 | <link rel="stylesheet" href="{{ static_url("notebook/css/override.css") }}" type="text/css" /> | |
19 |
|
19 | |||
20 | {% endblock %} |
|
20 | {% endblock %} | |
21 |
|
21 | |||
22 | {% block params %} |
|
22 | {% block params %} | |
23 |
|
23 | |||
24 | data-project={{project}} |
|
24 | data-project={{project}} | |
25 | data-base-project-url={{base_project_url}} |
|
25 | data-base-project-url={{base_project_url}} | |
26 | data-base-kernel-url={{base_kernel_url}} |
|
26 | data-base-kernel-url={{base_kernel_url}} | |
27 | data-notebook-id={{notebook_id}} |
|
27 | data-notebook-id={{notebook_id}} | |
28 | class="notebook_app" |
|
28 | class="notebook_app" | |
29 |
|
29 | |||
30 | {% endblock %} |
|
30 | {% endblock %} | |
31 |
|
31 | |||
32 |
|
32 | |||
33 | {% block header %} |
|
33 | {% block header %} | |
34 |
|
34 | |||
35 | <span id="save_widget" class="nav pull-left"> |
|
35 | <span id="save_widget" class="nav pull-left"> | |
36 | <span id="notebook_name"></span> |
|
36 | <span id="notebook_name"></span> | |
37 | <span id="checkpoint_status"></span> |
|
37 | <span id="checkpoint_status"></span> | |
38 | <span id="autosave_status"></span> |
|
38 | <span id="autosave_status"></span> | |
39 | </span> |
|
39 | </span> | |
40 |
|
40 | |||
41 | {% endblock %} |
|
41 | {% endblock %} | |
42 |
|
42 | |||
43 |
|
43 | |||
44 | {% block site %} |
|
44 | {% block site %} | |
45 |
|
45 | |||
46 | <div id="menubar-container" class="container"> |
|
46 | <div id="menubar-container" class="container"> | |
47 | <div id="menubar"> |
|
47 | <div id="menubar"> | |
48 | <div class="navbar"> |
|
48 | <div class="navbar"> | |
49 | <div class="navbar-inner"> |
|
49 | <div class="navbar-inner"> | |
50 | <div class="container"> |
|
50 | <div class="container"> | |
51 | <ul id="menus" class="nav"> |
|
51 | <ul id="menus" class="nav"> | |
52 | <li class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown">File</a> |
|
52 | <li class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown">File</a> | |
53 | <ul class="dropdown-menu"> |
|
53 | <ul class="dropdown-menu"> | |
54 | <li id="new_notebook"><a href="#">New</a></li> |
|
54 | <li id="new_notebook"><a href="#">New</a></li> | |
55 | <li id="open_notebook"><a href="#">Open...</a></li> |
|
55 | <li id="open_notebook"><a href="#">Open...</a></li> | |
56 | <!-- <hr/> --> |
|
56 | <!-- <hr/> --> | |
57 | <li class="divider"></li> |
|
57 | <li class="divider"></li> | |
58 | <li id="copy_notebook"><a href="#">Make a Copy...</a></li> |
|
58 | <li id="copy_notebook"><a href="#">Make a Copy...</a></li> | |
59 | <li id="rename_notebook"><a href="#">Rename...</a></li> |
|
59 | <li id="rename_notebook"><a href="#">Rename...</a></li> | |
60 | <li id="save_checkpoint"><a href="#">Save and Checkpoint</a></li> |
|
60 | <li id="save_checkpoint"><a href="#">Save and Checkpoint</a></li> | |
61 | <!-- <hr/> --> |
|
61 | <!-- <hr/> --> | |
62 | <li class="divider"></li> |
|
62 | <li class="divider"></li> | |
63 | <li id="restore_checkpoint" class="dropdown-submenu"><a href="#">Revert to Checkpoint</a> |
|
63 | <li id="restore_checkpoint" class="dropdown-submenu"><a href="#">Revert to Checkpoint</a> | |
64 | <ul class="dropdown-menu"> |
|
64 | <ul class="dropdown-menu"> | |
65 | <li><a href="#"></a></li> |
|
65 | <li><a href="#"></a></li> | |
66 | <li><a href="#"></a></li> |
|
66 | <li><a href="#"></a></li> | |
67 | <li><a href="#"></a></li> |
|
67 | <li><a href="#"></a></li> | |
68 | <li><a href="#"></a></li> |
|
68 | <li><a href="#"></a></li> | |
69 | <li><a href="#"></a></li> |
|
69 | <li><a href="#"></a></li> | |
70 | </ul> |
|
70 | </ul> | |
71 | </li> |
|
71 | </li> | |
72 | <li class="divider"></li> |
|
72 | <li class="divider"></li> | |
73 | <li class="dropdown-submenu"><a href="#">Download as</a> |
|
73 | <li class="dropdown-submenu"><a href="#">Download as</a> | |
74 | <ul class="dropdown-menu"> |
|
74 | <ul class="dropdown-menu"> | |
75 | <li id="download_ipynb"><a href="#">IPython (.ipynb)</a></li> |
|
75 | <li id="download_ipynb"><a href="#">IPython (.ipynb)</a></li> | |
76 | <li id="download_py"><a href="#">Python (.py)</a></li> |
|
76 | <li id="download_py"><a href="#">Python (.py)</a></li> | |
77 | </ul> |
|
77 | </ul> | |
78 | </li> |
|
78 | </li> | |
79 | <li class="divider"></li> |
|
79 | <li class="divider"></li> | |
80 |
|
80 | |||
81 | <li id="kill_and_exit"><a href="#" >Close and halt</a></li> |
|
81 | <li id="kill_and_exit"><a href="#" >Close and halt</a></li> | |
82 | </ul> |
|
82 | </ul> | |
83 | </li> |
|
83 | </li> | |
84 | <li class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown">Edit</a> |
|
84 | <li class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown">Edit</a> | |
85 | <ul class="dropdown-menu"> |
|
85 | <ul class="dropdown-menu"> | |
86 | <li id="cut_cell"><a href="#">Cut Cell</a></li> |
|
86 | <li id="cut_cell"><a href="#">Cut Cell</a></li> | |
87 | <li id="copy_cell"><a href="#">Copy Cell</a></li> |
|
87 | <li id="copy_cell"><a href="#">Copy Cell</a></li> | |
88 | <li id="paste_cell_above" class="disabled"><a href="#">Paste Cell Above</a></li> |
|
88 | <li id="paste_cell_above" class="disabled"><a href="#">Paste Cell Above</a></li> | |
89 | <li id="paste_cell_below" class="disabled"><a href="#">Paste Cell Below</a></li> |
|
89 | <li id="paste_cell_below" class="disabled"><a href="#">Paste Cell Below</a></li> | |
90 | <li id="paste_cell_replace" class="disabled"><a href="#">Paste Cell & Replace</a></li> |
|
90 | <li id="paste_cell_replace" class="disabled"><a href="#">Paste Cell & Replace</a></li> | |
91 | <li id="delete_cell"><a href="#">Delete Cell</a></li> |
|
91 | <li id="delete_cell"><a href="#">Delete Cell</a></li> | |
92 | <li id="undelete_cell" class="disabled"><a href="#">Undo Delete Cell</a></li> |
|
92 | <li id="undelete_cell" class="disabled"><a href="#">Undo Delete Cell</a></li> | |
93 | <li class="divider"></li> |
|
93 | <li class="divider"></li> | |
94 | <li id="split_cell"><a href="#">Split Cell</a></li> |
|
94 | <li id="split_cell"><a href="#">Split Cell</a></li> | |
95 | <li id="merge_cell_above"><a href="#">Merge Cell Above</a></li> |
|
95 | <li id="merge_cell_above"><a href="#">Merge Cell Above</a></li> | |
96 | <li id="merge_cell_below"><a href="#">Merge Cell Below</a></li> |
|
96 | <li id="merge_cell_below"><a href="#">Merge Cell Below</a></li> | |
97 | <li class="divider"></li> |
|
97 | <li class="divider"></li> | |
98 | <li id="move_cell_up"><a href="#">Move Cell Up</a></li> |
|
98 | <li id="move_cell_up"><a href="#">Move Cell Up</a></li> | |
99 | <li id="move_cell_down"><a href="#">Move Cell Down</a></li> |
|
99 | <li id="move_cell_down"><a href="#">Move Cell Down</a></li> | |
100 | <li class="divider"></li> |
|
100 | <li class="divider"></li> | |
101 | <li id="select_previous"><a href="#">Select Previous Cell</a></li> |
|
101 | <li id="select_previous"><a href="#">Select Previous Cell</a></li> | |
102 | <li id="select_next"><a href="#">Select Next Cell</a></li> |
|
102 | <li id="select_next"><a href="#">Select Next Cell</a></li> | |
|
103 | <li class="divider"></li> | |||
|
104 | <li id="edit_nb_metadata"><a href="#">Edit Notebook Metadata</a></li> | |||
103 | </ul> |
|
105 | </ul> | |
104 | </li> |
|
106 | </li> | |
105 | <li class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown">View</a> |
|
107 | <li class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown">View</a> | |
106 | <ul class="dropdown-menu"> |
|
108 | <ul class="dropdown-menu"> | |
107 | <li id="toggle_header"><a href="#">Toggle Header</a></li> |
|
109 | <li id="toggle_header"><a href="#">Toggle Header</a></li> | |
108 | <li id="toggle_toolbar"><a href="#">Toggle Toolbar</a></li> |
|
110 | <li id="toggle_toolbar"><a href="#">Toggle Toolbar</a></li> | |
109 | </ul> |
|
111 | </ul> | |
110 | </li> |
|
112 | </li> | |
111 | <li class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown">Insert</a> |
|
113 | <li class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown">Insert</a> | |
112 | <ul class="dropdown-menu"> |
|
114 | <ul class="dropdown-menu"> | |
113 | <li id="insert_cell_above"><a href="#">Insert Cell Above</a></li> |
|
115 | <li id="insert_cell_above"><a href="#">Insert Cell Above</a></li> | |
114 | <li id="insert_cell_below"><a href="#">Insert Cell Below</a></li> |
|
116 | <li id="insert_cell_below"><a href="#">Insert Cell Below</a></li> | |
115 | </ul> |
|
117 | </ul> | |
116 | </li> |
|
118 | </li> | |
117 | <li class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown">Cell</a> |
|
119 | <li class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown">Cell</a> | |
118 | <ul class="dropdown-menu"> |
|
120 | <ul class="dropdown-menu"> | |
119 | <li id="run_cell"><a href="#">Run</a></li> |
|
121 | <li id="run_cell"><a href="#">Run</a></li> | |
120 | <li id="run_cell_in_place"><a href="#">Run in Place</a></li> |
|
122 | <li id="run_cell_in_place"><a href="#">Run in Place</a></li> | |
121 | <li id="run_all_cells"><a href="#">Run All</a></li> |
|
123 | <li id="run_all_cells"><a href="#">Run All</a></li> | |
122 | <li id="run_all_cells_above"><a href="#">Run All Above</a></li> |
|
124 | <li id="run_all_cells_above"><a href="#">Run All Above</a></li> | |
123 | <li id="run_all_cells_below"><a href="#">Run All Below</a></li> |
|
125 | <li id="run_all_cells_below"><a href="#">Run All Below</a></li> | |
124 | <li class="divider"></li> |
|
126 | <li class="divider"></li> | |
125 | <li id="change_cell_type" class="dropdown-submenu"><a href="#">Cell Type</a> |
|
127 | <li id="change_cell_type" class="dropdown-submenu"><a href="#">Cell Type</a> | |
126 | <ul class="dropdown-menu"> |
|
128 | <ul class="dropdown-menu"> | |
127 | <li id="to_code"><a href="#">Code</a></li> |
|
129 | <li id="to_code"><a href="#">Code</a></li> | |
128 | <li id="to_markdown"><a href="#">Markdown </a></li> |
|
130 | <li id="to_markdown"><a href="#">Markdown </a></li> | |
129 | <li id="to_raw"><a href="#">Raw Text</a></li> |
|
131 | <li id="to_raw"><a href="#">Raw Text</a></li> | |
130 | <li id="to_heading1"><a href="#">Heading 1</a></li> |
|
132 | <li id="to_heading1"><a href="#">Heading 1</a></li> | |
131 | <li id="to_heading2"><a href="#">Heading 2</a></li> |
|
133 | <li id="to_heading2"><a href="#">Heading 2</a></li> | |
132 | <li id="to_heading3"><a href="#">Heading 3</a></li> |
|
134 | <li id="to_heading3"><a href="#">Heading 3</a></li> | |
133 | <li id="to_heading4"><a href="#">Heading 4</a></li> |
|
135 | <li id="to_heading4"><a href="#">Heading 4</a></li> | |
134 | <li id="to_heading5"><a href="#">Heading 5</a></li> |
|
136 | <li id="to_heading5"><a href="#">Heading 5</a></li> | |
135 | <li id="to_heading6"><a href="#">Heading 6</a></li> |
|
137 | <li id="to_heading6"><a href="#">Heading 6</a></li> | |
136 | </ul> |
|
138 | </ul> | |
137 | </li> |
|
139 | </li> | |
138 | <li class="divider"></li> |
|
140 | <li class="divider"></li> | |
139 | <li id="toggle_output"><a href="#">Toggle Current Output</a></li> |
|
141 | <li id="toggle_output"><a href="#">Toggle Current Output</a></li> | |
140 | <li id="all_outputs" class="dropdown-submenu"><a href="#">All Output</a> |
|
142 | <li id="all_outputs" class="dropdown-submenu"><a href="#">All Output</a> | |
141 | <ul class="dropdown-menu"> |
|
143 | <ul class="dropdown-menu"> | |
142 | <li id="expand_all_output"><a href="#">Expand</a></li> |
|
144 | <li id="expand_all_output"><a href="#">Expand</a></li> | |
143 | <li id="scroll_all_output"><a href="#">Scroll Long</a></li> |
|
145 | <li id="scroll_all_output"><a href="#">Scroll Long</a></li> | |
144 | <li id="collapse_all_output"><a href="#">Collapse</a></li> |
|
146 | <li id="collapse_all_output"><a href="#">Collapse</a></li> | |
145 | <li id="clear_all_output"><a href="#">Clear</a></li> |
|
147 | <li id="clear_all_output"><a href="#">Clear</a></li> | |
146 | </ul> |
|
148 | </ul> | |
147 | </li> |
|
149 | </li> | |
148 | </ul> |
|
150 | </ul> | |
149 | </li> |
|
151 | </li> | |
150 | <li class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown">Kernel</a> |
|
152 | <li class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown">Kernel</a> | |
151 | <ul class="dropdown-menu"> |
|
153 | <ul class="dropdown-menu"> | |
152 | <li id="int_kernel"><a href="#">Interrupt</a></li> |
|
154 | <li id="int_kernel"><a href="#">Interrupt</a></li> | |
153 | <li id="restart_kernel"><a href="#">Restart</a></li> |
|
155 | <li id="restart_kernel"><a href="#">Restart</a></li> | |
154 | </ul> |
|
156 | </ul> | |
155 | </li> |
|
157 | </li> | |
156 | <li class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown">Help</a> |
|
158 | <li class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown">Help</a> | |
157 | <ul class="dropdown-menu"> |
|
159 | <ul class="dropdown-menu"> | |
158 | <li><a href="http://ipython.org/documentation.html" target="_blank">IPython Help</a></li> |
|
160 | <li><a href="http://ipython.org/documentation.html" target="_blank">IPython Help</a></li> | |
159 | <li><a href="http://ipython.org/ipython-doc/stable/interactive/notebook.html" target="_blank">Notebook Help</a></li> |
|
161 | <li><a href="http://ipython.org/ipython-doc/stable/interactive/notebook.html" target="_blank">Notebook Help</a></li> | |
160 | <li id="keyboard_shortcuts"><a href="#">Keyboard Shortcuts</a></li> |
|
162 | <li id="keyboard_shortcuts"><a href="#">Keyboard Shortcuts</a></li> | |
161 | <li class="divider"></li> |
|
163 | <li class="divider"></li> | |
162 | <li><a href="http://docs.python.org" target="_blank">Python</a></li> |
|
164 | <li><a href="http://docs.python.org" target="_blank">Python</a></li> | |
163 | <li><a href="http://docs.scipy.org/doc/numpy/reference/" target="_blank">NumPy</a></li> |
|
165 | <li><a href="http://docs.scipy.org/doc/numpy/reference/" target="_blank">NumPy</a></li> | |
164 | <li><a href="http://docs.scipy.org/doc/scipy/reference/" target="_blank">SciPy</a></li> |
|
166 | <li><a href="http://docs.scipy.org/doc/scipy/reference/" target="_blank">SciPy</a></li> | |
165 | <li><a href="http://matplotlib.org/" target="_blank">Matplotlib</a></li> |
|
167 | <li><a href="http://matplotlib.org/" target="_blank">Matplotlib</a></li> | |
166 | <li><a href="http://docs.sympy.org/dev/index.html" target="_blank">SymPy</a></li> |
|
168 | <li><a href="http://docs.sympy.org/dev/index.html" target="_blank">SymPy</a></li> | |
167 | <li><a href="http://pandas.pydata.org/pandas-docs/stable/" target="_blank">pandas</a></li> |
|
169 | <li><a href="http://pandas.pydata.org/pandas-docs/stable/" target="_blank">pandas</a></li> | |
168 | </ul> |
|
170 | </ul> | |
169 | </li> |
|
171 | </li> | |
170 | </ul> |
|
172 | </ul> | |
171 | <div id="notification_area"></div> |
|
173 | <div id="notification_area"></div> | |
172 | </div> |
|
174 | </div> | |
173 | </div> |
|
175 | </div> | |
174 | </div> |
|
176 | </div> | |
175 | </div> |
|
177 | </div> | |
176 | <div id="maintoolbar" class="navbar"> |
|
178 | <div id="maintoolbar" class="navbar"> | |
177 | <div class="toolbar-inner navbar-inner navbar-nobg"> |
|
179 | <div class="toolbar-inner navbar-inner navbar-nobg"> | |
178 | <div id="maintoolbar-container" class="container"></div> |
|
180 | <div id="maintoolbar-container" class="container"></div> | |
179 | </div> |
|
181 | </div> | |
180 | </div> |
|
182 | </div> | |
181 | </div> |
|
183 | </div> | |
182 |
|
184 | |||
183 | <div id="ipython-main-app"> |
|
185 | <div id="ipython-main-app"> | |
184 |
|
186 | |||
185 | <div id="notebook_panel"> |
|
187 | <div id="notebook_panel"> | |
186 | <div id="notebook"></div> |
|
188 | <div id="notebook"></div> | |
187 | <div id="pager_splitter"></div> |
|
189 | <div id="pager_splitter"></div> | |
188 | <div id="pager"> |
|
190 | <div id="pager"> | |
189 | <div id='pager_button_area'> |
|
191 | <div id='pager_button_area'> | |
190 | </div> |
|
192 | </div> | |
191 | <div id="pager-container" class="container"></div> |
|
193 | <div id="pager-container" class="container"></div> | |
192 | </div> |
|
194 | </div> | |
193 | </div> |
|
195 | </div> | |
194 |
|
196 | |||
195 | </div> |
|
197 | </div> | |
196 | <div id='tooltip' class='ipython_tooltip' style='display:none'></div> |
|
198 | <div id='tooltip' class='ipython_tooltip' style='display:none'></div> | |
197 |
|
199 | |||
198 |
|
200 | |||
199 | {% endblock %} |
|
201 | {% endblock %} | |
200 |
|
202 | |||
201 |
|
203 | |||
202 | {% block script %} |
|
204 | {% block script %} | |
203 |
|
205 | |||
204 | {{super()}} |
|
206 | {{super()}} | |
205 |
|
207 | |||
206 | <script src="{{ static_url("components/codemirror/lib/codemirror.js") }}" charset="utf-8"></script> |
|
208 | <script src="{{ static_url("components/codemirror/lib/codemirror.js") }}" charset="utf-8"></script> | |
207 | <script type="text/javascript"> |
|
209 | <script type="text/javascript"> | |
208 | CodeMirror.modeURL = "{{ static_url("components/codemirror/mode/%N/%N.js") }}"; |
|
210 | CodeMirror.modeURL = "{{ static_url("components/codemirror/mode/%N/%N.js") }}"; | |
209 | </script> |
|
211 | </script> | |
210 | <script src="{{ static_url("components/codemirror/addon/mode/loadmode.js") }}" charset="utf-8"></script> |
|
212 | <script src="{{ static_url("components/codemirror/addon/mode/loadmode.js") }}" charset="utf-8"></script> | |
211 | <script src="{{ static_url("components/codemirror/addon/mode/multiplex.js") }}" charset="utf-8"></script> |
|
213 | <script src="{{ static_url("components/codemirror/addon/mode/multiplex.js") }}" charset="utf-8"></script> | |
212 | <script src="{{ static_url("components/codemirror/addon/mode/overlay.js") }}" charset="utf-8"></script> |
|
214 | <script src="{{ static_url("components/codemirror/addon/mode/overlay.js") }}" charset="utf-8"></script> | |
213 | <script src="{{ static_url("components/codemirror/addon/edit/matchbrackets.js") }}" charset="utf-8"></script> |
|
215 | <script src="{{ static_url("components/codemirror/addon/edit/matchbrackets.js") }}" charset="utf-8"></script> | |
214 | <script src="{{ static_url("components/codemirror/addon/comment/comment.js") }}" charset="utf-8"></script> |
|
216 | <script src="{{ static_url("components/codemirror/addon/comment/comment.js") }}" charset="utf-8"></script> | |
215 | <script src="{{ static_url("components/codemirror/mode/htmlmixed/htmlmixed.js") }}" charset="utf-8"></script> |
|
217 | <script src="{{ static_url("components/codemirror/mode/htmlmixed/htmlmixed.js") }}" charset="utf-8"></script> | |
216 | <script src="{{ static_url("components/codemirror/mode/xml/xml.js") }}" charset="utf-8"></script> |
|
218 | <script src="{{ static_url("components/codemirror/mode/xml/xml.js") }}" charset="utf-8"></script> | |
217 | <script src="{{ static_url("components/codemirror/mode/javascript/javascript.js") }}" charset="utf-8"></script> |
|
219 | <script src="{{ static_url("components/codemirror/mode/javascript/javascript.js") }}" charset="utf-8"></script> | |
218 | <script src="{{ static_url("components/codemirror/mode/css/css.js") }}" charset="utf-8"></script> |
|
220 | <script src="{{ static_url("components/codemirror/mode/css/css.js") }}" charset="utf-8"></script> | |
219 | <script src="{{ static_url("components/codemirror/mode/rst/rst.js") }}" charset="utf-8"></script> |
|
221 | <script src="{{ static_url("components/codemirror/mode/rst/rst.js") }}" charset="utf-8"></script> | |
220 | <script src="{{ static_url("components/codemirror/mode/markdown/markdown.js") }}" charset="utf-8"></script> |
|
222 | <script src="{{ static_url("components/codemirror/mode/markdown/markdown.js") }}" charset="utf-8"></script> | |
221 | <script src="{{ static_url("components/codemirror/mode/gfm/gfm.js") }}" charset="utf-8"></script> |
|
223 | <script src="{{ static_url("components/codemirror/mode/gfm/gfm.js") }}" charset="utf-8"></script> | |
222 | <script src="{{ static_url("components/codemirror/mode/python/python.js") }}" charset="utf-8"></script> |
|
224 | <script src="{{ static_url("components/codemirror/mode/python/python.js") }}" charset="utf-8"></script> | |
223 | <script src="{{ static_url("notebook/js/codemirror-ipython.js") }}" charset="utf-8"></script> |
|
225 | <script src="{{ static_url("notebook/js/codemirror-ipython.js") }}" charset="utf-8"></script> | |
224 |
|
226 | |||
225 | <script src="{{ static_url("components/highlight.js/build/highlight.pack.js") }}" charset="utf-8"></script> |
|
227 | <script src="{{ static_url("components/highlight.js/build/highlight.pack.js") }}" charset="utf-8"></script> | |
226 |
|
228 | |||
227 | <script src="{{ static_url("dateformat/date.format.js") }}" charset="utf-8"></script> |
|
229 | <script src="{{ static_url("dateformat/date.format.js") }}" charset="utf-8"></script> | |
228 |
|
230 | |||
229 | <script src="{{ static_url("base/js/events.js") }}" type="text/javascript" charset="utf-8"></script> |
|
231 | <script src="{{ static_url("base/js/events.js") }}" type="text/javascript" charset="utf-8"></script> | |
230 | <script src="{{ static_url("base/js/utils.js") }}" type="text/javascript" charset="utf-8"></script> |
|
232 | <script src="{{ static_url("base/js/utils.js") }}" type="text/javascript" charset="utf-8"></script> | |
231 | <script src="{{ static_url("base/js/dialog.js") }}" type="text/javascript" charset="utf-8"></script> |
|
233 | <script src="{{ static_url("base/js/dialog.js") }}" type="text/javascript" charset="utf-8"></script> | |
232 | <script src="{{ static_url("notebook/js/layoutmanager.js") }}" type="text/javascript" charset="utf-8"></script> |
|
234 | <script src="{{ static_url("notebook/js/layoutmanager.js") }}" type="text/javascript" charset="utf-8"></script> | |
233 | <script src="{{ static_url("notebook/js/mathjaxutils.js") }}" type="text/javascript" charset="utf-8"></script> |
|
235 | <script src="{{ static_url("notebook/js/mathjaxutils.js") }}" type="text/javascript" charset="utf-8"></script> | |
234 | <script src="{{ static_url("notebook/js/outputarea.js") }}" type="text/javascript" charset="utf-8"></script> |
|
236 | <script src="{{ static_url("notebook/js/outputarea.js") }}" type="text/javascript" charset="utf-8"></script> | |
235 | <script src="{{ static_url("notebook/js/cell.js") }}" type="text/javascript" charset="utf-8"></script> |
|
237 | <script src="{{ static_url("notebook/js/cell.js") }}" type="text/javascript" charset="utf-8"></script> | |
236 | <script src="{{ static_url("notebook/js/celltoolbar.js") }}" type="text/javascript" charset="utf-8"></script> |
|
238 | <script src="{{ static_url("notebook/js/celltoolbar.js") }}" type="text/javascript" charset="utf-8"></script> | |
237 | <script src="{{ static_url("notebook/js/codecell.js") }}" type="text/javascript" charset="utf-8"></script> |
|
239 | <script src="{{ static_url("notebook/js/codecell.js") }}" type="text/javascript" charset="utf-8"></script> | |
238 | <script src="{{ static_url("notebook/js/completer.js") }}" type="text/javascript" charset="utf-8"></script> |
|
240 | <script src="{{ static_url("notebook/js/completer.js") }}" type="text/javascript" charset="utf-8"></script> | |
239 | <script src="{{ static_url("notebook/js/textcell.js") }}" type="text/javascript" charset="utf-8"></script> |
|
241 | <script src="{{ static_url("notebook/js/textcell.js") }}" type="text/javascript" charset="utf-8"></script> | |
240 | <script src="{{ static_url("services/kernels/js/kernel.js") }}" type="text/javascript" charset="utf-8"></script> |
|
242 | <script src="{{ static_url("services/kernels/js/kernel.js") }}" type="text/javascript" charset="utf-8"></script> | |
241 | <script src="{{ static_url("notebook/js/savewidget.js") }}" type="text/javascript" charset="utf-8"></script> |
|
243 | <script src="{{ static_url("notebook/js/savewidget.js") }}" type="text/javascript" charset="utf-8"></script> | |
242 | <script src="{{ static_url("notebook/js/quickhelp.js") }}" type="text/javascript" charset="utf-8"></script> |
|
244 | <script src="{{ static_url("notebook/js/quickhelp.js") }}" type="text/javascript" charset="utf-8"></script> | |
243 | <script src="{{ static_url("notebook/js/pager.js") }}" type="text/javascript" charset="utf-8"></script> |
|
245 | <script src="{{ static_url("notebook/js/pager.js") }}" type="text/javascript" charset="utf-8"></script> | |
244 | <script src="{{ static_url("notebook/js/menubar.js") }}" type="text/javascript" charset="utf-8"></script> |
|
246 | <script src="{{ static_url("notebook/js/menubar.js") }}" type="text/javascript" charset="utf-8"></script> | |
245 | <script src="{{ static_url("notebook/js/toolbar.js") }}" type="text/javascript" charset="utf-8"></script> |
|
247 | <script src="{{ static_url("notebook/js/toolbar.js") }}" type="text/javascript" charset="utf-8"></script> | |
246 | <script src="{{ static_url("notebook/js/maintoolbar.js") }}" type="text/javascript" charset="utf-8"></script> |
|
248 | <script src="{{ static_url("notebook/js/maintoolbar.js") }}" type="text/javascript" charset="utf-8"></script> | |
247 | <script src="{{ static_url("notebook/js/notebook.js") }}" type="text/javascript" charset="utf-8"></script> |
|
249 | <script src="{{ static_url("notebook/js/notebook.js") }}" type="text/javascript" charset="utf-8"></script> | |
248 | <script src="{{ static_url("notebook/js/notificationwidget.js") }}" type="text/javascript" charset="utf-8"></script> |
|
250 | <script src="{{ static_url("notebook/js/notificationwidget.js") }}" type="text/javascript" charset="utf-8"></script> | |
249 | <script src="{{ static_url("notebook/js/notificationarea.js") }}" type="text/javascript" charset="utf-8"></script> |
|
251 | <script src="{{ static_url("notebook/js/notificationarea.js") }}" type="text/javascript" charset="utf-8"></script> | |
250 | <script src="{{ static_url("notebook/js/tooltip.js") }}" type="text/javascript" charset="utf-8"></script> |
|
252 | <script src="{{ static_url("notebook/js/tooltip.js") }}" type="text/javascript" charset="utf-8"></script> | |
251 | <script src="{{ static_url("notebook/js/config.js") }}" type="text/javascript" charset="utf-8"></script> |
|
253 | <script src="{{ static_url("notebook/js/config.js") }}" type="text/javascript" charset="utf-8"></script> | |
252 | <script src="{{ static_url("notebook/js/main.js") }}" type="text/javascript" charset="utf-8"></script> |
|
254 | <script src="{{ static_url("notebook/js/main.js") }}" type="text/javascript" charset="utf-8"></script> | |
253 |
|
255 | |||
254 | <script src="{{ static_url("notebook/js/contexthint.js") }}" charset="utf-8"></script> |
|
256 | <script src="{{ static_url("notebook/js/contexthint.js") }}" charset="utf-8"></script> | |
255 |
|
257 | |||
256 | <script src="{{ static_url("notebook/js/celltoolbarpresets/default.js") }}" type="text/javascript" charset="utf-8"></script> |
|
258 | <script src="{{ static_url("notebook/js/celltoolbarpresets/default.js") }}" type="text/javascript" charset="utf-8"></script> | |
257 | <script src="{{ static_url("notebook/js/celltoolbarpresets/slideshow.js") }}" type="text/javascript" charset="utf-8"></script> |
|
259 | <script src="{{ static_url("notebook/js/celltoolbarpresets/slideshow.js") }}" type="text/javascript" charset="utf-8"></script> | |
258 |
|
260 | |||
259 | {% endblock %} |
|
261 | {% endblock %} |
General Comments 0
You need to be logged in to leave comments.
Login now