##// END OF EJS Templates
Adding note about vbox related scroll bugs.
Brian E. Granger -
Show More
@@ -1,238 +1,239
1 /**
1 /**
2 * HTML5 ✰ Boilerplate
2 * HTML5 ✰ Boilerplate
3 *
3 *
4 * style.css contains a reset, font normalization and some base styles.
4 * style.css contains a reset, font normalization and some base styles.
5 *
5 *
6 * Credit is left where credit is due.
6 * Credit is left where credit is due.
7 * Much inspiration was taken from these projects:
7 * Much inspiration was taken from these projects:
8 * - yui.yahooapis.com/2.8.1/build/base/base.css
8 * - yui.yahooapis.com/2.8.1/build/base/base.css
9 * - camendesign.com/design/
9 * - camendesign.com/design/
10 * - praegnanz.de/weblog/htmlcssjs-kickstart
10 * - praegnanz.de/weblog/htmlcssjs-kickstart
11 */
11 */
12
12
13
13
14 /**
14 /**
15 * html5doctor.com Reset Stylesheet (Eric Meyer's Reset Reloaded + HTML5 baseline)
15 * html5doctor.com Reset Stylesheet (Eric Meyer's Reset Reloaded + HTML5 baseline)
16 * v1.6.1 2010-09-17 | Authors: Eric Meyer & Richard Clark
16 * v1.6.1 2010-09-17 | Authors: Eric Meyer & Richard Clark
17 * html5doctor.com/html-5-reset-stylesheet/
17 * html5doctor.com/html-5-reset-stylesheet/
18 */
18 */
19
19
20 html, body, div, span, object, iframe,
20 html, body, div, span, object, iframe,
21 h1, h2, h3, h4, h5, h6, p, blockquote, pre,
21 h1, h2, h3, h4, h5, h6, p, blockquote, pre,
22 abbr, address, cite, code, del, dfn, em, img, ins, kbd, q, samp,
22 abbr, address, cite, code, del, dfn, em, img, ins, kbd, q, samp,
23 small, strong, sub, sup, var, b, i, dl, dt, dd, ol, ul, li,
23 small, strong, sub, sup, var, b, i, dl, dt, dd, ol, ul, li,
24 fieldset, form, label, legend,
24 fieldset, form, label, legend,
25 table, caption, tbody, tfoot, thead, tr, th, td,
25 table, caption, tbody, tfoot, thead, tr, th, td,
26 article, aside, canvas, details, figcaption, figure,
26 article, aside, canvas, details, figcaption, figure,
27 footer, header, hgroup, menu, nav, section, summary,
27 footer, header, hgroup, menu, nav, section, summary,
28 time, mark, audio, video {
28 time, mark, audio, video {
29 margin: 0;
29 margin: 0;
30 padding: 0;
30 padding: 0;
31 border: 0;
31 border: 0;
32 /* font-size: 100%;*/
32 /* font-size: 100%;*/
33 font: inherit;
33 font: inherit;
34 vertical-align: baseline;
34 vertical-align: baseline;
35 }
35 }
36
36
37 article, aside, details, figcaption, figure,
37 article, aside, details, figcaption, figure,
38 footer, header, hgroup, menu, nav, section {
38 footer, header, hgroup, menu, nav, section {
39 display: block;
39 display: block;
40 }
40 }
41
41
42 blockquote, q { quotes: none; }
42 blockquote, q { quotes: none; }
43
43
44 blockquote:before, blockquote:after,
44 blockquote:before, blockquote:after,
45 q:before, q:after { content: ""; content: none; }
45 q:before, q:after { content: ""; content: none; }
46
46
47 ins { background-color: #ff9; color: #000; text-decoration: none; }
47 ins { background-color: #ff9; color: #000; text-decoration: none; }
48
48
49 mark { background-color: #ff9; color: #000; font-style: italic; font-weight: bold; }
49 mark { background-color: #ff9; color: #000; font-style: italic; font-weight: bold; }
50
50
51 del { text-decoration: line-through; }
51 del { text-decoration: line-through; }
52
52
53 abbr[title], dfn[title] { border-bottom: 1px dotted; cursor: help; }
53 abbr[title], dfn[title] { border-bottom: 1px dotted; cursor: help; }
54
54
55 table { border-collapse: collapse; border-spacing: 0; }
55 table { border-collapse: collapse; border-spacing: 0; }
56
56
57 hr { display: block; height: 1px; border: 0; border-top: 1px solid #ccc; margin: 1em 0; padding: 0; }
57 hr { display: block; height: 1px; border: 0; border-top: 1px solid #ccc; margin: 1em 0; padding: 0; }
58
58
59 input, select { vertical-align: middle; }
59 input, select { vertical-align: middle; }
60
60
61 body {
61 body {
62 background-color: white;
62 background-color: white;
63 /* This won't propagate to all children so we also set it below */
63 /* This won't propagate to all children so we also set it below */
64 font-size: 12pt;
64 font-size: 12pt;
65 /* This makes sure that the body covers the entire window and needs to
65 /* This makes sure that the body covers the entire window and needs to
66 be in a different element than the display: box in wrapper below */
66 be in a different element than the display: box in wrapper below */
67 position: absolute;
67 position: absolute;
68 left: 0px;
68 left: 0px;
69 right: 0px;
69 right: 0px;
70 top: 0px;
70 top: 0px;
71 bottom: 0px;
71 bottom: 0px;
72 overflow: hidden;
72 overflow: hidden;
73 }
73 }
74
74
75 div#wrapper {
75 div#wrapper {
76 /* This is needed to make sure the wrapper fills the body */
76 /* This is needed to make sure the wrapper fills the body */
77 width: 100%;
77 width: 100%;
78 height: 100%;
78 height: 100%;
79 }
79 }
80
80
81 span#ipython_notebook h1 {
81 span#ipython_notebook h1 {
82 font-family: Verdana, "Helvetica Neue", Arial, Helvetica, Geneva, sans-serif;
82 font-family: Verdana, "Helvetica Neue", Arial, Helvetica, Geneva, sans-serif;
83 font-size: 22pt;
83 font-size: 22pt;
84 padding: 10px;
84 padding: 10px;
85 margin: 10px;
85 margin: 10px;
86 }
86 }
87
87
88 div#tools {
88 div#tools {
89 font-size: 11pt;
89 font-size: 11pt;
90 }
90 }
91
91
92 span#kernel_status {
92 span#kernel_status {
93 position: absolute;
93 position: absolute;
94 top: 12%;
94 top: 12%;
95 right: 10px;
95 right: 10px;
96 font-weight: bold;
96 font-weight: bold;
97 }
97 }
98
98
99 .status_idle {
99 .status_idle {
100 color: gray;
100 color: gray;
101 }
101 }
102
102
103 .status_busy {
103 .status_busy {
104 color: red;
104 color: red;
105 }
105 }
106
106
107 .status_restarting {
107 .status_restarting {
108 color: black;
108 color: black;
109 }
109 }
110
110
111 div#notebook_app {
111 div#notebook_app {
112 width: 100%;
112 }
113 }
113
114
114 div#left_panel {
115 div#left_panel {
115 width: 200px;
116 width: 200px;
116 overflow-y: auto;
117 overflow-y: auto;
117 }
118 }
118
119
119 div#pager_splitter {
120 div#pager_splitter {
120 height: 7px;
121 height: 7px;
121 }
122 }
122
123
123 div#left_panel_splitter {
124 div#left_panel_splitter {
124 width: 7px;
125 width: 7px;
125 }
126 }
126
127
127 div#pager {
128 div#pager {
128 height: 200px;
129 height: 200px;
129 overflow: auto;
130 overflow: auto;
130 padding: 15px;
131 padding: 15px;
131 }
132 }
132
133
133 div#notebook {
134 div#notebook {
134 overflow-y: scroll;
135 overflow-y: scroll;
135 overflow-x: auto;
136 overflow-x: auto;
136 padding: 0px 15px;
137 padding: 0px 15px;
137 background-color: white;
138 background-color: white;
138 font-size: 12pt;
139 font-size: 12pt;
139 }
140 }
140
141
141 .monospace-font {
142 .monospace-font {
142 font-family: monospace;
143 font-family: monospace;
143 font-size: 12pt;
144 font-size: 12pt;
144 }
145 }
145
146
146 div.cell {
147 div.cell {
147 width: 100%;
148 width: 100%;
148 padding: 5px;
149 padding: 5px;
149 /* This acts as a spacer between cells, that is outside the border */
150 /* This acts as a spacer between cells, that is outside the border */
150 margin: 15px 0px 15px 0px;
151 margin: 15px 0px 15px 0px;
151 position: relative;
152 position: relative;
152 }
153 }
153
154
154 div.code_cell {
155 div.code_cell {
155 background-color: white;
156 background-color: white;
156 }
157 }
157
158
158 div.prompt {
159 div.prompt {
159 width: 90px;
160 width: 90px;
160 padding: 0px;
161 padding: 0px;
161 margin: 0px;
162 margin: 0px;
162 }
163 }
163
164
164 div.input_prompt {
165 div.input_prompt {
165 color: navy;
166 color: navy;
166 }
167 }
167
168
168 div.output {
169 div.output {
169 /* This is a spacer between the input and output of each cell */
170 /* This is a spacer between the input and output of each cell */
170 margin-top: 15px;
171 margin-top: 15px;
171 }
172 }
172
173
173 div.output_prompt {
174 div.output_prompt {
174 color: darkred;
175 color: darkred;
175 }
176 }
176
177
177 div.output_area {
178 div.output_area {
178 text-align: left;
179 text-align: left;
179 color: black;
180 color: black;
180 }
181 }
181
182
182 div.output_latex {
183 div.output_latex {
183 /* Slightly bigger than the rest of the notebook */
184 /* Slightly bigger than the rest of the notebook */
184 font-size: 13pt;
185 font-size: 13pt;
185 }
186 }
186
187
187 div.output_png {
188 div.output_png {
188 }
189 }
189
190
190 div.text_cell {
191 div.text_cell {
191 background-color: white;
192 background-color: white;
192 }
193 }
193
194
194 textarea.text_cell_input {
195 textarea.text_cell_input {
195 /* Slightly bigger than the rest of the notebook */
196 /* Slightly bigger than the rest of the notebook */
196 font-size: 13pt;
197 font-size: 13pt;
197 outline: none;
198 outline: none;
198 resize: none;
199 resize: none;
199 width: inherit;
200 width: inherit;
200 border-style: none;
201 border-style: none;
201 padding: 0px;
202 padding: 0px;
202 margin: 0px;
203 margin: 0px;
203 color: black;
204 color: black;
204 }
205 }
205
206
206 div.text_cell_render {
207 div.text_cell_render {
207 font-family: "Helvetica Neue", Arial, Helvetica, Geneva, sans-serif;
208 font-family: "Helvetica Neue", Arial, Helvetica, Geneva, sans-serif;
208 /* Slightly bigger than the rest of the notebook */
209 /* Slightly bigger than the rest of the notebook */
209 font-size: 13pt;
210 font-size: 13pt;
210 outline: none;
211 outline: none;
211 resize: none;
212 resize: none;
212 width: inherit;
213 width: inherit;
213 border-style: none;
214 border-style: none;
214 padding: 5px;
215 padding: 5px;
215 color: black;
216 color: black;
216 }
217 }
217
218
218 div.text_cell_render em {font-style: italic;}
219 div.text_cell_render em {font-style: italic;}
219 div.text_cell_render strong {font-weight: bold;}
220 div.text_cell_render strong {font-weight: bold;}
220 div.text_cell_render u {text-decoration: underline;}
221 div.text_cell_render u {text-decoration: underline;}
221 div.text_cell_render :link { text-decoration: underline }
222 div.text_cell_render :link { text-decoration: underline }
222 div.text_cell_render :visited { text-decoration: underline }
223 div.text_cell_render :visited { text-decoration: underline }
223 div.text_cell_render h1 {font-size: 2.0em; margin: .67em 0; font-weight: bold;}
224 div.text_cell_render h1 {font-size: 2.0em; margin: .67em 0; font-weight: bold;}
224 div.text_cell_render h2 {font-size: 1.5em; margin: .75em 0; font-weight: bold;}
225 div.text_cell_render h2 {font-size: 1.5em; margin: .75em 0; font-weight: bold;}
225 div.text_cell_render h3 {font-size: 1.17em; margin: .83em 0; font-weight: bold;}
226 div.text_cell_render h3 {font-size: 1.17em; margin: .83em 0; font-weight: bold;}
226 div.text_cell_render h4 {margin: 1.12em 0; font-weight: bold;}
227 div.text_cell_render h4 {margin: 1.12em 0; font-weight: bold;}
227 div.text_cell_render h5 {font-size: .83em; margin: 1.5em 0; font-weight: bold;}
228 div.text_cell_render h5 {font-size: .83em; margin: 1.5em 0; font-weight: bold;}
228 div.text_cell_render h6 {font-size: .75em; margin: 1.67em 0; font-weight: bold;}
229 div.text_cell_render h6 {font-size: .75em; margin: 1.67em 0; font-weight: bold;}
229 div.text_cell_render ul {list-style:disc; margin-left: 40px;}
230 div.text_cell_render ul {list-style:disc; margin-left: 40px;}
230 div.text_cell_render ul ul {list-style:square; margin-left: 40px;}
231 div.text_cell_render ul ul {list-style:square; margin-left: 40px;}
231 div.text_cell_render ul ul ul {list-style:circle; margin-left: 40px;}
232 div.text_cell_render ul ul ul {list-style:circle; margin-left: 40px;}
232 div.text_cell_render ol {list-style:upper-roman; margin-left: 40px;}
233 div.text_cell_render ol {list-style:upper-roman; margin-left: 40px;}
233 div.text_cell_render ol ol {list-style:upper-alpha;}
234 div.text_cell_render ol ol {list-style:upper-alpha;}
234 div.text_cell_render ol ol ol {list-style:decimal;}
235 div.text_cell_render ol ol ol {list-style:decimal;}
235 div.text_cell_render ol ol ol ol {list-style:lower-alpha;}
236 div.text_cell_render ol ol ol ol {list-style:lower-alpha;}
236 div.text_cell_render ol ol ol ol ol {list-style:lower-roman;}
237 div.text_cell_render ol ol ol ol ol {list-style:lower-roman;}
237
238
238
239
@@ -1,542 +1,544
1
1
2 //============================================================================
2 //============================================================================
3 // Notebook
3 // Notebook
4 //============================================================================
4 //============================================================================
5
5
6 var IPython = (function (IPython) {
6 var IPython = (function (IPython) {
7
7
8 var utils = IPython.utils;
8 var utils = IPython.utils;
9
9
10 var Notebook = function (selector) {
10 var Notebook = function (selector) {
11 this.element = $(selector);
11 this.element = $(selector);
12 this.element.scroll();
12 this.element.scroll();
13 this.element.data("notebook", this);
13 this.element.data("notebook", this);
14 this.next_prompt_number = 1;
14 this.next_prompt_number = 1;
15 this.kernel = null;
15 this.kernel = null;
16 this.msg_cell_map = {};
16 this.msg_cell_map = {};
17 this.filename = null;
17 this.filename = null;
18 this.notebook_load_re = /%notebook load/
18 this.notebook_load_re = /%notebook load/
19 this.notebook_save_re = /%notebook save/
19 this.notebook_save_re = /%notebook save/
20 this.notebook_filename_re = /(\w)+.ipynb/
20 this.notebook_filename_re = /(\w)+.ipynb/
21 this.style();
21 this.style();
22 this.bind_events();
22 this.bind_events();
23 this.start_kernel();
23 this.start_kernel();
24 };
24 };
25
25
26
26
27 Notebook.prototype.style = function () {
27 Notebook.prototype.style = function () {
28 // With vbox here Chrome exhibits the CodeMirror scroll bug.
29 // Without the vbox here, Firefox won't scroll the notebook div.
28 this.element.addClass('vbox box-flex1 border-box-sizing');
30 this.element.addClass('vbox box-flex1 border-box-sizing');
29 };
31 };
30
32
31
33
32 Notebook.prototype.bind_events = function () {
34 Notebook.prototype.bind_events = function () {
33 var that = this;
35 var that = this;
34 $(document).keydown(function (event) {
36 $(document).keydown(function (event) {
35 // console.log(event);
37 // console.log(event);
36 if (event.which === 38) {
38 if (event.which === 38) {
37 var cell = that.selected_cell();
39 var cell = that.selected_cell();
38 if (cell.at_top()) {
40 if (cell.at_top()) {
39 event.preventDefault();
41 event.preventDefault();
40 that.select_prev();
42 that.select_prev();
41 };
43 };
42 } else if (event.which === 40) {
44 } else if (event.which === 40) {
43 var cell = that.selected_cell();
45 var cell = that.selected_cell();
44 if (cell.at_bottom()) {
46 if (cell.at_bottom()) {
45 event.preventDefault();
47 event.preventDefault();
46 that.select_next();
48 that.select_next();
47 };
49 };
48 } else if (event.which === 13 && event.shiftKey) {
50 } else if (event.which === 13 && event.shiftKey) {
49 // The focus is not quite working here.
51 // The focus is not quite working here.
50 var cell = that.selected_cell();
52 var cell = that.selected_cell();
51 var cell_index = that.find_cell_index(cell);
53 var cell_index = that.find_cell_index(cell);
52 // TODO: the logic here needs to be moved into appropriate
54 // TODO: the logic here needs to be moved into appropriate
53 // methods of Notebook.
55 // methods of Notebook.
54 if (cell instanceof IPython.CodeCell) {
56 if (cell instanceof IPython.CodeCell) {
55 event.preventDefault();
57 event.preventDefault();
56 cell.clear_output();
58 cell.clear_output();
57 var code = cell.get_code();
59 var code = cell.get_code();
58 if (that.notebook_load_re.test(code)) {
60 if (that.notebook_load_re.test(code)) {
59 var code_parts = code.split(' ');
61 var code_parts = code.split(' ');
60 if (code_parts.length === 3) {
62 if (code_parts.length === 3) {
61 that.load_notebook(code_parts[2]);
63 that.load_notebook(code_parts[2]);
62 };
64 };
63 } else if (that.notebook_save_re.test(code)) {
65 } else if (that.notebook_save_re.test(code)) {
64 var code_parts = code.split(' ');
66 var code_parts = code.split(' ');
65 if (code_parts.length === 3) {
67 if (code_parts.length === 3) {
66 that.save_notebook(code_parts[2]);
68 that.save_notebook(code_parts[2]);
67 } else {
69 } else {
68 that.save_notebook()
70 that.save_notebook()
69 };
71 };
70 } else {
72 } else {
71 var msg_id = that.kernel.execute(cell.get_code());
73 var msg_id = that.kernel.execute(cell.get_code());
72 that.msg_cell_map[msg_id] = cell.cell_id;
74 that.msg_cell_map[msg_id] = cell.cell_id;
73 };
75 };
74 } else if (cell instanceof IPython.TextCell) {
76 } else if (cell instanceof IPython.TextCell) {
75 event.preventDefault();
77 event.preventDefault();
76 cell.render();
78 cell.render();
77 }
79 }
78 if (cell_index === (that.ncells()-1)) {
80 if (cell_index === (that.ncells()-1)) {
79 that.insert_code_cell_after();
81 that.insert_code_cell_after();
80 } else {
82 } else {
81 that.select(cell_index+1);
83 that.select(cell_index+1);
82 };
84 };
83 };
85 };
84 });
86 });
85 };
87 };
86
88
87
89
88 // Cell indexing, retrieval, etc.
90 // Cell indexing, retrieval, etc.
89
91
90
92
91 Notebook.prototype.cell_elements = function () {
93 Notebook.prototype.cell_elements = function () {
92 return this.element.children("div.cell");
94 return this.element.children("div.cell");
93 }
95 }
94
96
95
97
96 Notebook.prototype.ncells = function (cell) {
98 Notebook.prototype.ncells = function (cell) {
97 return this.cell_elements().length;
99 return this.cell_elements().length;
98 }
100 }
99
101
100
102
101 // TODO: we are often calling cells as cells()[i], which we should optimize
103 // TODO: we are often calling cells as cells()[i], which we should optimize
102 // to cells(i) or a new method.
104 // to cells(i) or a new method.
103 Notebook.prototype.cells = function () {
105 Notebook.prototype.cells = function () {
104 return this.cell_elements().toArray().map(function (e) {
106 return this.cell_elements().toArray().map(function (e) {
105 return $(e).data("cell");
107 return $(e).data("cell");
106 });
108 });
107 }
109 }
108
110
109
111
110 Notebook.prototype.find_cell_index = function (cell) {
112 Notebook.prototype.find_cell_index = function (cell) {
111 var result = null;
113 var result = null;
112 this.cell_elements().filter(function (index) {
114 this.cell_elements().filter(function (index) {
113 if ($(this).data("cell") === cell) {
115 if ($(this).data("cell") === cell) {
114 result = index;
116 result = index;
115 };
117 };
116 });
118 });
117 return result;
119 return result;
118 };
120 };
119
121
120
122
121 Notebook.prototype.index_or_selected = function (index) {
123 Notebook.prototype.index_or_selected = function (index) {
122 return index || this.selected_index() || 0;
124 return index || this.selected_index() || 0;
123 }
125 }
124
126
125
127
126 Notebook.prototype.select = function (index) {
128 Notebook.prototype.select = function (index) {
127 if (index !== undefined && index >= 0 && index < this.ncells()) {
129 if (index !== undefined && index >= 0 && index < this.ncells()) {
128 if (this.selected_index() !== null) {
130 if (this.selected_index() !== null) {
129 this.selected_cell().unselect();
131 this.selected_cell().unselect();
130 };
132 };
131 this.cells()[index].select();
133 this.cells()[index].select();
132 };
134 };
133 return this;
135 return this;
134 };
136 };
135
137
136
138
137 Notebook.prototype.select_next = function () {
139 Notebook.prototype.select_next = function () {
138 var index = this.selected_index();
140 var index = this.selected_index();
139 if (index !== null && index >= 0 && (index+1) < this.ncells()) {
141 if (index !== null && index >= 0 && (index+1) < this.ncells()) {
140 this.select(index+1);
142 this.select(index+1);
141 };
143 };
142 return this;
144 return this;
143 };
145 };
144
146
145
147
146 Notebook.prototype.select_prev = function () {
148 Notebook.prototype.select_prev = function () {
147 var index = this.selected_index();
149 var index = this.selected_index();
148 if (index !== null && index >= 0 && (index-1) < this.ncells()) {
150 if (index !== null && index >= 0 && (index-1) < this.ncells()) {
149 this.select(index-1);
151 this.select(index-1);
150 };
152 };
151 return this;
153 return this;
152 };
154 };
153
155
154
156
155 Notebook.prototype.selected_index = function () {
157 Notebook.prototype.selected_index = function () {
156 var result = null;
158 var result = null;
157 this.cell_elements().filter(function (index) {
159 this.cell_elements().filter(function (index) {
158 if ($(this).data("cell").selected === true) {
160 if ($(this).data("cell").selected === true) {
159 result = index;
161 result = index;
160 };
162 };
161 });
163 });
162 return result;
164 return result;
163 };
165 };
164
166
165
167
166 Notebook.prototype.cell_for_msg = function (msg_id) {
168 Notebook.prototype.cell_for_msg = function (msg_id) {
167 var cell_id = this.msg_cell_map[msg_id];
169 var cell_id = this.msg_cell_map[msg_id];
168 var result = null;
170 var result = null;
169 this.cell_elements().filter(function (index) {
171 this.cell_elements().filter(function (index) {
170 cell = $(this).data("cell");
172 cell = $(this).data("cell");
171 if (cell.cell_id === cell_id) {
173 if (cell.cell_id === cell_id) {
172 result = cell;
174 result = cell;
173 };
175 };
174 });
176 });
175 return result;
177 return result;
176 };
178 };
177
179
178
180
179 Notebook.prototype.selected_cell = function () {
181 Notebook.prototype.selected_cell = function () {
180 return this.cell_elements().eq(this.selected_index()).data("cell");
182 return this.cell_elements().eq(this.selected_index()).data("cell");
181 }
183 }
182
184
183
185
184 // Cell insertion, deletion and moving.
186 // Cell insertion, deletion and moving.
185
187
186
188
187 Notebook.prototype.delete_cell = function (index) {
189 Notebook.prototype.delete_cell = function (index) {
188 var i = index || this.selected_index();
190 var i = index || this.selected_index();
189 if (i !== null && i >= 0 && i < this.ncells()) {
191 if (i !== null && i >= 0 && i < this.ncells()) {
190 this.cell_elements().eq(i).remove();
192 this.cell_elements().eq(i).remove();
191 if (i === (this.ncells())) {
193 if (i === (this.ncells())) {
192 this.select(i-1);
194 this.select(i-1);
193 } else {
195 } else {
194 this.select(i);
196 this.select(i);
195 };
197 };
196 };
198 };
197 return this;
199 return this;
198 };
200 };
199
201
200
202
201 Notebook.prototype.append_cell = function (cell) {
203 Notebook.prototype.append_cell = function (cell) {
202 this.element.append(cell.element);
204 this.element.append(cell.element);
203 return this;
205 return this;
204 };
206 };
205
207
206
208
207 Notebook.prototype.insert_cell_after = function (cell, index) {
209 Notebook.prototype.insert_cell_after = function (cell, index) {
208 var ncells = this.ncells();
210 var ncells = this.ncells();
209 if (ncells === 0) {
211 if (ncells === 0) {
210 this.append_cell(cell);
212 this.append_cell(cell);
211 return this;
213 return this;
212 };
214 };
213 if (index >= 0 && index < ncells) {
215 if (index >= 0 && index < ncells) {
214 this.cell_elements().eq(index).after(cell.element);
216 this.cell_elements().eq(index).after(cell.element);
215 };
217 };
216 return this
218 return this
217 };
219 };
218
220
219
221
220 Notebook.prototype.insert_cell_before = function (cell, index) {
222 Notebook.prototype.insert_cell_before = function (cell, index) {
221 var ncells = this.ncells();
223 var ncells = this.ncells();
222 if (ncells === 0) {
224 if (ncells === 0) {
223 this.append_cell(cell);
225 this.append_cell(cell);
224 return this;
226 return this;
225 };
227 };
226 if (index >= 0 && index < ncells) {
228 if (index >= 0 && index < ncells) {
227 this.cell_elements().eq(index).before(cell.element);
229 this.cell_elements().eq(index).before(cell.element);
228 };
230 };
229 return this;
231 return this;
230 };
232 };
231
233
232
234
233 Notebook.prototype.move_cell_up = function (index) {
235 Notebook.prototype.move_cell_up = function (index) {
234 var i = index || this.selected_index();
236 var i = index || this.selected_index();
235 if (i !== null && i < this.ncells() && i > 0) {
237 if (i !== null && i < this.ncells() && i > 0) {
236 var pivot = this.cell_elements().eq(i-1);
238 var pivot = this.cell_elements().eq(i-1);
237 var tomove = this.cell_elements().eq(i);
239 var tomove = this.cell_elements().eq(i);
238 if (pivot !== null && tomove !== null) {
240 if (pivot !== null && tomove !== null) {
239 tomove.detach();
241 tomove.detach();
240 pivot.before(tomove);
242 pivot.before(tomove);
241 this.select(i-1);
243 this.select(i-1);
242 };
244 };
243 };
245 };
244 return this;
246 return this;
245 }
247 }
246
248
247
249
248 Notebook.prototype.move_cell_down = function (index) {
250 Notebook.prototype.move_cell_down = function (index) {
249 var i = index || this.selected_index();
251 var i = index || this.selected_index();
250 if (i !== null && i < (this.ncells()-1) && i >= 0) {
252 if (i !== null && i < (this.ncells()-1) && i >= 0) {
251 var pivot = this.cell_elements().eq(i+1)
253 var pivot = this.cell_elements().eq(i+1)
252 var tomove = this.cell_elements().eq(i)
254 var tomove = this.cell_elements().eq(i)
253 if (pivot !== null && tomove !== null) {
255 if (pivot !== null && tomove !== null) {
254 tomove.detach();
256 tomove.detach();
255 pivot.after(tomove);
257 pivot.after(tomove);
256 this.select(i+1);
258 this.select(i+1);
257 };
259 };
258 };
260 };
259 return this;
261 return this;
260 }
262 }
261
263
262
264
263 Notebook.prototype.sort_cells = function () {
265 Notebook.prototype.sort_cells = function () {
264 var ncells = this.ncells();
266 var ncells = this.ncells();
265 var sindex = this.selected_index();
267 var sindex = this.selected_index();
266 var swapped;
268 var swapped;
267 do {
269 do {
268 swapped = false
270 swapped = false
269 for (var i=1; i<ncells; i++) {
271 for (var i=1; i<ncells; i++) {
270 current = this.cell_elements().eq(i).data("cell");
272 current = this.cell_elements().eq(i).data("cell");
271 previous = this.cell_elements().eq(i-1).data("cell");
273 previous = this.cell_elements().eq(i-1).data("cell");
272 if (previous.input_prompt_number > current.input_prompt_number) {
274 if (previous.input_prompt_number > current.input_prompt_number) {
273 this.move_cell_up(i);
275 this.move_cell_up(i);
274 swapped = true;
276 swapped = true;
275 };
277 };
276 };
278 };
277 } while (swapped);
279 } while (swapped);
278 this.select(sindex);
280 this.select(sindex);
279 return this;
281 return this;
280 };
282 };
281
283
282
284
283 Notebook.prototype.insert_code_cell_before = function (index) {
285 Notebook.prototype.insert_code_cell_before = function (index) {
284 // TODO: Bounds check for i
286 // TODO: Bounds check for i
285 var i = this.index_or_selected(index);
287 var i = this.index_or_selected(index);
286 var cell = new IPython.CodeCell(this);
288 var cell = new IPython.CodeCell(this);
287 cell.set_input_prompt(this.next_prompt_number);
289 cell.set_input_prompt(this.next_prompt_number);
288 this.next_prompt_number = this.next_prompt_number + 1;
290 this.next_prompt_number = this.next_prompt_number + 1;
289 this.insert_cell_before(cell, i);
291 this.insert_cell_before(cell, i);
290 this.select(this.find_cell_index(cell));
292 this.select(this.find_cell_index(cell));
291 return this;
293 return this;
292 }
294 }
293
295
294
296
295 Notebook.prototype.insert_code_cell_after = function (index) {
297 Notebook.prototype.insert_code_cell_after = function (index) {
296 // TODO: Bounds check for i
298 // TODO: Bounds check for i
297 var i = this.index_or_selected(index);
299 var i = this.index_or_selected(index);
298 var cell = new IPython.CodeCell(this);
300 var cell = new IPython.CodeCell(this);
299 cell.set_input_prompt(this.next_prompt_number);
301 cell.set_input_prompt(this.next_prompt_number);
300 this.next_prompt_number = this.next_prompt_number + 1;
302 this.next_prompt_number = this.next_prompt_number + 1;
301 this.insert_cell_after(cell, i);
303 this.insert_cell_after(cell, i);
302 this.select(this.find_cell_index(cell));
304 this.select(this.find_cell_index(cell));
303 return this;
305 return this;
304 }
306 }
305
307
306
308
307 Notebook.prototype.insert_text_cell_before = function (index) {
309 Notebook.prototype.insert_text_cell_before = function (index) {
308 // TODO: Bounds check for i
310 // TODO: Bounds check for i
309 var i = this.index_or_selected(index);
311 var i = this.index_or_selected(index);
310 var cell = new IPython.TextCell(this);
312 var cell = new IPython.TextCell(this);
311 cell.config_mathjax();
313 cell.config_mathjax();
312 this.insert_cell_before(cell, i);
314 this.insert_cell_before(cell, i);
313 this.select(this.find_cell_index(cell));
315 this.select(this.find_cell_index(cell));
314 return this;
316 return this;
315 }
317 }
316
318
317
319
318 Notebook.prototype.insert_text_cell_after = function (index) {
320 Notebook.prototype.insert_text_cell_after = function (index) {
319 // TODO: Bounds check for i
321 // TODO: Bounds check for i
320 var i = this.index_or_selected(index);
322 var i = this.index_or_selected(index);
321 var cell = new IPython.TextCell(this);
323 var cell = new IPython.TextCell(this);
322 cell.config_mathjax();
324 cell.config_mathjax();
323 this.insert_cell_after(cell, i);
325 this.insert_cell_after(cell, i);
324 this.select(this.find_cell_index(cell));
326 this.select(this.find_cell_index(cell));
325 return this;
327 return this;
326 }
328 }
327
329
328
330
329 Notebook.prototype.text_to_code = function (index) {
331 Notebook.prototype.text_to_code = function (index) {
330 // TODO: Bounds check for i
332 // TODO: Bounds check for i
331 var i = this.index_or_selected(index);
333 var i = this.index_or_selected(index);
332 var source_element = this.cell_elements().eq(i);
334 var source_element = this.cell_elements().eq(i);
333 var source_cell = source_element.data("cell");
335 var source_cell = source_element.data("cell");
334 if (source_cell instanceof IPython.TextCell) {
336 if (source_cell instanceof IPython.TextCell) {
335 this.insert_code_cell_after(i);
337 this.insert_code_cell_after(i);
336 var target_cell = this.cells()[i+1];
338 var target_cell = this.cells()[i+1];
337 target_cell.set_code(source_cell.get_text());
339 target_cell.set_code(source_cell.get_text());
338 source_element.remove();
340 source_element.remove();
339 };
341 };
340 };
342 };
341
343
342
344
343 Notebook.prototype.code_to_text = function (index) {
345 Notebook.prototype.code_to_text = function (index) {
344 // TODO: Bounds check for i
346 // TODO: Bounds check for i
345 var i = this.index_or_selected(index);
347 var i = this.index_or_selected(index);
346 var source_element = this.cell_elements().eq(i);
348 var source_element = this.cell_elements().eq(i);
347 var source_cell = source_element.data("cell");
349 var source_cell = source_element.data("cell");
348 if (source_cell instanceof IPython.CodeCell) {
350 if (source_cell instanceof IPython.CodeCell) {
349 this.insert_text_cell_after(i);
351 this.insert_text_cell_after(i);
350 var target_cell = this.cells()[i+1];
352 var target_cell = this.cells()[i+1];
351 var text = source_cell.get_code();
353 var text = source_cell.get_code();
352 if (text === "") {text = target_cell.placeholder;};
354 if (text === "") {text = target_cell.placeholder;};
353 target_cell.set_text(text);
355 target_cell.set_text(text);
354 source_element.remove();
356 source_element.remove();
355 target_cell.edit();
357 target_cell.edit();
356 };
358 };
357 };
359 };
358
360
359
361
360 // Cell collapsing
362 // Cell collapsing
361
363
362 Notebook.prototype.collapse = function (index) {
364 Notebook.prototype.collapse = function (index) {
363 var i = this.index_or_selected(index);
365 var i = this.index_or_selected(index);
364 this.cells()[i].collapse();
366 this.cells()[i].collapse();
365 };
367 };
366
368
367
369
368 Notebook.prototype.expand = function (index) {
370 Notebook.prototype.expand = function (index) {
369 var i = this.index_or_selected(index);
371 var i = this.index_or_selected(index);
370 this.cells()[i].expand();
372 this.cells()[i].expand();
371 };
373 };
372
374
373
375
374 // Kernel related things
376 // Kernel related things
375
377
376 Notebook.prototype.start_kernel = function () {
378 Notebook.prototype.start_kernel = function () {
377 this.kernel = new IPython.Kernel();
379 this.kernel = new IPython.Kernel();
378 this.kernel.start_kernel($.proxy(this.kernel_started, this));
380 this.kernel.start_kernel($.proxy(this.kernel_started, this));
379 };
381 };
380
382
381
383
382 Notebook.prototype.handle_shell_reply = function (e) {
384 Notebook.prototype.handle_shell_reply = function (e) {
383 reply = $.parseJSON(e.data);
385 reply = $.parseJSON(e.data);
384 var header = reply.header;
386 var header = reply.header;
385 var content = reply.content;
387 var content = reply.content;
386 var msg_type = header.msg_type;
388 var msg_type = header.msg_type;
387 console.log(reply);
389 console.log(reply);
388 var cell = this.cell_for_msg(reply.parent_header.msg_id);
390 var cell = this.cell_for_msg(reply.parent_header.msg_id);
389 if (msg_type === "execute_reply") {
391 if (msg_type === "execute_reply") {
390 cell.set_input_prompt(content.execution_count);
392 cell.set_input_prompt(content.execution_count);
391 };
393 };
392 var payload = content.payload || [];
394 var payload = content.payload || [];
393 this.handle_payload(content.payload);
395 this.handle_payload(content.payload);
394 };
396 };
395
397
396
398
397 Notebook.prototype.handle_payload = function (payload) {
399 Notebook.prototype.handle_payload = function (payload) {
398 var l = payload.length;
400 var l = payload.length;
399 if (l > 0) {
401 if (l > 0) {
400 IPython.pager.clear();
402 IPython.pager.clear();
401 IPython.pager.expand();
403 IPython.pager.expand();
402 };
404 };
403 for (var i=0; i<l; i++) {
405 for (var i=0; i<l; i++) {
404 IPython.pager.append_text(payload[i].text);
406 IPython.pager.append_text(payload[i].text);
405 };
407 };
406 };
408 };
407
409
408
410
409 Notebook.prototype.handle_iopub_reply = function (e) {
411 Notebook.prototype.handle_iopub_reply = function (e) {
410 reply = $.parseJSON(e.data);
412 reply = $.parseJSON(e.data);
411 var content = reply.content;
413 var content = reply.content;
412 // console.log(reply);
414 // console.log(reply);
413 var msg_type = reply.header.msg_type;
415 var msg_type = reply.header.msg_type;
414 var cell = this.cell_for_msg(reply.parent_header.msg_id);
416 var cell = this.cell_for_msg(reply.parent_header.msg_id);
415 if (msg_type === "stream") {
417 if (msg_type === "stream") {
416 cell.expand();
418 cell.expand();
417 cell.append_stream(content.data + "\n");
419 cell.append_stream(content.data + "\n");
418 } else if (msg_type === "display_data") {
420 } else if (msg_type === "display_data") {
419 cell.expand();
421 cell.expand();
420 cell.append_display_data(content.data);
422 cell.append_display_data(content.data);
421 } else if (msg_type === "pyout") {
423 } else if (msg_type === "pyout") {
422 cell.expand();
424 cell.expand();
423 cell.append_pyout(content.data, content.execution_count)
425 cell.append_pyout(content.data, content.execution_count)
424 } else if (msg_type === "pyerr") {
426 } else if (msg_type === "pyerr") {
425 cell.expand();
427 cell.expand();
426 cell.append_pyerr(content.ename, content.evalue, content.traceback);
428 cell.append_pyerr(content.ename, content.evalue, content.traceback);
427 } else if (msg_type === "status") {
429 } else if (msg_type === "status") {
428 if (content.execution_state === "busy") {
430 if (content.execution_state === "busy") {
429 this.kernel.status_busy();
431 this.kernel.status_busy();
430 } else if (content.execution_state === "idle") {
432 } else if (content.execution_state === "idle") {
431 this.kernel.status_idle();
433 this.kernel.status_idle();
432 };
434 };
433 }
435 }
434 };
436 };
435
437
436
438
437 Notebook.prototype.kernel_started = function () {
439 Notebook.prototype.kernel_started = function () {
438 console.log("Kernel started: ", this.kernel.kernel_id);
440 console.log("Kernel started: ", this.kernel.kernel_id);
439 this.kernel.shell_channel.onmessage = $.proxy(this.handle_shell_reply,this);
441 this.kernel.shell_channel.onmessage = $.proxy(this.handle_shell_reply,this);
440 this.kernel.iopub_channel.onmessage = $.proxy(this.handle_iopub_reply,this);
442 this.kernel.iopub_channel.onmessage = $.proxy(this.handle_iopub_reply,this);
441 };
443 };
442
444
443
445
444 // Persistance and loading
446 // Persistance and loading
445
447
446
448
447 Notebook.prototype.fromJSON = function (data) {
449 Notebook.prototype.fromJSON = function (data) {
448 var ncells = this.ncells();
450 var ncells = this.ncells();
449 for (var i=0; i<ncells; i++) {
451 for (var i=0; i<ncells; i++) {
450 // Always delete cell 0 as they get renumbered as they are deleted.
452 // Always delete cell 0 as they get renumbered as they are deleted.
451 this.delete_cell(0);
453 this.delete_cell(0);
452 };
454 };
453 var new_cells = data.cells;
455 var new_cells = data.cells;
454 ncells = new_cells.length;
456 ncells = new_cells.length;
455 var cell_data = null;
457 var cell_data = null;
456 for (var i=0; i<ncells; i++) {
458 for (var i=0; i<ncells; i++) {
457 cell_data = new_cells[i];
459 cell_data = new_cells[i];
458 if (cell_data.cell_type == 'code') {
460 if (cell_data.cell_type == 'code') {
459 this.insert_code_cell_after();
461 this.insert_code_cell_after();
460 this.selected_cell().fromJSON(cell_data);
462 this.selected_cell().fromJSON(cell_data);
461 } else if (cell_data.cell_type === 'text') {
463 } else if (cell_data.cell_type === 'text') {
462 this.insert_text_cell_after();
464 this.insert_text_cell_after();
463 this.selected_cell().fromJSON(cell_data);
465 this.selected_cell().fromJSON(cell_data);
464 };
466 };
465 };
467 };
466 };
468 };
467
469
468
470
469 Notebook.prototype.toJSON = function () {
471 Notebook.prototype.toJSON = function () {
470 var cells = this.cells();
472 var cells = this.cells();
471 var ncells = cells.length;
473 var ncells = cells.length;
472 cell_array = new Array(ncells);
474 cell_array = new Array(ncells);
473 for (var i=0; i<ncells; i++) {
475 for (var i=0; i<ncells; i++) {
474 cell_array[i] = cells[i].toJSON();
476 cell_array[i] = cells[i].toJSON();
475 };
477 };
476 json = {
478 json = {
477 cells : cell_array
479 cells : cell_array
478 };
480 };
479 return json
481 return json
480 };
482 };
481
483
482
484
483 Notebook.prototype.test_filename = function (filename) {
485 Notebook.prototype.test_filename = function (filename) {
484 if (this.notebook_filename_re.test(filename)) {
486 if (this.notebook_filename_re.test(filename)) {
485 return true;
487 return true;
486 } else {
488 } else {
487 var bad_filename = $('<div/>');
489 var bad_filename = $('<div/>');
488 bad_filename.html(
490 bad_filename.html(
489 "The filename you entered (" + filename + ") is not valid. Notebook filenames must have the following form: foo.ipynb"
491 "The filename you entered (" + filename + ") is not valid. Notebook filenames must have the following form: foo.ipynb"
490 );
492 );
491 bad_filename.dialog({title: 'Invalid filename', modal: true});
493 bad_filename.dialog({title: 'Invalid filename', modal: true});
492 return false;
494 return false;
493 };
495 };
494 };
496 };
495
497
496 Notebook.prototype.save_notebook = function (filename) {
498 Notebook.prototype.save_notebook = function (filename) {
497 this.filename = filename || this.filename || '';
499 this.filename = filename || this.filename || '';
498 if (this.filename === '') {
500 if (this.filename === '') {
499 var no_filename = $('<div/>');
501 var no_filename = $('<div/>');
500 no_filename.html(
502 no_filename.html(
501 "This notebook has no filename, please specify a filename of the form: foo.ipynb"
503 "This notebook has no filename, please specify a filename of the form: foo.ipynb"
502 );
504 );
503 no_filename.dialog({title: 'Missing filename', modal: true});
505 no_filename.dialog({title: 'Missing filename', modal: true});
504 return;
506 return;
505 }
507 }
506 if (!this.test_filename(this.filename)) {return;}
508 if (!this.test_filename(this.filename)) {return;}
507 var thedata = this.toJSON();
509 var thedata = this.toJSON();
508 var settings = {
510 var settings = {
509 processData : false,
511 processData : false,
510 cache : false,
512 cache : false,
511 type : "PUT",
513 type : "PUT",
512 data : JSON.stringify(thedata),
514 data : JSON.stringify(thedata),
513 success : function (data, status, xhr) {console.log(data);}
515 success : function (data, status, xhr) {console.log(data);}
514 };
516 };
515 $.ajax("/notebooks/" + this.filename, settings);
517 $.ajax("/notebooks/" + this.filename, settings);
516 };
518 };
517
519
518
520
519 Notebook.prototype.load_notebook = function (filename) {
521 Notebook.prototype.load_notebook = function (filename) {
520 if (!this.test_filename(filename)) {return;}
522 if (!this.test_filename(filename)) {return;}
521 var that = this;
523 var that = this;
522 // We do the call with settings so we can set cache to false.
524 // We do the call with settings so we can set cache to false.
523 var settings = {
525 var settings = {
524 processData : false,
526 processData : false,
525 cache : false,
527 cache : false,
526 type : "GET",
528 type : "GET",
527 dataType : "json",
529 dataType : "json",
528 success : function (data, status, xhr) {
530 success : function (data, status, xhr) {
529 that.fromJSON(data);
531 that.fromJSON(data);
530 that.filename = filename;
532 that.filename = filename;
531 that.kernel.restart();
533 that.kernel.restart();
532 }
534 }
533 };
535 };
534 $.ajax("/notebooks/" + filename, settings);
536 $.ajax("/notebooks/" + filename, settings);
535 }
537 }
536
538
537 IPython.Notebook = Notebook;
539 IPython.Notebook = Notebook;
538
540
539 return IPython;
541 return IPython;
540
542
541 }(IPython));
543 }(IPython));
542
544
General Comments 0
You need to be logged in to leave comments. Login now