##// END OF EJS Templates
Merge pull request #2421 from Carreau/nbconsole...
Brian E. Granger -
r8527:f851aea2 merge
parent child Browse files
Show More
@@ -1,408 +1,408 b''
1 /**
1 /**
2 * Primary styles
2 * Primary styles
3 *
3 *
4 * Author: IPython Development Team
4 * Author: IPython Development Team
5 */
5 */
6
6
7
7
8 body {
8 body {
9 overflow: hidden;
9 overflow: hidden;
10 }
10 }
11
11
12 span#save_widget {
12 span#save_widget {
13 padding: 5px;
13 padding: 5px;
14 margin: 0px 0px 0px 300px;
14 margin: 0px 0px 0px 300px;
15 display:inline-block;
15 display:inline-block;
16 }
16 }
17
17
18 span#notebook_name {
18 span#notebook_name {
19 height: 1em;
19 height: 1em;
20 line-height: 1em;
20 line-height: 1em;
21 padding: 3px;
21 padding: 3px;
22 border: none;
22 border: none;
23 font-size: 146.5%;
23 font-size: 146.5%;
24 }
24 }
25
25
26 .ui-menubar-item .ui-button .ui-button-text {
26 .ui-menubar-item .ui-button .ui-button-text {
27 padding: 0.4em 1.0em;
27 padding: 0.4em 1.0em;
28 font-size: 100%;
28 font-size: 100%;
29 }
29 }
30
30
31 .ui-menu {
31 .ui-menu {
32 -moz-box-shadow: 0px 6px 10px -1px #adadad;
32 -moz-box-shadow: 0px 6px 10px -1px #adadad;
33 -webkit-box-shadow: 0px 6px 10px -1px #adadad;
33 -webkit-box-shadow: 0px 6px 10px -1px #adadad;
34 box-shadow: 0px 6px 10px -1px #adadad;
34 box-shadow: 0px 6px 10px -1px #adadad;
35 }
35 }
36
36
37 .ui-menu .ui-menu-item a {
37 .ui-menu .ui-menu-item a {
38 border: 1px solid transparent;
38 border: 1px solid transparent;
39 padding: 2px 1.6em;
39 padding: 2px 1.6em;
40 }
40 }
41
41
42 .ui-menu .ui-menu-item a.ui-state-focus {
42 .ui-menu .ui-menu-item a.ui-state-focus {
43 margin: 0;
43 margin: 0;
44 }
44 }
45
45
46 .ui-menu hr {
46 .ui-menu hr {
47 margin: 0.3em 0;
47 margin: 0.3em 0;
48 }
48 }
49
49
50 #menubar_container {
50 #menubar_container {
51 position: relative;
51 position: relative;
52 }
52 }
53
53
54 #notification_area {
54 #notification_area {
55 position: absolute;
55 position: absolute;
56 right: 0px;
56 right: 0px;
57 top: 0px;
57 top: 0px;
58 height: 25px;
58 height: 25px;
59 padding: 3px 0px;
59 padding: 3px 0px;
60 padding-right: 3px;
60 padding-right: 3px;
61 z-index: 10;
61 z-index: 10;
62 }
62 }
63
63
64 .notification_widget{
64 .notification_widget{
65 float : right;
65 float : right;
66 right: 0px;
66 right: 0px;
67 top: 1px;
67 top: 1px;
68 height: 25px;
68 height: 25px;
69 padding: 3px 6px;
69 padding: 3px 6px;
70 z-index: 10;
70 z-index: 10;
71 }
71 }
72
72
73 .toolbar {
73 .toolbar {
74 padding: 3px 15px;
74 padding: 3px 15px;
75 }
75 }
76
76
77 #cell_type {
77 #cell_type {
78 font-size: 85%;
78 font-size: 85%;
79 }
79 }
80
80
81
81
82 div#main_app {
82 div#main_app {
83 width: 100%;
83 width: 100%;
84 position: relative;
84 position: relative;
85 }
85 }
86
86
87 span#quick_help_area {
87 span#quick_help_area {
88 position: static;
88 position: static;
89 padding: 5px 0px;
89 padding: 5px 0px;
90 margin: 0px 0px 0px 0px;
90 margin: 0px 0px 0px 0px;
91 }
91 }
92
92
93 .help_string {
93 .help_string {
94 float: right;
94 float: right;
95 width: 170px;
95 width: 170px;
96 padding: 0px 5px;
96 padding: 0px 5px;
97 text-align: left;
97 text-align: left;
98 font-size: 85%;
98 font-size: 85%;
99 }
99 }
100
100
101 .help_string_label {
101 .help_string_label {
102 float: right;
102 float: right;
103 font-size: 85%;
103 font-size: 85%;
104 }
104 }
105
105
106 div#notebook_panel {
106 div#notebook_panel {
107 margin: 0px 0px 0px 0px;
107 margin: 0px 0px 0px 0px;
108 padding: 0px;
108 padding: 0px;
109 }
109 }
110
110
111 div#notebook {
111 div#notebook {
112 overflow-y: scroll;
112 overflow-y: scroll;
113 overflow-x: auto;
113 overflow-x: auto;
114 width: 100%;
114 width: 100%;
115 /* This spaces the cell away from the edge of the notebook area */
115 /* This spaces the cell away from the edge of the notebook area */
116 padding: 5px 5px 15px 5px;
116 padding: 5px 5px 15px 5px;
117 margin: 0px;
117 margin: 0px;
118 background-color: white;
118 background-color: white;
119 }
119 }
120
120
121 div#pager_splitter {
121 div#pager_splitter {
122 height: 8px;
122 height: 8px;
123 }
123 }
124
124
125 #pager_container {
125 #pager_container {
126 position : relative;
126 position : relative;
127 }
127 }
128
128
129 div#pager {
129 div#pager {
130 padding: 15px;
130 padding: 15px;
131 overflow: auto;
131 overflow: auto;
132 display: none;
132 display: none;
133 }
133 }
134
134
135 div.ui-widget-content {
135 div.ui-widget-content {
136 border: 1px solid #aaa;
136 border: 1px solid #aaa;
137 outline: none;
137 outline: none;
138 }
138 }
139
139
140 .cell {
140 .cell {
141 border: 1px solid transparent;
141 border: 1px solid transparent;
142 }
142 }
143
143
144 div.cell {
144 div.cell {
145 width: 100%;
145 width: 100%;
146 padding: 5px 5px 5px 0px;
146 padding: 5px 5px 5px 0px;
147 /* This acts as a spacer between cells, that is outside the border */
147 /* This acts as a spacer between cells, that is outside the border */
148 margin: 2px 0px 2px 0px;
148 margin: 2px 0px 2px 0px;
149 }
149 }
150
150
151 div.code_cell {
151 div.code_cell {
152 background-color: white;
152 background-color: white;
153 }
153 }
154
154
155 /* any special styling for code cells that are currently running goes here */
155 /* any special styling for code cells that are currently running goes here */
156 div.code_cell.running {
156 div.code_cell.running {
157 }
157 }
158
158
159 div.prompt {
159 div.prompt {
160 /* This needs to be wide enough for 3 digit prompt numbers: In[100]: */
160 /* This needs to be wide enough for 3 digit prompt numbers: In[100]: */
161 width: 11ex;
161 width: 11ex;
162 /* This 0.4em is tuned to match the padding on the CodeMirror editor. */
162 /* This 0.4em is tuned to match the padding on the CodeMirror editor. */
163 padding: 0.4em;
163 padding: 0.4em;
164 margin: 0px;
164 margin: 0px;
165 font-family: monospace;
165 font-family: monospace;
166 text-align:right;
166 text-align:right;
167 }
167 }
168
168
169 div.input {
169 div.input {
170 page-break-inside: avoid;
170 page-break-inside: avoid;
171 }
171 }
172
172
173 /* input_area and input_prompt must match in top border and margin for alignment */
173 /* input_area and input_prompt must match in top border and margin for alignment */
174 div.input_area {
174 div.input_area {
175 color: black;
175 color: black;
176 border: 1px solid #ddd;
176 border: 1px solid #ddd;
177 border-radius: 3px;
177 border-radius: 3px;
178 background: #f7f7f7;
178 background: #f7f7f7;
179 }
179 }
180
180
181 div.input_prompt {
181 div.input_prompt {
182 color: navy;
182 color: navy;
183 border-top: 1px solid transparent;
183 border-top: 1px solid transparent;
184 }
184 }
185
185
186 div.output_wrapper {
186 div.output_wrapper {
187 /* This is a spacer between the input and output of each cell */
187 /* This is a spacer between the input and output of each cell */
188 margin-top: 5px;
188 margin-top: 5px;
189 margin-left: 5px;
189 margin-left: 5px;
190 /* FF needs explicit width to stretch */
190 /* FF needs explicit width to stretch */
191 width: 100%;
191 width: 100%;
192 /* this position must be relative to enable descendents to be absolute within it */
192 /* this position must be relative to enable descendents to be absolute within it */
193 position: relative;
193 position: relative;
194 }
194 }
195
195
196 /* class for the output area when it should be height-limited */
196 /* class for the output area when it should be height-limited */
197 div.output_scroll {
197 div.output_scroll {
198 /* ideally, this would be max-height, but FF barfs all over that */
198 /* ideally, this would be max-height, but FF barfs all over that */
199 height: 24em;
199 height: 24em;
200 /* FF needs this *and the wrapper* to specify full width, or it will shrinkwrap */
200 /* FF needs this *and the wrapper* to specify full width, or it will shrinkwrap */
201 width: 100%;
201 width: 100%;
202
202
203 overflow: auto;
203 overflow: auto;
204 border-radius: 3px;
204 border-radius: 3px;
205 box-shadow: inset 0 2px 8px rgba(0, 0, 0, .8);
205 box-shadow: inset 0 2px 8px rgba(0, 0, 0, .8);
206 }
206 }
207
207
208 /* output div while it is collapsed */
208 /* output div while it is collapsed */
209 div.output_collapsed {
209 div.output_collapsed {
210 margin-right: 5px;
210 margin-right: 5px;
211 }
211 }
212
212
213 div.out_prompt_overlay {
213 div.out_prompt_overlay {
214 height: 100%;
214 height: 100%;
215 padding: 0px;
215 padding: 0px;
216 position: absolute;
216 position: absolute;
217 border-radius: 3px;
217 border-radius: 3px;
218 }
218 }
219
219
220 div.out_prompt_overlay:hover {
220 div.out_prompt_overlay:hover {
221 /* use inner shadow to get border that is computed the same on WebKit/FF */
221 /* use inner shadow to get border that is computed the same on WebKit/FF */
222 box-shadow: inset 0 0 1px #000;
222 box-shadow: inset 0 0 1px #000;
223 background: rgba(240, 240, 240, 0.5);
223 background: rgba(240, 240, 240, 0.5);
224 }
224 }
225
225
226 div.output_prompt {
226 div.output_prompt {
227 color: darkred;
227 color: darkred;
228 /* 5px right shift to account for margin in parent container */
228 /* 5px right shift to account for margin in parent container */
229 margin: 0 5px 0 -5px;
229 margin: 0 5px 0 -5px;
230 }
230 }
231
231
232 /* This class is the outer container of all output sections. */
232 /* This class is the outer container of all output sections. */
233 div.output_area {
233 div.output_area {
234 padding: 0px;
234 padding: 0px;
235 page-break-inside: avoid;
235 page-break-inside: avoid;
236 }
236 }
237
237
238 /* This class is for the output subarea inside the output_area and after
238 /* This class is for the output subarea inside the output_area and after
239 the prompt div. */
239 the prompt div. */
240 div.output_subarea {
240 div.output_subarea {
241 padding: 0.4em 0.4em 0.4em 0.4em;
241 padding: 0.44em 0.4em 0.4em 1px;
242 }
242 }
243
243
244 /* The rest of the output_* classes are for special styling of the different
244 /* The rest of the output_* classes are for special styling of the different
245 output types */
245 output types */
246
246
247 /* all text output has this class: */
247 /* all text output has this class: */
248 div.output_text {
248 div.output_text {
249 text-align: left;
249 text-align: left;
250 color: black;
250 color: black;
251 font-family: monospace;
251 font-family: monospace;
252 }
252 }
253
253
254 /* stdout/stderr are 'text' as well as 'stream', but pyout/pyerr are *not* streams */
254 /* stdout/stderr are 'text' as well as 'stream', but pyout/pyerr are *not* streams */
255 div.output_stream {
255 div.output_stream {
256 padding-top: 0.0em;
256 padding-top: 0.0em;
257 padding-bottom: 0.0em;
257 padding-bottom: 0.0em;
258 }
258 }
259 div.output_stdout {
259 div.output_stdout {
260 }
260 }
261 div.output_stderr {
261 div.output_stderr {
262 background: #fdd; /* very light red background for stderr */
262 background: #fdd; /* very light red background for stderr */
263 }
263 }
264
264
265 div.output_latex {
265 div.output_latex {
266 text-align: left;
266 text-align: left;
267 color: black;
267 color: black;
268 }
268 }
269
269
270 div.output_html {
270 div.output_html {
271 }
271 }
272
272
273 div.output_png {
273 div.output_png {
274 }
274 }
275
275
276 div.output_jpeg {
276 div.output_jpeg {
277 }
277 }
278
278
279 div.text_cell {
279 div.text_cell {
280 background-color: white;
280 background-color: white;
281 padding: 5px 5px 5px 5px;
281 padding: 5px 5px 5px 5px;
282 }
282 }
283
283
284 div.text_cell_input {
284 div.text_cell_input {
285 color: black;
285 color: black;
286 border: 1px solid #ddd;
286 border: 1px solid #ddd;
287 border-radius: 3px;
287 border-radius: 3px;
288 background: #f7f7f7;
288 background: #f7f7f7;
289 }
289 }
290
290
291 div.text_cell_render {
291 div.text_cell_render {
292 font-family: "Helvetica Neue", Arial, Helvetica, Geneva, sans-serif;
292 font-family: "Helvetica Neue", Arial, Helvetica, Geneva, sans-serif;
293 outline: none;
293 outline: none;
294 resize: none;
294 resize: none;
295 width: inherit;
295 width: inherit;
296 border-style: none;
296 border-style: none;
297 padding: 5px;
297 padding: 5px;
298 color: black;
298 color: black;
299 }
299 }
300
300
301 /* The following gets added to the <head> if it is detected that the user has a
301 /* The following gets added to the <head> if it is detected that the user has a
302 * monospace font with inconsistent normal/bold/italic height. See
302 * monospace font with inconsistent normal/bold/italic height. See
303 * notebookmain.js. Such fonts will have keywords vertically offset with
303 * notebookmain.js. Such fonts will have keywords vertically offset with
304 * respect to the rest of the text. The user should select a better font.
304 * respect to the rest of the text. The user should select a better font.
305 * See: https://github.com/ipython/ipython/issues/1503
305 * See: https://github.com/ipython/ipython/issues/1503
306 *
306 *
307 * .CodeMirror span {
307 * .CodeMirror span {
308 * vertical-align: bottom;
308 * vertical-align: bottom;
309 * }
309 * }
310 */
310 */
311
311
312 .CodeMirror {
312 .CodeMirror {
313 line-height: 1.231; /* Changed from 1em to our global default */
313 line-height: 1.231; /* Changed from 1em to our global default */
314 }
314 }
315
315
316 .CodeMirror-scroll {
316 .CodeMirror-scroll {
317 height: auto; /* Changed to auto to autogrow */
317 height: auto; /* Changed to auto to autogrow */
318 /* The CodeMirror docs are a bit fuzzy on if overflow-y should be hidden or visible.*/
318 /* The CodeMirror docs are a bit fuzzy on if overflow-y should be hidden or visible.*/
319 /* We have found that if it is visible, vertical scrollbars appear with font size changes.*/
319 /* We have found that if it is visible, vertical scrollbars appear with font size changes.*/
320 overflow-y: hidden;
320 overflow-y: hidden;
321 overflow-x: auto; /* Changed from auto to remove scrollbar */
321 overflow-x: auto; /* Changed from auto to remove scrollbar */
322 }
322 }
323
323
324 /* CSS font colors for translated ANSI colors. */
324 /* CSS font colors for translated ANSI colors. */
325
325
326
326
327 .ansiblack {color: black;}
327 .ansiblack {color: black;}
328 .ansired {color: darkred;}
328 .ansired {color: darkred;}
329 .ansigreen {color: darkgreen;}
329 .ansigreen {color: darkgreen;}
330 .ansiyellow {color: brown;}
330 .ansiyellow {color: brown;}
331 .ansiblue {color: darkblue;}
331 .ansiblue {color: darkblue;}
332 .ansipurple {color: darkviolet;}
332 .ansipurple {color: darkviolet;}
333 .ansicyan {color: steelblue;}
333 .ansicyan {color: steelblue;}
334 .ansigrey {color: grey;}
334 .ansigrey {color: grey;}
335 .ansibold {font-weight: bold;}
335 .ansibold {font-weight: bold;}
336
336
337 .completions {
337 .completions {
338 position: absolute;
338 position: absolute;
339 z-index: 10;
339 z-index: 10;
340 overflow: hidden;
340 overflow: hidden;
341 border: 1px solid grey;
341 border: 1px solid grey;
342 }
342 }
343
343
344 .completions select {
344 .completions select {
345 background: white;
345 background: white;
346 outline: none;
346 outline: none;
347 border: none;
347 border: none;
348 padding: 0px;
348 padding: 0px;
349 margin: 0px;
349 margin: 0px;
350 overflow: auto;
350 overflow: auto;
351 font-family: monospace;
351 font-family: monospace;
352 }
352 }
353
353
354 option.context {
354 option.context {
355 background-color: #DEF7FF;
355 background-color: #DEF7FF;
356 }
356 }
357 option.introspection {
357 option.introspection {
358 background-color: #EBF4EB;
358 background-color: #EBF4EB;
359 }
359 }
360
360
361 /*fixed part of the completion*/
361 /*fixed part of the completion*/
362 .completions p b {
362 .completions p b {
363 font-weight:bold;
363 font-weight:bold;
364 }
364 }
365
365
366 .completions p {
366 .completions p {
367 background: #DDF;
367 background: #DDF;
368 /*outline: none;
368 /*outline: none;
369 padding: 0px;*/
369 padding: 0px;*/
370 border-bottom: black solid 1px;
370 border-bottom: black solid 1px;
371 padding: 1px;
371 padding: 1px;
372 font-family: monospace;
372 font-family: monospace;
373 }
373 }
374
374
375 pre.dialog {
375 pre.dialog {
376 background-color: #f7f7f7;
376 background-color: #f7f7f7;
377 border: 1px solid #ddd;
377 border: 1px solid #ddd;
378 border-radius: 3px;
378 border-radius: 3px;
379 padding: 0.4em;
379 padding: 0.4em;
380 padding-left: 2em;
380 padding-left: 2em;
381 }
381 }
382
382
383 p.dialog {
383 p.dialog {
384 padding : 0.2em;
384 padding : 0.2em;
385 }
385 }
386
386
387 .shortcut_key {
387 .shortcut_key {
388 display: inline-block;
388 display: inline-block;
389 width: 15ex;
389 width: 15ex;
390 text-align: right;
390 text-align: right;
391 font-family: monospace;
391 font-family: monospace;
392 }
392 }
393
393
394 .shortcut_descr {
394 .shortcut_descr {
395 }
395 }
396
396
397 /* Word-wrap output correctly. This is the CSS3 spelling, though Firefox seems
397 /* Word-wrap output correctly. This is the CSS3 spelling, though Firefox seems
398 to not honor it correctly. Webkit browsers (Chrome, rekonq, Safari) do.
398 to not honor it correctly. Webkit browsers (Chrome, rekonq, Safari) do.
399 */
399 */
400 pre, code, kbd, samp { white-space: pre-wrap; }
400 pre, code, kbd, samp { white-space: pre-wrap; }
401
401
402 #fonttest {
402 #fonttest {
403 font-family: monospace;
403 font-family: monospace;
404 }
404 }
405
405
406 .js-error {
406 .js-error {
407 color: darkred;
407 color: darkred;
408 }
408 }
@@ -1,322 +1,345 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 // CodeCell
9 // CodeCell
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 CodeMirror.modeURL = "/static/codemirror/mode/%N/%N.js";
17 CodeMirror.modeURL = "/static/codemirror/mode/%N/%N.js";
18
18
19 var CodeCell = function (kernel) {
19 var CodeCell = function (kernel) {
20 // The kernel doesn't have to be set at creation time, in that case
20 // The kernel doesn't have to be set at creation time, in that case
21 // it will be null and set_kernel has to be called later.
21 // it will be null and set_kernel has to be called later.
22 this.kernel = kernel || null;
22 this.kernel = kernel || null;
23 this.code_mirror = null;
23 this.code_mirror = null;
24 this.input_prompt_number = null;
24 this.input_prompt_number = null;
25 this.tooltip_on_tab = true;
25 this.tooltip_on_tab = true;
26 this.collapsed = false;
26 this.collapsed = false;
27 this.default_mode = 'python';
27 this.default_mode = 'python';
28 IPython.Cell.apply(this, arguments);
28 IPython.Cell.apply(this, arguments);
29
29
30 var that = this;
30 var that = this;
31 this.element.focusout(
31 this.element.focusout(
32 function() { that.auto_highlight(); }
32 function() { that.auto_highlight(); }
33 );
33 );
34 };
34 };
35
35
36
36
37 CodeCell.prototype = new IPython.Cell();
37 CodeCell.prototype = new IPython.Cell();
38
38
39
39
40 CodeCell.prototype.auto_highlight = function () {
40 CodeCell.prototype.auto_highlight = function () {
41 this._auto_highlight(IPython.config.cell_magic_highlight)
41 this._auto_highlight(IPython.config.cell_magic_highlight)
42 };
42 };
43
43
44 CodeCell.prototype.create_element = function () {
44 CodeCell.prototype.create_element = function () {
45 var cell = $('<div></div>').addClass('cell border-box-sizing code_cell vbox');
45 var cell = $('<div></div>').addClass('cell border-box-sizing code_cell vbox');
46 cell.attr('tabindex','2');
46 cell.attr('tabindex','2');
47 var input = $('<div></div>').addClass('input hbox');
47 var input = $('<div></div>').addClass('input hbox');
48 input.append($('<div/>').addClass('prompt input_prompt'));
48 input.append($('<div/>').addClass('prompt input_prompt'));
49 var input_area = $('<div/>').addClass('input_area box-flex1');
49 var input_area = $('<div/>').addClass('input_area box-flex1');
50 this.code_mirror = CodeMirror(input_area.get(0), {
50 this.code_mirror = CodeMirror(input_area.get(0), {
51 indentUnit : 4,
51 indentUnit : 4,
52 mode: 'python',
52 mode: 'python',
53 theme: 'ipython',
53 theme: 'ipython',
54 readOnly: this.read_only,
54 readOnly: this.read_only,
55 extraKeys: {"Tab": "indentMore","Shift-Tab" : "indentLess",'Backspace':"delSpaceToPrevTabStop"},
55 extraKeys: {"Tab": "indentMore","Shift-Tab" : "indentLess",'Backspace':"delSpaceToPrevTabStop"},
56 onKeyEvent: $.proxy(this.handle_codemirror_keyevent,this)
56 onKeyEvent: $.proxy(this.handle_codemirror_keyevent,this)
57 });
57 });
58 input.append(input_area);
58 input.append(input_area);
59 var output = $('<div></div>');
59 var output = $('<div></div>');
60 cell.append(input).append(output);
60 cell.append(input).append(output);
61 this.element = cell;
61 this.element = cell;
62 this.output_area = new IPython.OutputArea(output, true);
62 this.output_area = new IPython.OutputArea(output, true);
63
63
64 // construct a completer only if class exist
64 // construct a completer only if class exist
65 // otherwise no print view
65 // otherwise no print view
66 if (IPython.Completer !== undefined)
66 if (IPython.Completer !== undefined)
67 {
67 {
68 this.completer = new IPython.Completer(this);
68 this.completer = new IPython.Completer(this);
69 }
69 }
70 };
70 };
71
71
72 CodeCell.prototype.handle_codemirror_keyevent = function (editor, event) {
72 CodeCell.prototype.handle_codemirror_keyevent = function (editor, event) {
73 // This method gets called in CodeMirror's onKeyDown/onKeyPress
73 // This method gets called in CodeMirror's onKeyDown/onKeyPress
74 // handlers and is used to provide custom key handling. Its return
74 // handlers and is used to provide custom key handling. Its return
75 // value is used to determine if CodeMirror should ignore the event:
75 // value is used to determine if CodeMirror should ignore the event:
76 // true = ignore, false = don't ignore.
76 // true = ignore, false = don't ignore.
77
77
78 if (this.read_only){
78 if (this.read_only){
79 return false;
79 return false;
80 }
80 }
81
81
82 var that = this;
82 var that = this;
83 // whatever key is pressed, first, cancel the tooltip request before
83 // whatever key is pressed, first, cancel the tooltip request before
84 // they are sent, and remove tooltip if any, except for tab again
84 // they are sent, and remove tooltip if any, except for tab again
85 if (event.type === 'keydown' && event.which != key.TAB ) {
85 if (event.type === 'keydown' && event.which != key.TAB ) {
86 IPython.tooltip.remove_and_cancel_tooltip();
86 IPython.tooltip.remove_and_cancel_tooltip();
87 };
87 };
88
88
89 var cur = editor.getCursor();
89 var cur = editor.getCursor();
90 if (event.keyCode === key.ENTER){
90 if (event.keyCode === key.ENTER){
91 this.auto_highlight();
91 this.auto_highlight();
92 }
92 }
93
93
94 if (event.keyCode === key.ENTER && (event.shiftKey || event.ctrlKey)) {
94 if (event.keyCode === key.ENTER && (event.shiftKey || event.ctrlKey)) {
95 // Always ignore shift-enter in CodeMirror as we handle it.
95 // Always ignore shift-enter in CodeMirror as we handle it.
96 return true;
96 return true;
97 } else if (event.which === 40 && event.type === 'keypress' && IPython.tooltip.time_before_tooltip >= 0) {
97 } else if (event.which === 40 && event.type === 'keypress' && IPython.tooltip.time_before_tooltip >= 0) {
98 // triger on keypress (!) otherwise inconsistent event.which depending on plateform
98 // triger on keypress (!) otherwise inconsistent event.which depending on plateform
99 // browser and keyboard layout !
99 // browser and keyboard layout !
100 // Pressing '(' , request tooltip, don't forget to reappend it
100 // Pressing '(' , request tooltip, don't forget to reappend it
101 IPython.tooltip.pending(that);
101 IPython.tooltip.pending(that);
102 } else if (event.which === key.UPARROW && event.type === 'keydown') {
102 } else if (event.which === key.UPARROW && event.type === 'keydown') {
103 // If we are not at the top, let CM handle the up arrow and
103 // If we are not at the top, let CM handle the up arrow and
104 // prevent the global keydown handler from handling it.
104 // prevent the global keydown handler from handling it.
105 if (!that.at_top()) {
105 if (!that.at_top()) {
106 event.stop();
106 event.stop();
107 return false;
107 return false;
108 } else {
108 } else {
109 return true;
109 return true;
110 };
110 };
111 } else if (event.which === key.ESC) {
111 } else if (event.which === key.ESC) {
112 IPython.tooltip.remove_and_cancel_tooltip(true);
112 IPython.tooltip.remove_and_cancel_tooltip(true);
113 return true;
113 return true;
114 } else if (event.which === key.DOWNARROW && event.type === 'keydown') {
114 } else if (event.which === key.DOWNARROW && event.type === 'keydown') {
115 // If we are not at the bottom, let CM handle the down arrow and
115 // If we are not at the bottom, let CM handle the down arrow and
116 // prevent the global keydown handler from handling it.
116 // prevent the global keydown handler from handling it.
117 if (!that.at_bottom()) {
117 if (!that.at_bottom()) {
118 event.stop();
118 event.stop();
119 return false;
119 return false;
120 } else {
120 } else {
121 return true;
121 return true;
122 };
122 };
123 } else if (event.keyCode === key.TAB && event.type == 'keydown') {
123 } else if (event.keyCode === key.TAB && event.type == 'keydown') {
124 // Tab completion.
124 // Tab completion.
125 //Do not trim here because of tooltip
125 //Do not trim here because of tooltip
126 var pre_cursor = editor.getRange({line:cur.line,ch:0},cur);
126 var pre_cursor = editor.getRange({line:cur.line,ch:0},cur);
127 if (pre_cursor.trim() === "") {
127 if (pre_cursor.trim() === "") {
128 // Don't autocomplete if the part of the line before the cursor
128 // Don't autocomplete if the part of the line before the cursor
129 // is empty. In this case, let CodeMirror handle indentation.
129 // is empty. In this case, let CodeMirror handle indentation.
130 return false;
130 return false;
131 } else if ((pre_cursor.substr(-1) === "("|| pre_cursor.substr(-1) === " ") && that.tooltip_on_tab ) {
131 } else if ((pre_cursor.substr(-1) === "("|| pre_cursor.substr(-1) === " ") && that.tooltip_on_tab ) {
132 IPython.tooltip.request(that);
132 IPython.tooltip.request(that);
133 // Prevent the event from bubbling up.
133 // Prevent the event from bubbling up.
134 event.stop();
134 event.stop();
135 // Prevent CodeMirror from handling the tab.
135 // Prevent CodeMirror from handling the tab.
136 return true;
136 return true;
137 } else {
137 } else {
138 event.stop();
138 event.stop();
139 this.completer.startCompletion();
139 this.completer.startCompletion();
140 return true;
140 return true;
141 };
141 };
142 } else {
142 } else {
143 // keypress/keyup also trigger on TAB press, and we don't want to
143 // keypress/keyup also trigger on TAB press, and we don't want to
144 // use those to disable tab completion.
144 // use those to disable tab completion.
145 return false;
145 return false;
146 };
146 };
147 return false;
147 return false;
148 };
148 };
149
149
150
150
151 // Kernel related calls.
151 // Kernel related calls.
152
152
153 CodeCell.prototype.set_kernel = function (kernel) {
153 CodeCell.prototype.set_kernel = function (kernel) {
154 this.kernel = kernel;
154 this.kernel = kernel;
155 }
155 }
156
156
157
157
158 CodeCell.prototype.execute = function () {
158 CodeCell.prototype.execute = function () {
159 this.output_area.clear_output(true, true, true);
159 this.output_area.clear_output(true, true, true);
160 this.set_input_prompt('*');
160 this.set_input_prompt('*');
161 this.element.addClass("running");
161 this.element.addClass("running");
162 var callbacks = {
162 var callbacks = {
163 'execute_reply': $.proxy(this._handle_execute_reply, this),
163 'execute_reply': $.proxy(this._handle_execute_reply, this),
164 'output': $.proxy(this.output_area.handle_output, this.output_area),
164 'output': $.proxy(this.output_area.handle_output, this.output_area),
165 'clear_output': $.proxy(this.output_area.handle_clear_output, this.output_area),
165 'clear_output': $.proxy(this.output_area.handle_clear_output, this.output_area),
166 'set_next_input': $.proxy(this._handle_set_next_input, this)
166 'set_next_input': $.proxy(this._handle_set_next_input, this)
167 };
167 };
168 var msg_id = this.kernel.execute(this.get_text(), callbacks, {silent: false});
168 var msg_id = this.kernel.execute(this.get_text(), callbacks, {silent: false});
169 };
169 };
170
170
171
171
172 CodeCell.prototype._handle_execute_reply = function (content) {
172 CodeCell.prototype._handle_execute_reply = function (content) {
173 this.set_input_prompt(content.execution_count);
173 this.set_input_prompt(content.execution_count);
174 this.element.removeClass("running");
174 this.element.removeClass("running");
175 $([IPython.events]).trigger('set_dirty.Notebook', {'value': true});
175 $([IPython.events]).trigger('set_dirty.Notebook', {'value': true});
176 }
176 }
177
177
178 CodeCell.prototype._handle_set_next_input = function (text) {
178 CodeCell.prototype._handle_set_next_input = function (text) {
179 var data = {'cell': this, 'text': text}
179 var data = {'cell': this, 'text': text}
180 $([IPython.events]).trigger('set_next_input.Notebook', data);
180 $([IPython.events]).trigger('set_next_input.Notebook', data);
181 }
181 }
182
182
183 // Basic cell manipulation.
183 // Basic cell manipulation.
184
184
185 CodeCell.prototype.select = function () {
185 CodeCell.prototype.select = function () {
186 IPython.Cell.prototype.select.apply(this);
186 IPython.Cell.prototype.select.apply(this);
187 this.code_mirror.refresh();
187 this.code_mirror.refresh();
188 this.code_mirror.focus();
188 this.code_mirror.focus();
189 this.auto_highlight();
189 this.auto_highlight();
190 // We used to need an additional refresh() after the focus, but
190 // We used to need an additional refresh() after the focus, but
191 // it appears that this has been fixed in CM. This bug would show
191 // it appears that this has been fixed in CM. This bug would show
192 // up on FF when a newly loaded markdown cell was edited.
192 // up on FF when a newly loaded markdown cell was edited.
193 };
193 };
194
194
195
195
196 CodeCell.prototype.select_all = function () {
196 CodeCell.prototype.select_all = function () {
197 var start = {line: 0, ch: 0};
197 var start = {line: 0, ch: 0};
198 var nlines = this.code_mirror.lineCount();
198 var nlines = this.code_mirror.lineCount();
199 var last_line = this.code_mirror.getLine(nlines-1);
199 var last_line = this.code_mirror.getLine(nlines-1);
200 var end = {line: nlines-1, ch: last_line.length};
200 var end = {line: nlines-1, ch: last_line.length};
201 this.code_mirror.setSelection(start, end);
201 this.code_mirror.setSelection(start, end);
202 };
202 };
203
203
204
204
205 CodeCell.prototype.collapse = function () {
205 CodeCell.prototype.collapse = function () {
206 this.collapsed = true;
206 this.collapsed = true;
207 this.output_area.collapse();
207 this.output_area.collapse();
208 };
208 };
209
209
210
210
211 CodeCell.prototype.expand = function () {
211 CodeCell.prototype.expand = function () {
212 this.collapsed = false;
212 this.collapsed = false;
213 this.output_area.expand();
213 this.output_area.expand();
214 };
214 };
215
215
216
216
217 CodeCell.prototype.toggle_output = function () {
217 CodeCell.prototype.toggle_output = function () {
218 this.collapsed = Boolean(1 - this.collapsed);
218 this.collapsed = Boolean(1 - this.collapsed);
219 this.output_area.toggle_output();
219 this.output_area.toggle_output();
220 };
220 };
221
221
222
222
223 CodeCell.prototype.toggle_output_scroll = function () {
223 CodeCell.prototype.toggle_output_scroll = function () {
224 this.output_area.toggle_scroll();
224 this.output_area.toggle_scroll();
225 };
225 };
226
226
227
227
228
229
230
231 CodeCell.input_prompt_classical = function (prompt_value, lines_number) {
232 var ns = prompt_value || "&nbsp;";
233 return 'In&nbsp;[' + ns + ']:'
234 };
235
236 CodeCell.input_prompt_continuation = function (prompt_value, lines_number) {
237 var html = [CodeCell.input_prompt_classical(prompt_value, lines_number)];
238 for(var i=1; i < lines_number; i++){html.push(['...:'])};
239 return html.join('</br>')
240 };
241
242 CodeCell.input_prompt_function = CodeCell.input_prompt_classical;
243
244
228 CodeCell.prototype.set_input_prompt = function (number) {
245 CodeCell.prototype.set_input_prompt = function (number) {
229 this.input_prompt_number = number;
246 var nline = 1
230 var ns = number || "&nbsp;";
247 if( this.code_mirror != undefined) {
231 this.element.find('div.input_prompt').html('In&nbsp;[' + ns + ']:');
248 nline = this.code_mirror.lineCount();
249 }
250 if (number){
251 this.input_prompt_number = number;
252 }
253 var prompt_html = CodeCell.input_prompt_function(this.input_prompt_number, nline);
254 this.element.find('div.input_prompt').html(prompt_html);
232 };
255 };
233
256
234
257
235 CodeCell.prototype.clear_input = function () {
258 CodeCell.prototype.clear_input = function () {
236 this.code_mirror.setValue('');
259 this.code_mirror.setValue('');
237 };
260 };
238
261
239
262
240 CodeCell.prototype.get_text = function () {
263 CodeCell.prototype.get_text = function () {
241 return this.code_mirror.getValue();
264 return this.code_mirror.getValue();
242 };
265 };
243
266
244
267
245 CodeCell.prototype.set_text = function (code) {
268 CodeCell.prototype.set_text = function (code) {
246 return this.code_mirror.setValue(code);
269 return this.code_mirror.setValue(code);
247 };
270 };
248
271
249
272
250 CodeCell.prototype.at_top = function () {
273 CodeCell.prototype.at_top = function () {
251 var cursor = this.code_mirror.getCursor();
274 var cursor = this.code_mirror.getCursor();
252 if (cursor.line === 0 && cursor.ch === 0) {
275 if (cursor.line === 0 && cursor.ch === 0) {
253 return true;
276 return true;
254 } else {
277 } else {
255 return false;
278 return false;
256 }
279 }
257 };
280 };
258
281
259
282
260 CodeCell.prototype.at_bottom = function () {
283 CodeCell.prototype.at_bottom = function () {
261 var cursor = this.code_mirror.getCursor();
284 var cursor = this.code_mirror.getCursor();
262 if (cursor.line === (this.code_mirror.lineCount()-1) && cursor.ch === this.code_mirror.getLine(cursor.line).length) {
285 if (cursor.line === (this.code_mirror.lineCount()-1) && cursor.ch === this.code_mirror.getLine(cursor.line).length) {
263 return true;
286 return true;
264 } else {
287 } else {
265 return false;
288 return false;
266 }
289 }
267 };
290 };
268
291
269
292
270 CodeCell.prototype.clear_output = function (stdout, stderr, other) {
293 CodeCell.prototype.clear_output = function (stdout, stderr, other) {
271 this.output_area.clear_output(stdout, stderr, other);
294 this.output_area.clear_output(stdout, stderr, other);
272 };
295 };
273
296
274
297
275 // JSON serialization
298 // JSON serialization
276
299
277 CodeCell.prototype.fromJSON = function (data) {
300 CodeCell.prototype.fromJSON = function (data) {
278 IPython.Cell.prototype.fromJSON.apply(this, arguments);
301 IPython.Cell.prototype.fromJSON.apply(this, arguments);
279 if (data.cell_type === 'code') {
302 if (data.cell_type === 'code') {
280 if (data.input !== undefined) {
303 if (data.input !== undefined) {
281 this.set_text(data.input);
304 this.set_text(data.input);
282 // make this value the starting point, so that we can only undo
305 // make this value the starting point, so that we can only undo
283 // to this state, instead of a blank cell
306 // to this state, instead of a blank cell
284 this.code_mirror.clearHistory();
307 this.code_mirror.clearHistory();
285 this.auto_highlight();
308 this.auto_highlight();
286 }
309 }
287 if (data.prompt_number !== undefined) {
310 if (data.prompt_number !== undefined) {
288 this.set_input_prompt(data.prompt_number);
311 this.set_input_prompt(data.prompt_number);
289 } else {
312 } else {
290 this.set_input_prompt();
313 this.set_input_prompt();
291 };
314 };
292 this.output_area.fromJSON(data.outputs);
315 this.output_area.fromJSON(data.outputs);
293 if (data.collapsed !== undefined) {
316 if (data.collapsed !== undefined) {
294 if (data.collapsed) {
317 if (data.collapsed) {
295 this.collapse();
318 this.collapse();
296 } else {
319 } else {
297 this.expand();
320 this.expand();
298 };
321 };
299 };
322 };
300 };
323 };
301 };
324 };
302
325
303
326
304 CodeCell.prototype.toJSON = function () {
327 CodeCell.prototype.toJSON = function () {
305 var data = IPython.Cell.prototype.toJSON.apply(this);
328 var data = IPython.Cell.prototype.toJSON.apply(this);
306 data.input = this.get_text();
329 data.input = this.get_text();
307 data.cell_type = 'code';
330 data.cell_type = 'code';
308 if (this.input_prompt_number) {
331 if (this.input_prompt_number) {
309 data.prompt_number = this.input_prompt_number;
332 data.prompt_number = this.input_prompt_number;
310 };
333 };
311 var outputs = this.output_area.toJSON();
334 var outputs = this.output_area.toJSON();
312 data.outputs = outputs;
335 data.outputs = outputs;
313 data.language = 'python';
336 data.language = 'python';
314 data.collapsed = this.collapsed;
337 data.collapsed = this.collapsed;
315 return data;
338 return data;
316 };
339 };
317
340
318
341
319 IPython.CodeCell = CodeCell;
342 IPython.CodeCell = CodeCell;
320
343
321 return IPython;
344 return IPython;
322 }(IPython));
345 }(IPython));
@@ -1,1305 +1,1310 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
13
14 var utils = IPython.utils;
14 var utils = IPython.utils;
15 var key = IPython.utils.keycodes;
15 var key = IPython.utils.keycodes;
16
16
17 var Notebook = function (selector) {
17 var Notebook = function (selector) {
18 this.read_only = IPython.read_only;
18 this.read_only = IPython.read_only;
19 this.element = $(selector);
19 this.element = $(selector);
20 this.element.scroll();
20 this.element.scroll();
21 this.element.data("notebook", this);
21 this.element.data("notebook", this);
22 this.next_prompt_number = 1;
22 this.next_prompt_number = 1;
23 this.kernel = null;
23 this.kernel = null;
24 this.clipboard = null;
24 this.clipboard = null;
25 this.paste_enabled = false;
25 this.paste_enabled = false;
26 this.dirty = false;
26 this.dirty = false;
27 this.metadata = {};
27 this.metadata = {};
28 // single worksheet for now
28 // single worksheet for now
29 this.worksheet_metadata = {};
29 this.worksheet_metadata = {};
30 this.control_key_active = false;
30 this.control_key_active = false;
31 this.notebook_id = null;
31 this.notebook_id = null;
32 this.notebook_name = null;
32 this.notebook_name = null;
33 this.notebook_name_blacklist_re = /[\/\\:]/;
33 this.notebook_name_blacklist_re = /[\/\\:]/;
34 this.nbformat = 3 // Increment this when changing the nbformat
34 this.nbformat = 3 // Increment this when changing the nbformat
35 this.nbformat_minor = 0 // Increment this when changing the nbformat
35 this.nbformat_minor = 0 // Increment this when changing the nbformat
36 this.style();
36 this.style();
37 this.create_elements();
37 this.create_elements();
38 this.bind_events();
38 this.bind_events();
39 };
39 };
40
40
41
41
42 Notebook.prototype.style = function () {
42 Notebook.prototype.style = function () {
43 $('div#notebook').addClass('border-box-sizing');
43 $('div#notebook').addClass('border-box-sizing');
44 };
44 };
45
45
46
46
47 Notebook.prototype.create_elements = function () {
47 Notebook.prototype.create_elements = function () {
48 // We add this end_space div to the end of the notebook div to:
48 // We add this end_space div to the end of the notebook div to:
49 // i) provide a margin between the last cell and the end of the notebook
49 // i) provide a margin between the last cell and the end of the notebook
50 // ii) to prevent the div from scrolling up when the last cell is being
50 // ii) to prevent the div from scrolling up when the last cell is being
51 // edited, but is too low on the page, which browsers will do automatically.
51 // edited, but is too low on the page, which browsers will do automatically.
52 var that = this;
52 var that = this;
53 var end_space = $('<div/>').addClass('end_space').height("30%");
53 var end_space = $('<div/>').addClass('end_space').height("30%");
54 end_space.dblclick(function (e) {
54 end_space.dblclick(function (e) {
55 if (that.read_only) return;
55 if (that.read_only) return;
56 var ncells = that.ncells();
56 var ncells = that.ncells();
57 that.insert_cell_below('code',ncells-1);
57 that.insert_cell_below('code',ncells-1);
58 });
58 });
59 this.element.append(end_space);
59 this.element.append(end_space);
60 $('div#notebook').addClass('border-box-sizing');
60 $('div#notebook').addClass('border-box-sizing');
61 };
61 };
62
62
63
63
64 Notebook.prototype.bind_events = function () {
64 Notebook.prototype.bind_events = function () {
65 var that = this;
65 var that = this;
66
66
67 $([IPython.events]).on('set_next_input.Notebook', function (event, data) {
67 $([IPython.events]).on('set_next_input.Notebook', function (event, data) {
68 var index = that.find_cell_index(data.cell);
68 var index = that.find_cell_index(data.cell);
69 var new_cell = that.insert_cell_below('code',index);
69 var new_cell = that.insert_cell_below('code',index);
70 new_cell.set_text(data.text);
70 new_cell.set_text(data.text);
71 that.dirty = true;
71 that.dirty = true;
72 });
72 });
73
73
74 $([IPython.events]).on('set_dirty.Notebook', function (event, data) {
74 $([IPython.events]).on('set_dirty.Notebook', function (event, data) {
75 that.dirty = data.value;
75 that.dirty = data.value;
76 });
76 });
77
77
78 $([IPython.events]).on('select.Cell', function (event, data) {
78 $([IPython.events]).on('select.Cell', function (event, data) {
79 var index = that.find_cell_index(data.cell);
79 var index = that.find_cell_index(data.cell);
80 that.select(index);
80 that.select(index);
81 });
81 });
82
82
83
83
84 $(document).keydown(function (event) {
84 $(document).keydown(function (event) {
85 // console.log(event);
85 // console.log(event);
86 if (that.read_only) return true;
86 if (that.read_only) return true;
87
87
88 // Save (CTRL+S) or (AppleKey+S)
88 // Save (CTRL+S) or (AppleKey+S)
89 //metaKey = applekey on mac
89 //metaKey = applekey on mac
90 if ((event.ctrlKey || event.metaKey) && event.keyCode==83) {
90 if ((event.ctrlKey || event.metaKey) && event.keyCode==83) {
91 that.save_notebook();
91 that.save_notebook();
92 event.preventDefault();
92 event.preventDefault();
93 return false;
93 return false;
94 } else if (event.which === key.ESC) {
94 } else if (event.which === key.ESC) {
95 // Intercept escape at highest level to avoid closing
95 // Intercept escape at highest level to avoid closing
96 // websocket connection with firefox
96 // websocket connection with firefox
97 event.preventDefault();
97 event.preventDefault();
98 } else if (event.which === key.SHIFT) {
98 } else if (event.which === key.SHIFT) {
99 // ignore shift keydown
99 // ignore shift keydown
100 return true;
100 return true;
101 }
101 }
102 if (event.which === key.UPARROW && !event.shiftKey) {
102 if (event.which === key.UPARROW && !event.shiftKey) {
103 var cell = that.get_selected_cell();
103 var cell = that.get_selected_cell();
104 if (cell.at_top()) {
104 if (cell.at_top()) {
105 event.preventDefault();
105 event.preventDefault();
106 that.select_prev();
106 that.select_prev();
107 };
107 };
108 } else if (event.which === key.DOWNARROW && !event.shiftKey) {
108 } else if (event.which === key.DOWNARROW && !event.shiftKey) {
109 var cell = that.get_selected_cell();
109 var cell = that.get_selected_cell();
110 if (cell.at_bottom()) {
110 if (cell.at_bottom()) {
111 event.preventDefault();
111 event.preventDefault();
112 that.select_next();
112 that.select_next();
113 };
113 };
114 } else if (event.which === key.ENTER && event.shiftKey) {
114 } else if (event.which === key.ENTER && event.shiftKey) {
115 that.execute_selected_cell();
115 that.execute_selected_cell();
116 return false;
116 return false;
117 } else if (event.which === key.ENTER && event.altKey) {
117 } else if (event.which === key.ENTER && event.altKey) {
118 // Execute code cell, and insert new in place
118 // Execute code cell, and insert new in place
119 that.execute_selected_cell();
119 that.execute_selected_cell();
120 // Only insert a new cell, if we ended up in an already populated cell
120 // Only insert a new cell, if we ended up in an already populated cell
121 if (/\S/.test(that.get_selected_cell().get_text()) == true) {
121 if (/\S/.test(that.get_selected_cell().get_text()) == true) {
122 that.insert_cell_above('code');
122 that.insert_cell_above('code');
123 }
123 }
124 return false;
124 return false;
125 } else if (event.which === key.ENTER && event.ctrlKey) {
125 } else if (event.which === key.ENTER && event.ctrlKey) {
126 that.execute_selected_cell({terminal:true});
126 that.execute_selected_cell({terminal:true});
127 return false;
127 return false;
128 } else if (event.which === 77 && event.ctrlKey && that.control_key_active == false) {
128 } else if (event.which === 77 && event.ctrlKey && that.control_key_active == false) {
129 that.control_key_active = true;
129 that.control_key_active = true;
130 return false;
130 return false;
131 } else if (event.which === 88 && that.control_key_active) {
131 } else if (event.which === 88 && that.control_key_active) {
132 // Cut selected cell = x
132 // Cut selected cell = x
133 that.cut_cell();
133 that.cut_cell();
134 that.control_key_active = false;
134 that.control_key_active = false;
135 return false;
135 return false;
136 } else if (event.which === 67 && that.control_key_active) {
136 } else if (event.which === 67 && that.control_key_active) {
137 // Copy selected cell = c
137 // Copy selected cell = c
138 that.copy_cell();
138 that.copy_cell();
139 that.control_key_active = false;
139 that.control_key_active = false;
140 return false;
140 return false;
141 } else if (event.which === 86 && that.control_key_active) {
141 } else if (event.which === 86 && that.control_key_active) {
142 // Paste selected cell = v
142 // Paste selected cell = v
143 that.paste_cell();
143 that.paste_cell();
144 that.control_key_active = false;
144 that.control_key_active = false;
145 return false;
145 return false;
146 } else if (event.which === 68 && that.control_key_active) {
146 } else if (event.which === 68 && that.control_key_active) {
147 // Delete selected cell = d
147 // Delete selected cell = d
148 that.delete_cell();
148 that.delete_cell();
149 that.control_key_active = false;
149 that.control_key_active = false;
150 return false;
150 return false;
151 } else if (event.which === 65 && that.control_key_active) {
151 } else if (event.which === 65 && that.control_key_active) {
152 // Insert code cell above selected = a
152 // Insert code cell above selected = a
153 that.insert_cell_above('code');
153 that.insert_cell_above('code');
154 that.control_key_active = false;
154 that.control_key_active = false;
155 return false;
155 return false;
156 } else if (event.which === 66 && that.control_key_active) {
156 } else if (event.which === 66 && that.control_key_active) {
157 // Insert code cell below selected = b
157 // Insert code cell below selected = b
158 that.insert_cell_below('code');
158 that.insert_cell_below('code');
159 that.control_key_active = false;
159 that.control_key_active = false;
160 return false;
160 return false;
161 } else if (event.which === 89 && that.control_key_active) {
161 } else if (event.which === 89 && that.control_key_active) {
162 // To code = y
162 // To code = y
163 that.to_code();
163 that.to_code();
164 that.control_key_active = false;
164 that.control_key_active = false;
165 return false;
165 return false;
166 } else if (event.which === 77 && that.control_key_active) {
166 } else if (event.which === 77 && that.control_key_active) {
167 // To markdown = m
167 // To markdown = m
168 that.to_markdown();
168 that.to_markdown();
169 that.control_key_active = false;
169 that.control_key_active = false;
170 return false;
170 return false;
171 } else if (event.which === 84 && that.control_key_active) {
171 } else if (event.which === 84 && that.control_key_active) {
172 // To Raw = t
172 // To Raw = t
173 that.to_raw();
173 that.to_raw();
174 that.control_key_active = false;
174 that.control_key_active = false;
175 return false;
175 return false;
176 } else if (event.which === 49 && that.control_key_active) {
176 } else if (event.which === 49 && that.control_key_active) {
177 // To Heading 1 = 1
177 // To Heading 1 = 1
178 that.to_heading(undefined, 1);
178 that.to_heading(undefined, 1);
179 that.control_key_active = false;
179 that.control_key_active = false;
180 return false;
180 return false;
181 } else if (event.which === 50 && that.control_key_active) {
181 } else if (event.which === 50 && that.control_key_active) {
182 // To Heading 2 = 2
182 // To Heading 2 = 2
183 that.to_heading(undefined, 2);
183 that.to_heading(undefined, 2);
184 that.control_key_active = false;
184 that.control_key_active = false;
185 return false;
185 return false;
186 } else if (event.which === 51 && that.control_key_active) {
186 } else if (event.which === 51 && that.control_key_active) {
187 // To Heading 3 = 3
187 // To Heading 3 = 3
188 that.to_heading(undefined, 3);
188 that.to_heading(undefined, 3);
189 that.control_key_active = false;
189 that.control_key_active = false;
190 return false;
190 return false;
191 } else if (event.which === 52 && that.control_key_active) {
191 } else if (event.which === 52 && that.control_key_active) {
192 // To Heading 4 = 4
192 // To Heading 4 = 4
193 that.to_heading(undefined, 4);
193 that.to_heading(undefined, 4);
194 that.control_key_active = false;
194 that.control_key_active = false;
195 return false;
195 return false;
196 } else if (event.which === 53 && that.control_key_active) {
196 } else if (event.which === 53 && that.control_key_active) {
197 // To Heading 5 = 5
197 // To Heading 5 = 5
198 that.to_heading(undefined, 5);
198 that.to_heading(undefined, 5);
199 that.control_key_active = false;
199 that.control_key_active = false;
200 return false;
200 return false;
201 } else if (event.which === 54 && that.control_key_active) {
201 } else if (event.which === 54 && that.control_key_active) {
202 // To Heading 6 = 6
202 // To Heading 6 = 6
203 that.to_heading(undefined, 6);
203 that.to_heading(undefined, 6);
204 that.control_key_active = false;
204 that.control_key_active = false;
205 return false;
205 return false;
206 } else if (event.which === 79 && that.control_key_active) {
206 } else if (event.which === 79 && that.control_key_active) {
207 // Toggle output = o
207 // Toggle output = o
208 if (event.shiftKey){
208 if (event.shiftKey){
209 that.toggle_output_scroll();
209 that.toggle_output_scroll();
210 } else {
210 } else {
211 that.toggle_output();
211 that.toggle_output();
212 }
212 }
213 that.control_key_active = false;
213 that.control_key_active = false;
214 return false;
214 return false;
215 } else if (event.which === 83 && that.control_key_active) {
215 } else if (event.which === 83 && that.control_key_active) {
216 // Save notebook = s
216 // Save notebook = s
217 that.save_notebook();
217 that.save_notebook();
218 that.control_key_active = false;
218 that.control_key_active = false;
219 return false;
219 return false;
220 } else if (event.which === 74 && that.control_key_active) {
220 } else if (event.which === 74 && that.control_key_active) {
221 // Move cell down = j
221 // Move cell down = j
222 that.move_cell_down();
222 that.move_cell_down();
223 that.control_key_active = false;
223 that.control_key_active = false;
224 return false;
224 return false;
225 } else if (event.which === 75 && that.control_key_active) {
225 } else if (event.which === 75 && that.control_key_active) {
226 // Move cell up = k
226 // Move cell up = k
227 that.move_cell_up();
227 that.move_cell_up();
228 that.control_key_active = false;
228 that.control_key_active = false;
229 return false;
229 return false;
230 } else if (event.which === 80 && that.control_key_active) {
230 } else if (event.which === 80 && that.control_key_active) {
231 // Select previous = p
231 // Select previous = p
232 that.select_prev();
232 that.select_prev();
233 that.control_key_active = false;
233 that.control_key_active = false;
234 return false;
234 return false;
235 } else if (event.which === 78 && that.control_key_active) {
235 } else if (event.which === 78 && that.control_key_active) {
236 // Select next = n
236 // Select next = n
237 that.select_next();
237 that.select_next();
238 that.control_key_active = false;
238 that.control_key_active = false;
239 return false;
239 return false;
240 } else if (event.which === 76 && that.control_key_active) {
240 } else if (event.which === 76 && that.control_key_active) {
241 // Toggle line numbers = l
241 // Toggle line numbers = l
242 that.cell_toggle_line_numbers();
242 that.cell_toggle_line_numbers();
243 that.control_key_active = false;
243 that.control_key_active = false;
244 return false;
244 return false;
245 } else if (event.which === 73 && that.control_key_active) {
245 } else if (event.which === 73 && that.control_key_active) {
246 // Interrupt kernel = i
246 // Interrupt kernel = i
247 that.kernel.interrupt();
247 that.kernel.interrupt();
248 that.control_key_active = false;
248 that.control_key_active = false;
249 return false;
249 return false;
250 } else if (event.which === 190 && that.control_key_active) {
250 } else if (event.which === 190 && that.control_key_active) {
251 // Restart kernel = . # matches qt console
251 // Restart kernel = . # matches qt console
252 that.restart_kernel();
252 that.restart_kernel();
253 that.control_key_active = false;
253 that.control_key_active = false;
254 return false;
254 return false;
255 } else if (event.which === 72 && that.control_key_active) {
255 } else if (event.which === 72 && that.control_key_active) {
256 // Show keyboard shortcuts = h
256 // Show keyboard shortcuts = h
257 IPython.quick_help.show_keyboard_shortcuts();
257 IPython.quick_help.show_keyboard_shortcuts();
258 that.control_key_active = false;
258 that.control_key_active = false;
259 return false;
259 return false;
260 } else if (that.control_key_active) {
260 } else if (that.control_key_active) {
261 that.control_key_active = false;
261 that.control_key_active = false;
262 return true;
262 return true;
263 };
263 };
264 return true;
264 return true;
265 });
265 });
266
266
267 var collapse_time = function(time){
267 var collapse_time = function(time){
268 var app_height = $('div#main_app').height(); // content height
268 var app_height = $('div#main_app').height(); // content height
269 var splitter_height = $('div#pager_splitter').outerHeight(true);
269 var splitter_height = $('div#pager_splitter').outerHeight(true);
270 var new_height = app_height - splitter_height;
270 var new_height = app_height - splitter_height;
271 that.element.animate({height : new_height + 'px'}, time);
271 that.element.animate({height : new_height + 'px'}, time);
272 }
272 }
273
273
274 this.element.bind('collapse_pager', function (event,extrap) {
274 this.element.bind('collapse_pager', function (event,extrap) {
275 time = (extrap != undefined) ? ((extrap.duration != undefined ) ? extrap.duration : 'fast') : 'fast';
275 time = (extrap != undefined) ? ((extrap.duration != undefined ) ? extrap.duration : 'fast') : 'fast';
276 collapse_time(time);
276 collapse_time(time);
277 });
277 });
278
278
279 var expand_time = function(time) {
279 var expand_time = function(time) {
280 var app_height = $('div#main_app').height(); // content height
280 var app_height = $('div#main_app').height(); // content height
281 var splitter_height = $('div#pager_splitter').outerHeight(true);
281 var splitter_height = $('div#pager_splitter').outerHeight(true);
282 var pager_height = $('div#pager').outerHeight(true);
282 var pager_height = $('div#pager').outerHeight(true);
283 var new_height = app_height - pager_height - splitter_height;
283 var new_height = app_height - pager_height - splitter_height;
284 that.element.animate({height : new_height + 'px'}, time);
284 that.element.animate({height : new_height + 'px'}, time);
285 }
285 }
286
286
287 this.element.bind('expand_pager', function (event, extrap) {
287 this.element.bind('expand_pager', function (event, extrap) {
288 time = (extrap != undefined) ? ((extrap.duration != undefined ) ? extrap.duration : 'fast') : 'fast';
288 time = (extrap != undefined) ? ((extrap.duration != undefined ) ? extrap.duration : 'fast') : 'fast';
289 expand_time(time);
289 expand_time(time);
290 });
290 });
291
291
292 $(window).bind('beforeunload', function () {
292 $(window).bind('beforeunload', function () {
293 // TODO: Make killing the kernel configurable.
293 // TODO: Make killing the kernel configurable.
294 var kill_kernel = false;
294 var kill_kernel = false;
295 if (kill_kernel) {
295 if (kill_kernel) {
296 that.kernel.kill();
296 that.kernel.kill();
297 }
297 }
298 if (that.dirty && ! that.read_only) {
298 if (that.dirty && ! that.read_only) {
299 return "You have unsaved changes that will be lost if you leave this page.";
299 return "You have unsaved changes that will be lost if you leave this page.";
300 };
300 };
301 // Null is the *only* return value that will make the browser not
301 // Null is the *only* return value that will make the browser not
302 // pop up the "don't leave" dialog.
302 // pop up the "don't leave" dialog.
303 return null;
303 return null;
304 });
304 });
305 };
305 };
306
306
307 Notebook.prototype.scroll_to_cell = function (cell_number, time) {
307 Notebook.prototype.scroll_to_cell = function (cell_number, time) {
308 var cells = this.get_cells();
308 var cells = this.get_cells();
309 var time = time || 0;
309 var time = time || 0;
310 cell_number = Math.min(cells.length-1,cell_number);
310 cell_number = Math.min(cells.length-1,cell_number);
311 cell_number = Math.max(0 ,cell_number);
311 cell_number = Math.max(0 ,cell_number);
312 scroll_value = cells[cell_number].element.position().top-cells[0].element.position().top ;
312 scroll_value = cells[cell_number].element.position().top-cells[0].element.position().top ;
313 this.element.animate({scrollTop:scroll_value}, time);
313 this.element.animate({scrollTop:scroll_value}, time);
314 return scroll_value;
314 return scroll_value;
315 };
315 };
316
316
317
317
318 Notebook.prototype.scroll_to_bottom = function () {
318 Notebook.prototype.scroll_to_bottom = function () {
319 this.element.animate({scrollTop:this.element.get(0).scrollHeight}, 0);
319 this.element.animate({scrollTop:this.element.get(0).scrollHeight}, 0);
320 };
320 };
321
321
322
322
323 Notebook.prototype.scroll_to_top = function () {
323 Notebook.prototype.scroll_to_top = function () {
324 this.element.animate({scrollTop:0}, 0);
324 this.element.animate({scrollTop:0}, 0);
325 };
325 };
326
326
327
327
328 // Cell indexing, retrieval, etc.
328 // Cell indexing, retrieval, etc.
329
329
330 Notebook.prototype.get_cell_elements = function () {
330 Notebook.prototype.get_cell_elements = function () {
331 return this.element.children("div.cell");
331 return this.element.children("div.cell");
332 };
332 };
333
333
334
334
335 Notebook.prototype.get_cell_element = function (index) {
335 Notebook.prototype.get_cell_element = function (index) {
336 var result = null;
336 var result = null;
337 var e = this.get_cell_elements().eq(index);
337 var e = this.get_cell_elements().eq(index);
338 if (e.length !== 0) {
338 if (e.length !== 0) {
339 result = e;
339 result = e;
340 }
340 }
341 return result;
341 return result;
342 };
342 };
343
343
344
344
345 Notebook.prototype.ncells = function (cell) {
345 Notebook.prototype.ncells = function (cell) {
346 return this.get_cell_elements().length;
346 return this.get_cell_elements().length;
347 };
347 };
348
348
349
349
350 // TODO: we are often calling cells as cells()[i], which we should optimize
350 // TODO: we are often calling cells as cells()[i], which we should optimize
351 // to cells(i) or a new method.
351 // to cells(i) or a new method.
352 Notebook.prototype.get_cells = function () {
352 Notebook.prototype.get_cells = function () {
353 return this.get_cell_elements().toArray().map(function (e) {
353 return this.get_cell_elements().toArray().map(function (e) {
354 return $(e).data("cell");
354 return $(e).data("cell");
355 });
355 });
356 };
356 };
357
357
358
358
359 Notebook.prototype.get_cell = function (index) {
359 Notebook.prototype.get_cell = function (index) {
360 var result = null;
360 var result = null;
361 var ce = this.get_cell_element(index);
361 var ce = this.get_cell_element(index);
362 if (ce !== null) {
362 if (ce !== null) {
363 result = ce.data('cell');
363 result = ce.data('cell');
364 }
364 }
365 return result;
365 return result;
366 }
366 }
367
367
368
368
369 Notebook.prototype.get_next_cell = function (cell) {
369 Notebook.prototype.get_next_cell = function (cell) {
370 var result = null;
370 var result = null;
371 var index = this.find_cell_index(cell);
371 var index = this.find_cell_index(cell);
372 if (index !== null && index < this.ncells()) {
372 if (index !== null && index < this.ncells()) {
373 result = this.get_cell(index+1);
373 result = this.get_cell(index+1);
374 }
374 }
375 return result;
375 return result;
376 }
376 }
377
377
378
378
379 Notebook.prototype.get_prev_cell = function (cell) {
379 Notebook.prototype.get_prev_cell = function (cell) {
380 var result = null;
380 var result = null;
381 var index = this.find_cell_index(cell);
381 var index = this.find_cell_index(cell);
382 if (index !== null && index > 1) {
382 if (index !== null && index > 1) {
383 result = this.get_cell(index-1);
383 result = this.get_cell(index-1);
384 }
384 }
385 return result;
385 return result;
386 }
386 }
387
387
388 Notebook.prototype.find_cell_index = function (cell) {
388 Notebook.prototype.find_cell_index = function (cell) {
389 var result = null;
389 var result = null;
390 this.get_cell_elements().filter(function (index) {
390 this.get_cell_elements().filter(function (index) {
391 if ($(this).data("cell") === cell) {
391 if ($(this).data("cell") === cell) {
392 result = index;
392 result = index;
393 };
393 };
394 });
394 });
395 return result;
395 return result;
396 };
396 };
397
397
398
398
399 Notebook.prototype.index_or_selected = function (index) {
399 Notebook.prototype.index_or_selected = function (index) {
400 var i;
400 var i;
401 if (index === undefined || index === null) {
401 if (index === undefined || index === null) {
402 i = this.get_selected_index();
402 i = this.get_selected_index();
403 if (i === null) {
403 if (i === null) {
404 i = 0;
404 i = 0;
405 }
405 }
406 } else {
406 } else {
407 i = index;
407 i = index;
408 }
408 }
409 return i;
409 return i;
410 };
410 };
411
411
412
412
413 Notebook.prototype.get_selected_cell = function () {
413 Notebook.prototype.get_selected_cell = function () {
414 var index = this.get_selected_index();
414 var index = this.get_selected_index();
415 return this.get_cell(index);
415 return this.get_cell(index);
416 };
416 };
417
417
418
418
419 Notebook.prototype.is_valid_cell_index = function (index) {
419 Notebook.prototype.is_valid_cell_index = function (index) {
420 if (index !== null && index >= 0 && index < this.ncells()) {
420 if (index !== null && index >= 0 && index < this.ncells()) {
421 return true;
421 return true;
422 } else {
422 } else {
423 return false;
423 return false;
424 };
424 };
425 }
425 }
426
426
427 Notebook.prototype.get_selected_index = function () {
427 Notebook.prototype.get_selected_index = function () {
428 var result = null;
428 var result = null;
429 this.get_cell_elements().filter(function (index) {
429 this.get_cell_elements().filter(function (index) {
430 if ($(this).data("cell").selected === true) {
430 if ($(this).data("cell").selected === true) {
431 result = index;
431 result = index;
432 };
432 };
433 });
433 });
434 return result;
434 return result;
435 };
435 };
436
436
437
437
438 // Cell selection.
438 // Cell selection.
439
439
440 Notebook.prototype.select = function (index) {
440 Notebook.prototype.select = function (index) {
441 if (index !== undefined && index >= 0 && index < this.ncells()) {
441 if (index !== undefined && index >= 0 && index < this.ncells()) {
442 sindex = this.get_selected_index()
442 sindex = this.get_selected_index()
443 if (sindex !== null && index !== sindex) {
443 if (sindex !== null && index !== sindex) {
444 this.get_cell(sindex).unselect();
444 this.get_cell(sindex).unselect();
445 };
445 };
446 var cell = this.get_cell(index)
446 var cell = this.get_cell(index)
447 cell.select();
447 cell.select();
448 if (cell.cell_type === 'heading') {
448 if (cell.cell_type === 'heading') {
449 $([IPython.events]).trigger('selected_cell_type_changed.Notebook',
449 $([IPython.events]).trigger('selected_cell_type_changed.Notebook',
450 {'cell_type':cell.cell_type,level:cell.level}
450 {'cell_type':cell.cell_type,level:cell.level}
451 );
451 );
452 } else {
452 } else {
453 $([IPython.events]).trigger('selected_cell_type_changed.Notebook',
453 $([IPython.events]).trigger('selected_cell_type_changed.Notebook',
454 {'cell_type':cell.cell_type}
454 {'cell_type':cell.cell_type}
455 );
455 );
456 };
456 };
457 };
457 };
458 return this;
458 return this;
459 };
459 };
460
460
461
461
462 Notebook.prototype.select_next = function () {
462 Notebook.prototype.select_next = function () {
463 var index = this.get_selected_index();
463 var index = this.get_selected_index();
464 if (index !== null && index >= 0 && (index+1) < this.ncells()) {
464 if (index !== null && index >= 0 && (index+1) < this.ncells()) {
465 this.select(index+1);
465 this.select(index+1);
466 };
466 };
467 return this;
467 return this;
468 };
468 };
469
469
470
470
471 Notebook.prototype.select_prev = function () {
471 Notebook.prototype.select_prev = function () {
472 var index = this.get_selected_index();
472 var index = this.get_selected_index();
473 if (index !== null && index >= 0 && (index-1) < this.ncells()) {
473 if (index !== null && index >= 0 && (index-1) < this.ncells()) {
474 this.select(index-1);
474 this.select(index-1);
475 };
475 };
476 return this;
476 return this;
477 };
477 };
478
478
479
479
480 // Cell movement
480 // Cell movement
481
481
482 Notebook.prototype.move_cell_up = function (index) {
482 Notebook.prototype.move_cell_up = function (index) {
483 var i = this.index_or_selected();
483 var i = this.index_or_selected();
484 if (i !== null && i < this.ncells() && i > 0) {
484 if (i !== null && i < this.ncells() && i > 0) {
485 var pivot = this.get_cell_element(i-1);
485 var pivot = this.get_cell_element(i-1);
486 var tomove = this.get_cell_element(i);
486 var tomove = this.get_cell_element(i);
487 if (pivot !== null && tomove !== null) {
487 if (pivot !== null && tomove !== null) {
488 tomove.detach();
488 tomove.detach();
489 pivot.before(tomove);
489 pivot.before(tomove);
490 this.select(i-1);
490 this.select(i-1);
491 };
491 };
492 };
492 };
493 this.dirty = true;
493 this.dirty = true;
494 return this;
494 return this;
495 };
495 };
496
496
497
497
498 Notebook.prototype.move_cell_down = function (index) {
498 Notebook.prototype.move_cell_down = function (index) {
499 var i = this.index_or_selected();
499 var i = this.index_or_selected();
500 if (i !== null && i < (this.ncells()-1) && i >= 0) {
500 if (i !== null && i < (this.ncells()-1) && i >= 0) {
501 var pivot = this.get_cell_element(i+1);
501 var pivot = this.get_cell_element(i+1);
502 var tomove = this.get_cell_element(i);
502 var tomove = this.get_cell_element(i);
503 if (pivot !== null && tomove !== null) {
503 if (pivot !== null && tomove !== null) {
504 tomove.detach();
504 tomove.detach();
505 pivot.after(tomove);
505 pivot.after(tomove);
506 this.select(i+1);
506 this.select(i+1);
507 };
507 };
508 };
508 };
509 this.dirty = true;
509 this.dirty = true;
510 return this;
510 return this;
511 };
511 };
512
512
513
513
514 Notebook.prototype.sort_cells = function () {
514 Notebook.prototype.sort_cells = function () {
515 // This is not working right now. Calling this will actually crash
515 // This is not working right now. Calling this will actually crash
516 // the browser. I think there is an infinite loop in here...
516 // the browser. I think there is an infinite loop in here...
517 var ncells = this.ncells();
517 var ncells = this.ncells();
518 var sindex = this.get_selected_index();
518 var sindex = this.get_selected_index();
519 var swapped;
519 var swapped;
520 do {
520 do {
521 swapped = false;
521 swapped = false;
522 for (var i=1; i<ncells; i++) {
522 for (var i=1; i<ncells; i++) {
523 current = this.get_cell(i);
523 current = this.get_cell(i);
524 previous = this.get_cell(i-1);
524 previous = this.get_cell(i-1);
525 if (previous.input_prompt_number > current.input_prompt_number) {
525 if (previous.input_prompt_number > current.input_prompt_number) {
526 this.move_cell_up(i);
526 this.move_cell_up(i);
527 swapped = true;
527 swapped = true;
528 };
528 };
529 };
529 };
530 } while (swapped);
530 } while (swapped);
531 this.select(sindex);
531 this.select(sindex);
532 return this;
532 return this;
533 };
533 };
534
534
535 // Insertion, deletion.
535 // Insertion, deletion.
536
536
537 Notebook.prototype.delete_cell = function (index) {
537 Notebook.prototype.delete_cell = function (index) {
538 var i = this.index_or_selected(index);
538 var i = this.index_or_selected(index);
539 if (this.is_valid_cell_index(i)) {
539 if (this.is_valid_cell_index(i)) {
540 var ce = this.get_cell_element(i);
540 var ce = this.get_cell_element(i);
541 ce.remove();
541 ce.remove();
542 if (i === (this.ncells())) {
542 if (i === (this.ncells())) {
543 this.select(i-1);
543 this.select(i-1);
544 } else {
544 } else {
545 this.select(i);
545 this.select(i);
546 };
546 };
547 this.dirty = true;
547 this.dirty = true;
548 };
548 };
549 return this;
549 return this;
550 };
550 };
551
551
552
552
553 Notebook.prototype.insert_cell_at_bottom = function (type){
554 var len = this.ncells();
555 return this.insert_cell_below(type,len-1);
556 }
557
553 Notebook.prototype.insert_cell_below = function (type, index) {
558 Notebook.prototype.insert_cell_below = function (type, index) {
554 // type = ('code','html','markdown')
559 // type = ('code','html','markdown')
555 // index = cell index or undefined to insert below selected
560 // index = cell index or undefined to insert below selected
556 index = this.index_or_selected(index);
561 index = this.index_or_selected(index);
557 var cell = null;
562 var cell = null;
558 if (this.ncells() === 0 || this.is_valid_cell_index(index)) {
563 if (this.ncells() === 0 || this.is_valid_cell_index(index)) {
559 if (type === 'code') {
564 if (type === 'code') {
560 cell = new IPython.CodeCell(this.kernel);
565 cell = new IPython.CodeCell(this.kernel);
561 cell.set_input_prompt();
566 cell.set_input_prompt();
562 } else if (type === 'markdown') {
567 } else if (type === 'markdown') {
563 cell = new IPython.MarkdownCell();
568 cell = new IPython.MarkdownCell();
564 } else if (type === 'html') {
569 } else if (type === 'html') {
565 cell = new IPython.HTMLCell();
570 cell = new IPython.HTMLCell();
566 } else if (type === 'raw') {
571 } else if (type === 'raw') {
567 cell = new IPython.RawCell();
572 cell = new IPython.RawCell();
568 } else if (type === 'heading') {
573 } else if (type === 'heading') {
569 cell = new IPython.HeadingCell();
574 cell = new IPython.HeadingCell();
570 };
575 };
571 if (cell !== null) {
576 if (cell !== null) {
572 if (this.ncells() === 0) {
577 if (this.ncells() === 0) {
573 this.element.find('div.end_space').before(cell.element);
578 this.element.find('div.end_space').before(cell.element);
574 } else if (this.is_valid_cell_index(index)) {
579 } else if (this.is_valid_cell_index(index)) {
575 this.get_cell_element(index).after(cell.element);
580 this.get_cell_element(index).after(cell.element);
576 };
581 };
577 cell.render();
582 cell.render();
578 this.select(this.find_cell_index(cell));
583 this.select(this.find_cell_index(cell));
579 this.dirty = true;
584 this.dirty = true;
580 return cell;
585 return cell;
581 };
586 };
582 };
587 };
583 return cell;
588 return cell;
584 };
589 };
585
590
586
591
587 Notebook.prototype.insert_cell_above = function (type, index) {
592 Notebook.prototype.insert_cell_above = function (type, index) {
588 // type = ('code','html','markdown')
593 // type = ('code','html','markdown')
589 // index = cell index or undefined to insert above selected
594 // index = cell index or undefined to insert above selected
590 index = this.index_or_selected(index);
595 index = this.index_or_selected(index);
591 var cell = null;
596 var cell = null;
592 if (this.ncells() === 0 || this.is_valid_cell_index(index)) {
597 if (this.ncells() === 0 || this.is_valid_cell_index(index)) {
593 if (type === 'code') {
598 if (type === 'code') {
594 cell = new IPython.CodeCell(this.kernel);
599 cell = new IPython.CodeCell(this.kernel);
595 cell.set_input_prompt();
600 cell.set_input_prompt();
596 } else if (type === 'markdown') {
601 } else if (type === 'markdown') {
597 cell = new IPython.MarkdownCell();
602 cell = new IPython.MarkdownCell();
598 } else if (type === 'html') {
603 } else if (type === 'html') {
599 cell = new IPython.HTMLCell();
604 cell = new IPython.HTMLCell();
600 } else if (type === 'raw') {
605 } else if (type === 'raw') {
601 cell = new IPython.RawCell();
606 cell = new IPython.RawCell();
602 } else if (type === 'heading') {
607 } else if (type === 'heading') {
603 cell = new IPython.HeadingCell();
608 cell = new IPython.HeadingCell();
604 };
609 };
605 if (cell !== null) {
610 if (cell !== null) {
606 if (this.ncells() === 0) {
611 if (this.ncells() === 0) {
607 this.element.find('div.end_space').before(cell.element);
612 this.element.find('div.end_space').before(cell.element);
608 } else if (this.is_valid_cell_index(index)) {
613 } else if (this.is_valid_cell_index(index)) {
609 this.get_cell_element(index).before(cell.element);
614 this.get_cell_element(index).before(cell.element);
610 };
615 };
611 cell.render();
616 cell.render();
612 this.select(this.find_cell_index(cell));
617 this.select(this.find_cell_index(cell));
613 this.dirty = true;
618 this.dirty = true;
614 return cell;
619 return cell;
615 };
620 };
616 };
621 };
617 return cell;
622 return cell;
618 };
623 };
619
624
620
625
621 Notebook.prototype.to_code = function (index) {
626 Notebook.prototype.to_code = function (index) {
622 var i = this.index_or_selected(index);
627 var i = this.index_or_selected(index);
623 if (this.is_valid_cell_index(i)) {
628 if (this.is_valid_cell_index(i)) {
624 var source_element = this.get_cell_element(i);
629 var source_element = this.get_cell_element(i);
625 var source_cell = source_element.data("cell");
630 var source_cell = source_element.data("cell");
626 if (!(source_cell instanceof IPython.CodeCell)) {
631 if (!(source_cell instanceof IPython.CodeCell)) {
627 target_cell = this.insert_cell_below('code',i);
632 target_cell = this.insert_cell_below('code',i);
628 var text = source_cell.get_text();
633 var text = source_cell.get_text();
629 if (text === source_cell.placeholder) {
634 if (text === source_cell.placeholder) {
630 text = '';
635 text = '';
631 }
636 }
632 target_cell.set_text(text);
637 target_cell.set_text(text);
633 // make this value the starting point, so that we can only undo
638 // make this value the starting point, so that we can only undo
634 // to this state, instead of a blank cell
639 // to this state, instead of a blank cell
635 target_cell.code_mirror.clearHistory();
640 target_cell.code_mirror.clearHistory();
636 source_element.remove();
641 source_element.remove();
637 this.dirty = true;
642 this.dirty = true;
638 };
643 };
639 };
644 };
640 };
645 };
641
646
642
647
643 Notebook.prototype.to_markdown = function (index) {
648 Notebook.prototype.to_markdown = function (index) {
644 var i = this.index_or_selected(index);
649 var i = this.index_or_selected(index);
645 if (this.is_valid_cell_index(i)) {
650 if (this.is_valid_cell_index(i)) {
646 var source_element = this.get_cell_element(i);
651 var source_element = this.get_cell_element(i);
647 var source_cell = source_element.data("cell");
652 var source_cell = source_element.data("cell");
648 if (!(source_cell instanceof IPython.MarkdownCell)) {
653 if (!(source_cell instanceof IPython.MarkdownCell)) {
649 target_cell = this.insert_cell_below('markdown',i);
654 target_cell = this.insert_cell_below('markdown',i);
650 var text = source_cell.get_text();
655 var text = source_cell.get_text();
651 if (text === source_cell.placeholder) {
656 if (text === source_cell.placeholder) {
652 text = '';
657 text = '';
653 };
658 };
654 // The edit must come before the set_text.
659 // The edit must come before the set_text.
655 target_cell.edit();
660 target_cell.edit();
656 target_cell.set_text(text);
661 target_cell.set_text(text);
657 // make this value the starting point, so that we can only undo
662 // make this value the starting point, so that we can only undo
658 // to this state, instead of a blank cell
663 // to this state, instead of a blank cell
659 target_cell.code_mirror.clearHistory();
664 target_cell.code_mirror.clearHistory();
660 source_element.remove();
665 source_element.remove();
661 this.dirty = true;
666 this.dirty = true;
662 };
667 };
663 };
668 };
664 };
669 };
665
670
666
671
667 Notebook.prototype.to_html = function (index) {
672 Notebook.prototype.to_html = function (index) {
668 var i = this.index_or_selected(index);
673 var i = this.index_or_selected(index);
669 if (this.is_valid_cell_index(i)) {
674 if (this.is_valid_cell_index(i)) {
670 var source_element = this.get_cell_element(i);
675 var source_element = this.get_cell_element(i);
671 var source_cell = source_element.data("cell");
676 var source_cell = source_element.data("cell");
672 var target_cell = null;
677 var target_cell = null;
673 if (!(source_cell instanceof IPython.HTMLCell)) {
678 if (!(source_cell instanceof IPython.HTMLCell)) {
674 target_cell = this.insert_cell_below('html',i);
679 target_cell = this.insert_cell_below('html',i);
675 var text = source_cell.get_text();
680 var text = source_cell.get_text();
676 if (text === source_cell.placeholder) {
681 if (text === source_cell.placeholder) {
677 text = '';
682 text = '';
678 };
683 };
679 // The edit must come before the set_text.
684 // The edit must come before the set_text.
680 target_cell.edit();
685 target_cell.edit();
681 target_cell.set_text(text);
686 target_cell.set_text(text);
682 // make this value the starting point, so that we can only undo
687 // make this value the starting point, so that we can only undo
683 // to this state, instead of a blank cell
688 // to this state, instead of a blank cell
684 target_cell.code_mirror.clearHistory();
689 target_cell.code_mirror.clearHistory();
685 source_element.remove();
690 source_element.remove();
686 this.dirty = true;
691 this.dirty = true;
687 };
692 };
688 };
693 };
689 };
694 };
690
695
691
696
692 Notebook.prototype.to_raw = function (index) {
697 Notebook.prototype.to_raw = function (index) {
693 var i = this.index_or_selected(index);
698 var i = this.index_or_selected(index);
694 if (this.is_valid_cell_index(i)) {
699 if (this.is_valid_cell_index(i)) {
695 var source_element = this.get_cell_element(i);
700 var source_element = this.get_cell_element(i);
696 var source_cell = source_element.data("cell");
701 var source_cell = source_element.data("cell");
697 var target_cell = null;
702 var target_cell = null;
698 if (!(source_cell instanceof IPython.RawCell)) {
703 if (!(source_cell instanceof IPython.RawCell)) {
699 target_cell = this.insert_cell_below('raw',i);
704 target_cell = this.insert_cell_below('raw',i);
700 var text = source_cell.get_text();
705 var text = source_cell.get_text();
701 if (text === source_cell.placeholder) {
706 if (text === source_cell.placeholder) {
702 text = '';
707 text = '';
703 };
708 };
704 // The edit must come before the set_text.
709 // The edit must come before the set_text.
705 target_cell.edit();
710 target_cell.edit();
706 target_cell.set_text(text);
711 target_cell.set_text(text);
707 // make this value the starting point, so that we can only undo
712 // make this value the starting point, so that we can only undo
708 // to this state, instead of a blank cell
713 // to this state, instead of a blank cell
709 target_cell.code_mirror.clearHistory();
714 target_cell.code_mirror.clearHistory();
710 source_element.remove();
715 source_element.remove();
711 this.dirty = true;
716 this.dirty = true;
712 };
717 };
713 };
718 };
714 };
719 };
715
720
716
721
717 Notebook.prototype.to_heading = function (index, level) {
722 Notebook.prototype.to_heading = function (index, level) {
718 level = level || 1;
723 level = level || 1;
719 var i = this.index_or_selected(index);
724 var i = this.index_or_selected(index);
720 if (this.is_valid_cell_index(i)) {
725 if (this.is_valid_cell_index(i)) {
721 var source_element = this.get_cell_element(i);
726 var source_element = this.get_cell_element(i);
722 var source_cell = source_element.data("cell");
727 var source_cell = source_element.data("cell");
723 var target_cell = null;
728 var target_cell = null;
724 if (source_cell instanceof IPython.HeadingCell) {
729 if (source_cell instanceof IPython.HeadingCell) {
725 source_cell.set_level(level);
730 source_cell.set_level(level);
726 } else {
731 } else {
727 target_cell = this.insert_cell_below('heading',i);
732 target_cell = this.insert_cell_below('heading',i);
728 var text = source_cell.get_text();
733 var text = source_cell.get_text();
729 if (text === source_cell.placeholder) {
734 if (text === source_cell.placeholder) {
730 text = '';
735 text = '';
731 };
736 };
732 // The edit must come before the set_text.
737 // The edit must come before the set_text.
733 target_cell.set_level(level);
738 target_cell.set_level(level);
734 target_cell.edit();
739 target_cell.edit();
735 target_cell.set_text(text);
740 target_cell.set_text(text);
736 // make this value the starting point, so that we can only undo
741 // make this value the starting point, so that we can only undo
737 // to this state, instead of a blank cell
742 // to this state, instead of a blank cell
738 target_cell.code_mirror.clearHistory();
743 target_cell.code_mirror.clearHistory();
739 source_element.remove();
744 source_element.remove();
740 this.dirty = true;
745 this.dirty = true;
741 };
746 };
742 $([IPython.events]).trigger('selected_cell_type_changed.Notebook',
747 $([IPython.events]).trigger('selected_cell_type_changed.Notebook',
743 {'cell_type':'heading',level:level}
748 {'cell_type':'heading',level:level}
744 );
749 );
745 };
750 };
746 };
751 };
747
752
748
753
749 // Cut/Copy/Paste
754 // Cut/Copy/Paste
750
755
751 Notebook.prototype.enable_paste = function () {
756 Notebook.prototype.enable_paste = function () {
752 var that = this;
757 var that = this;
753 if (!this.paste_enabled) {
758 if (!this.paste_enabled) {
754 $('#paste_cell').removeClass('ui-state-disabled')
759 $('#paste_cell').removeClass('ui-state-disabled')
755 .on('click', function () {that.paste_cell();});
760 .on('click', function () {that.paste_cell();});
756 $('#paste_cell_above').removeClass('ui-state-disabled')
761 $('#paste_cell_above').removeClass('ui-state-disabled')
757 .on('click', function () {that.paste_cell_above();});
762 .on('click', function () {that.paste_cell_above();});
758 $('#paste_cell_below').removeClass('ui-state-disabled')
763 $('#paste_cell_below').removeClass('ui-state-disabled')
759 .on('click', function () {that.paste_cell_below();});
764 .on('click', function () {that.paste_cell_below();});
760 this.paste_enabled = true;
765 this.paste_enabled = true;
761 };
766 };
762 };
767 };
763
768
764
769
765 Notebook.prototype.disable_paste = function () {
770 Notebook.prototype.disable_paste = function () {
766 if (this.paste_enabled) {
771 if (this.paste_enabled) {
767 $('#paste_cell').addClass('ui-state-disabled').off('click');
772 $('#paste_cell').addClass('ui-state-disabled').off('click');
768 $('#paste_cell_above').addClass('ui-state-disabled').off('click');
773 $('#paste_cell_above').addClass('ui-state-disabled').off('click');
769 $('#paste_cell_below').addClass('ui-state-disabled').off('click');
774 $('#paste_cell_below').addClass('ui-state-disabled').off('click');
770 this.paste_enabled = false;
775 this.paste_enabled = false;
771 };
776 };
772 };
777 };
773
778
774
779
775 Notebook.prototype.cut_cell = function () {
780 Notebook.prototype.cut_cell = function () {
776 this.copy_cell();
781 this.copy_cell();
777 this.delete_cell();
782 this.delete_cell();
778 }
783 }
779
784
780 Notebook.prototype.copy_cell = function () {
785 Notebook.prototype.copy_cell = function () {
781 var cell = this.get_selected_cell();
786 var cell = this.get_selected_cell();
782 this.clipboard = cell.toJSON();
787 this.clipboard = cell.toJSON();
783 this.enable_paste();
788 this.enable_paste();
784 };
789 };
785
790
786
791
787 Notebook.prototype.paste_cell = function () {
792 Notebook.prototype.paste_cell = function () {
788 if (this.clipboard !== null && this.paste_enabled) {
793 if (this.clipboard !== null && this.paste_enabled) {
789 var cell_data = this.clipboard;
794 var cell_data = this.clipboard;
790 var new_cell = this.insert_cell_above(cell_data.cell_type);
795 var new_cell = this.insert_cell_above(cell_data.cell_type);
791 new_cell.fromJSON(cell_data);
796 new_cell.fromJSON(cell_data);
792 old_cell = this.get_next_cell(new_cell);
797 old_cell = this.get_next_cell(new_cell);
793 this.delete_cell(this.find_cell_index(old_cell));
798 this.delete_cell(this.find_cell_index(old_cell));
794 this.select(this.find_cell_index(new_cell));
799 this.select(this.find_cell_index(new_cell));
795 };
800 };
796 };
801 };
797
802
798
803
799 Notebook.prototype.paste_cell_above = function () {
804 Notebook.prototype.paste_cell_above = function () {
800 if (this.clipboard !== null && this.paste_enabled) {
805 if (this.clipboard !== null && this.paste_enabled) {
801 var cell_data = this.clipboard;
806 var cell_data = this.clipboard;
802 var new_cell = this.insert_cell_above(cell_data.cell_type);
807 var new_cell = this.insert_cell_above(cell_data.cell_type);
803 new_cell.fromJSON(cell_data);
808 new_cell.fromJSON(cell_data);
804 };
809 };
805 };
810 };
806
811
807
812
808 Notebook.prototype.paste_cell_below = function () {
813 Notebook.prototype.paste_cell_below = function () {
809 if (this.clipboard !== null && this.paste_enabled) {
814 if (this.clipboard !== null && this.paste_enabled) {
810 var cell_data = this.clipboard;
815 var cell_data = this.clipboard;
811 var new_cell = this.insert_cell_below(cell_data.cell_type);
816 var new_cell = this.insert_cell_below(cell_data.cell_type);
812 new_cell.fromJSON(cell_data);
817 new_cell.fromJSON(cell_data);
813 };
818 };
814 };
819 };
815
820
816
821
817 // Split/merge
822 // Split/merge
818
823
819 Notebook.prototype.split_cell = function () {
824 Notebook.prototype.split_cell = function () {
820 // Todo: implement spliting for other cell types.
825 // Todo: implement spliting for other cell types.
821 var cell = this.get_selected_cell();
826 var cell = this.get_selected_cell();
822 if (cell.is_splittable()) {
827 if (cell.is_splittable()) {
823 texta = cell.get_pre_cursor();
828 texta = cell.get_pre_cursor();
824 textb = cell.get_post_cursor();
829 textb = cell.get_post_cursor();
825 if (cell instanceof IPython.CodeCell) {
830 if (cell instanceof IPython.CodeCell) {
826 cell.set_text(texta);
831 cell.set_text(texta);
827 var new_cell = this.insert_cell_below('code');
832 var new_cell = this.insert_cell_below('code');
828 new_cell.set_text(textb);
833 new_cell.set_text(textb);
829 } else if (cell instanceof IPython.MarkdownCell) {
834 } else if (cell instanceof IPython.MarkdownCell) {
830 cell.set_text(texta);
835 cell.set_text(texta);
831 cell.render();
836 cell.render();
832 var new_cell = this.insert_cell_below('markdown');
837 var new_cell = this.insert_cell_below('markdown');
833 new_cell.edit(); // editor must be visible to call set_text
838 new_cell.edit(); // editor must be visible to call set_text
834 new_cell.set_text(textb);
839 new_cell.set_text(textb);
835 new_cell.render();
840 new_cell.render();
836 } else if (cell instanceof IPython.HTMLCell) {
841 } else if (cell instanceof IPython.HTMLCell) {
837 cell.set_text(texta);
842 cell.set_text(texta);
838 cell.render();
843 cell.render();
839 var new_cell = this.insert_cell_below('html');
844 var new_cell = this.insert_cell_below('html');
840 new_cell.edit(); // editor must be visible to call set_text
845 new_cell.edit(); // editor must be visible to call set_text
841 new_cell.set_text(textb);
846 new_cell.set_text(textb);
842 new_cell.render();
847 new_cell.render();
843 };
848 };
844 };
849 };
845 };
850 };
846
851
847
852
848 Notebook.prototype.merge_cell_above = function () {
853 Notebook.prototype.merge_cell_above = function () {
849 var index = this.get_selected_index();
854 var index = this.get_selected_index();
850 var cell = this.get_cell(index);
855 var cell = this.get_cell(index);
851 if (index > 0) {
856 if (index > 0) {
852 upper_cell = this.get_cell(index-1);
857 upper_cell = this.get_cell(index-1);
853 upper_text = upper_cell.get_text();
858 upper_text = upper_cell.get_text();
854 text = cell.get_text();
859 text = cell.get_text();
855 if (cell instanceof IPython.CodeCell) {
860 if (cell instanceof IPython.CodeCell) {
856 cell.set_text(upper_text+'\n'+text);
861 cell.set_text(upper_text+'\n'+text);
857 } else if (cell instanceof IPython.MarkdownCell || cell instanceof IPython.HTMLCell) {
862 } else if (cell instanceof IPython.MarkdownCell || cell instanceof IPython.HTMLCell) {
858 cell.edit();
863 cell.edit();
859 cell.set_text(upper_text+'\n'+text);
864 cell.set_text(upper_text+'\n'+text);
860 cell.render();
865 cell.render();
861 };
866 };
862 this.delete_cell(index-1);
867 this.delete_cell(index-1);
863 this.select(this.find_cell_index(cell));
868 this.select(this.find_cell_index(cell));
864 };
869 };
865 };
870 };
866
871
867
872
868 Notebook.prototype.merge_cell_below = function () {
873 Notebook.prototype.merge_cell_below = function () {
869 var index = this.get_selected_index();
874 var index = this.get_selected_index();
870 var cell = this.get_cell(index);
875 var cell = this.get_cell(index);
871 if (index < this.ncells()-1) {
876 if (index < this.ncells()-1) {
872 lower_cell = this.get_cell(index+1);
877 lower_cell = this.get_cell(index+1);
873 lower_text = lower_cell.get_text();
878 lower_text = lower_cell.get_text();
874 text = cell.get_text();
879 text = cell.get_text();
875 if (cell instanceof IPython.CodeCell) {
880 if (cell instanceof IPython.CodeCell) {
876 cell.set_text(text+'\n'+lower_text);
881 cell.set_text(text+'\n'+lower_text);
877 } else if (cell instanceof IPython.MarkdownCell || cell instanceof IPython.HTMLCell) {
882 } else if (cell instanceof IPython.MarkdownCell || cell instanceof IPython.HTMLCell) {
878 cell.edit();
883 cell.edit();
879 cell.set_text(text+'\n'+lower_text);
884 cell.set_text(text+'\n'+lower_text);
880 cell.render();
885 cell.render();
881 };
886 };
882 this.delete_cell(index+1);
887 this.delete_cell(index+1);
883 this.select(this.find_cell_index(cell));
888 this.select(this.find_cell_index(cell));
884 };
889 };
885 };
890 };
886
891
887
892
888 // Cell collapsing and output clearing
893 // Cell collapsing and output clearing
889
894
890 Notebook.prototype.collapse = function (index) {
895 Notebook.prototype.collapse = function (index) {
891 var i = this.index_or_selected(index);
896 var i = this.index_or_selected(index);
892 this.get_cell(i).collapse();
897 this.get_cell(i).collapse();
893 this.dirty = true;
898 this.dirty = true;
894 };
899 };
895
900
896
901
897 Notebook.prototype.expand = function (index) {
902 Notebook.prototype.expand = function (index) {
898 var i = this.index_or_selected(index);
903 var i = this.index_or_selected(index);
899 this.get_cell(i).expand();
904 this.get_cell(i).expand();
900 this.dirty = true;
905 this.dirty = true;
901 };
906 };
902
907
903
908
904 Notebook.prototype.toggle_output = function (index) {
909 Notebook.prototype.toggle_output = function (index) {
905 var i = this.index_or_selected(index);
910 var i = this.index_or_selected(index);
906 this.get_cell(i).toggle_output();
911 this.get_cell(i).toggle_output();
907 this.dirty = true;
912 this.dirty = true;
908 };
913 };
909
914
910
915
911 Notebook.prototype.toggle_output_scroll = function (index) {
916 Notebook.prototype.toggle_output_scroll = function (index) {
912 var i = this.index_or_selected(index);
917 var i = this.index_or_selected(index);
913 this.get_cell(i).toggle_output_scroll();
918 this.get_cell(i).toggle_output_scroll();
914 };
919 };
915
920
916
921
917 Notebook.prototype.collapse_all_output = function () {
922 Notebook.prototype.collapse_all_output = function () {
918 var ncells = this.ncells();
923 var ncells = this.ncells();
919 var cells = this.get_cells();
924 var cells = this.get_cells();
920 for (var i=0; i<ncells; i++) {
925 for (var i=0; i<ncells; i++) {
921 if (cells[i] instanceof IPython.CodeCell) {
926 if (cells[i] instanceof IPython.CodeCell) {
922 cells[i].output_area.collapse();
927 cells[i].output_area.collapse();
923 }
928 }
924 };
929 };
925 // this should not be set if the `collapse` key is removed from nbformat
930 // this should not be set if the `collapse` key is removed from nbformat
926 this.dirty = true;
931 this.dirty = true;
927 };
932 };
928
933
929
934
930 Notebook.prototype.scroll_all_output = function () {
935 Notebook.prototype.scroll_all_output = function () {
931 var ncells = this.ncells();
936 var ncells = this.ncells();
932 var cells = this.get_cells();
937 var cells = this.get_cells();
933 for (var i=0; i<ncells; i++) {
938 for (var i=0; i<ncells; i++) {
934 if (cells[i] instanceof IPython.CodeCell) {
939 if (cells[i] instanceof IPython.CodeCell) {
935 cells[i].output_area.expand();
940 cells[i].output_area.expand();
936 cells[i].output_area.scroll_if_long(20);
941 cells[i].output_area.scroll_if_long(20);
937 }
942 }
938 };
943 };
939 // this should not be set if the `collapse` key is removed from nbformat
944 // this should not be set if the `collapse` key is removed from nbformat
940 this.dirty = true;
945 this.dirty = true;
941 };
946 };
942
947
943
948
944 Notebook.prototype.expand_all_output = function () {
949 Notebook.prototype.expand_all_output = function () {
945 var ncells = this.ncells();
950 var ncells = this.ncells();
946 var cells = this.get_cells();
951 var cells = this.get_cells();
947 for (var i=0; i<ncells; i++) {
952 for (var i=0; i<ncells; i++) {
948 if (cells[i] instanceof IPython.CodeCell) {
953 if (cells[i] instanceof IPython.CodeCell) {
949 cells[i].output_area.expand();
954 cells[i].output_area.expand();
950 cells[i].output_area.unscroll_area();
955 cells[i].output_area.unscroll_area();
951 }
956 }
952 };
957 };
953 // this should not be set if the `collapse` key is removed from nbformat
958 // this should not be set if the `collapse` key is removed from nbformat
954 this.dirty = true;
959 this.dirty = true;
955 };
960 };
956
961
957
962
958 Notebook.prototype.clear_all_output = function () {
963 Notebook.prototype.clear_all_output = function () {
959 var ncells = this.ncells();
964 var ncells = this.ncells();
960 var cells = this.get_cells();
965 var cells = this.get_cells();
961 for (var i=0; i<ncells; i++) {
966 for (var i=0; i<ncells; i++) {
962 if (cells[i] instanceof IPython.CodeCell) {
967 if (cells[i] instanceof IPython.CodeCell) {
963 cells[i].clear_output(true,true,true);
968 cells[i].clear_output(true,true,true);
964 // Make all In[] prompts blank, as well
969 // Make all In[] prompts blank, as well
965 // TODO: make this configurable (via checkbox?)
970 // TODO: make this configurable (via checkbox?)
966 cells[i].set_input_prompt();
971 cells[i].set_input_prompt();
967 }
972 }
968 };
973 };
969 this.dirty = true;
974 this.dirty = true;
970 };
975 };
971
976
972
977
973 // Other cell functions: line numbers, ...
978 // Other cell functions: line numbers, ...
974
979
975 Notebook.prototype.cell_toggle_line_numbers = function() {
980 Notebook.prototype.cell_toggle_line_numbers = function() {
976 this.get_selected_cell().toggle_line_numbers();
981 this.get_selected_cell().toggle_line_numbers();
977 };
982 };
978
983
979 // Kernel related things
984 // Kernel related things
980
985
981 Notebook.prototype.start_kernel = function () {
986 Notebook.prototype.start_kernel = function () {
982 var base_url = $('body').data('baseKernelUrl') + "kernels";
987 var base_url = $('body').data('baseKernelUrl') + "kernels";
983 this.kernel = new IPython.Kernel(base_url);
988 this.kernel = new IPython.Kernel(base_url);
984 this.kernel.start(this.notebook_id);
989 this.kernel.start(this.notebook_id);
985 // Now that the kernel has been created, tell the CodeCells about it.
990 // Now that the kernel has been created, tell the CodeCells about it.
986 var ncells = this.ncells();
991 var ncells = this.ncells();
987 for (var i=0; i<ncells; i++) {
992 for (var i=0; i<ncells; i++) {
988 var cell = this.get_cell(i);
993 var cell = this.get_cell(i);
989 if (cell instanceof IPython.CodeCell) {
994 if (cell instanceof IPython.CodeCell) {
990 cell.set_kernel(this.kernel)
995 cell.set_kernel(this.kernel)
991 };
996 };
992 };
997 };
993 };
998 };
994
999
995
1000
996 Notebook.prototype.restart_kernel = function () {
1001 Notebook.prototype.restart_kernel = function () {
997 var that = this;
1002 var that = this;
998 var dialog = $('<div/>');
1003 var dialog = $('<div/>');
999 dialog.html('Do you want to restart the current kernel? You will lose all variables defined in it.');
1004 dialog.html('Do you want to restart the current kernel? You will lose all variables defined in it.');
1000 $(document).append(dialog);
1005 $(document).append(dialog);
1001 dialog.dialog({
1006 dialog.dialog({
1002 resizable: false,
1007 resizable: false,
1003 modal: true,
1008 modal: true,
1004 title: "Restart kernel or continue running?",
1009 title: "Restart kernel or continue running?",
1005 closeText: '',
1010 closeText: '',
1006 buttons : {
1011 buttons : {
1007 "Restart": function () {
1012 "Restart": function () {
1008 that.kernel.restart();
1013 that.kernel.restart();
1009 $(this).dialog('close');
1014 $(this).dialog('close');
1010 },
1015 },
1011 "Continue running": function () {
1016 "Continue running": function () {
1012 $(this).dialog('close');
1017 $(this).dialog('close');
1013 }
1018 }
1014 }
1019 }
1015 });
1020 });
1016 };
1021 };
1017
1022
1018
1023
1019 Notebook.prototype.execute_selected_cell = function (options) {
1024 Notebook.prototype.execute_selected_cell = function (options) {
1020 // add_new: should a new cell be added if we are at the end of the nb
1025 // add_new: should a new cell be added if we are at the end of the nb
1021 // terminal: execute in terminal mode, which stays in the current cell
1026 // terminal: execute in terminal mode, which stays in the current cell
1022 default_options = {terminal: false, add_new: true};
1027 default_options = {terminal: false, add_new: true};
1023 $.extend(default_options, options);
1028 $.extend(default_options, options);
1024 var that = this;
1029 var that = this;
1025 var cell = that.get_selected_cell();
1030 var cell = that.get_selected_cell();
1026 var cell_index = that.find_cell_index(cell);
1031 var cell_index = that.find_cell_index(cell);
1027 if (cell instanceof IPython.CodeCell) {
1032 if (cell instanceof IPython.CodeCell) {
1028 cell.execute();
1033 cell.execute();
1029 } else if (cell instanceof IPython.HTMLCell) {
1034 } else if (cell instanceof IPython.HTMLCell) {
1030 cell.render();
1035 cell.render();
1031 }
1036 }
1032 if (default_options.terminal) {
1037 if (default_options.terminal) {
1033 cell.select_all();
1038 cell.select_all();
1034 } else {
1039 } else {
1035 if ((cell_index === (that.ncells()-1)) && default_options.add_new) {
1040 if ((cell_index === (that.ncells()-1)) && default_options.add_new) {
1036 that.insert_cell_below('code');
1041 that.insert_cell_below('code');
1037 // If we are adding a new cell at the end, scroll down to show it.
1042 // If we are adding a new cell at the end, scroll down to show it.
1038 that.scroll_to_bottom();
1043 that.scroll_to_bottom();
1039 } else {
1044 } else {
1040 that.select(cell_index+1);
1045 that.select(cell_index+1);
1041 };
1046 };
1042 };
1047 };
1043 this.dirty = true;
1048 this.dirty = true;
1044 };
1049 };
1045
1050
1046
1051
1047 Notebook.prototype.execute_all_cells = function () {
1052 Notebook.prototype.execute_all_cells = function () {
1048 var ncells = this.ncells();
1053 var ncells = this.ncells();
1049 for (var i=0; i<ncells; i++) {
1054 for (var i=0; i<ncells; i++) {
1050 this.select(i);
1055 this.select(i);
1051 this.execute_selected_cell({add_new:false});
1056 this.execute_selected_cell({add_new:false});
1052 };
1057 };
1053 this.scroll_to_bottom();
1058 this.scroll_to_bottom();
1054 };
1059 };
1055
1060
1056 // Persistance and loading
1061 // Persistance and loading
1057
1062
1058 Notebook.prototype.get_notebook_id = function () {
1063 Notebook.prototype.get_notebook_id = function () {
1059 return this.notebook_id;
1064 return this.notebook_id;
1060 };
1065 };
1061
1066
1062
1067
1063 Notebook.prototype.get_notebook_name = function () {
1068 Notebook.prototype.get_notebook_name = function () {
1064 return this.notebook_name;
1069 return this.notebook_name;
1065 };
1070 };
1066
1071
1067
1072
1068 Notebook.prototype.set_notebook_name = function (name) {
1073 Notebook.prototype.set_notebook_name = function (name) {
1069 this.notebook_name = name;
1074 this.notebook_name = name;
1070 };
1075 };
1071
1076
1072
1077
1073 Notebook.prototype.test_notebook_name = function (nbname) {
1078 Notebook.prototype.test_notebook_name = function (nbname) {
1074 nbname = nbname || '';
1079 nbname = nbname || '';
1075 if (this.notebook_name_blacklist_re.test(nbname) == false && nbname.length>0) {
1080 if (this.notebook_name_blacklist_re.test(nbname) == false && nbname.length>0) {
1076 return true;
1081 return true;
1077 } else {
1082 } else {
1078 return false;
1083 return false;
1079 };
1084 };
1080 };
1085 };
1081
1086
1082
1087
1083 Notebook.prototype.fromJSON = function (data) {
1088 Notebook.prototype.fromJSON = function (data) {
1084 var ncells = this.ncells();
1089 var ncells = this.ncells();
1085 var i;
1090 var i;
1086 for (i=0; i<ncells; i++) {
1091 for (i=0; i<ncells; i++) {
1087 // Always delete cell 0 as they get renumbered as they are deleted.
1092 // Always delete cell 0 as they get renumbered as they are deleted.
1088 this.delete_cell(0);
1093 this.delete_cell(0);
1089 };
1094 };
1090 // Save the metadata and name.
1095 // Save the metadata and name.
1091 this.metadata = data.metadata;
1096 this.metadata = data.metadata;
1092 this.notebook_name = data.metadata.name;
1097 this.notebook_name = data.metadata.name;
1093 // Only handle 1 worksheet for now.
1098 // Only handle 1 worksheet for now.
1094 var worksheet = data.worksheets[0];
1099 var worksheet = data.worksheets[0];
1095 if (worksheet !== undefined) {
1100 if (worksheet !== undefined) {
1096 if (worksheet.metadata) {
1101 if (worksheet.metadata) {
1097 this.worksheet_metadata = worksheet.metadata;
1102 this.worksheet_metadata = worksheet.metadata;
1098 }
1103 }
1099 var new_cells = worksheet.cells;
1104 var new_cells = worksheet.cells;
1100 ncells = new_cells.length;
1105 ncells = new_cells.length;
1101 var cell_data = null;
1106 var cell_data = null;
1102 var new_cell = null;
1107 var new_cell = null;
1103 for (i=0; i<ncells; i++) {
1108 for (i=0; i<ncells; i++) {
1104 cell_data = new_cells[i];
1109 cell_data = new_cells[i];
1105 // VERSIONHACK: plaintext -> raw
1110 // VERSIONHACK: plaintext -> raw
1106 // handle never-released plaintext name for raw cells
1111 // handle never-released plaintext name for raw cells
1107 if (cell_data.cell_type === 'plaintext'){
1112 if (cell_data.cell_type === 'plaintext'){
1108 cell_data.cell_type = 'raw';
1113 cell_data.cell_type = 'raw';
1109 }
1114 }
1110
1115
1111 new_cell = this.insert_cell_below(cell_data.cell_type);
1116 new_cell = this.insert_cell_below(cell_data.cell_type);
1112 new_cell.fromJSON(cell_data);
1117 new_cell.fromJSON(cell_data);
1113 };
1118 };
1114 };
1119 };
1115 if (data.worksheets.length > 1) {
1120 if (data.worksheets.length > 1) {
1116 var dialog = $('<div/>');
1121 var dialog = $('<div/>');
1117 dialog.html("This notebook has " + data.worksheets.length + " worksheets, " +
1122 dialog.html("This notebook has " + data.worksheets.length + " worksheets, " +
1118 "but this version of IPython can only handle the first. " +
1123 "but this version of IPython can only handle the first. " +
1119 "If you save this notebook, worksheets after the first will be lost."
1124 "If you save this notebook, worksheets after the first will be lost."
1120 );
1125 );
1121 this.element.append(dialog);
1126 this.element.append(dialog);
1122 dialog.dialog({
1127 dialog.dialog({
1123 resizable: false,
1128 resizable: false,
1124 modal: true,
1129 modal: true,
1125 title: "Multiple worksheets",
1130 title: "Multiple worksheets",
1126 closeText: "",
1131 closeText: "",
1127 close: function(event, ui) {$(this).dialog('destroy').remove();},
1132 close: function(event, ui) {$(this).dialog('destroy').remove();},
1128 buttons : {
1133 buttons : {
1129 "OK": function () {
1134 "OK": function () {
1130 $(this).dialog('close');
1135 $(this).dialog('close');
1131 }
1136 }
1132 },
1137 },
1133 width: 400
1138 width: 400
1134 });
1139 });
1135 }
1140 }
1136 };
1141 };
1137
1142
1138
1143
1139 Notebook.prototype.toJSON = function () {
1144 Notebook.prototype.toJSON = function () {
1140 var cells = this.get_cells();
1145 var cells = this.get_cells();
1141 var ncells = cells.length;
1146 var ncells = cells.length;
1142 var cell_array = new Array(ncells);
1147 var cell_array = new Array(ncells);
1143 for (var i=0; i<ncells; i++) {
1148 for (var i=0; i<ncells; i++) {
1144 cell_array[i] = cells[i].toJSON();
1149 cell_array[i] = cells[i].toJSON();
1145 };
1150 };
1146 var data = {
1151 var data = {
1147 // Only handle 1 worksheet for now.
1152 // Only handle 1 worksheet for now.
1148 worksheets : [{
1153 worksheets : [{
1149 cells: cell_array,
1154 cells: cell_array,
1150 metadata: this.worksheet_metadata
1155 metadata: this.worksheet_metadata
1151 }],
1156 }],
1152 metadata : this.metadata
1157 metadata : this.metadata
1153 };
1158 };
1154 return data;
1159 return data;
1155 };
1160 };
1156
1161
1157 Notebook.prototype.save_notebook = function () {
1162 Notebook.prototype.save_notebook = function () {
1158 // We may want to move the name/id/nbformat logic inside toJSON?
1163 // We may want to move the name/id/nbformat logic inside toJSON?
1159 var data = this.toJSON();
1164 var data = this.toJSON();
1160 data.metadata.name = this.notebook_name;
1165 data.metadata.name = this.notebook_name;
1161 data.nbformat = this.nbformat;
1166 data.nbformat = this.nbformat;
1162 data.nbformat_minor = this.nbformat_minor;
1167 data.nbformat_minor = this.nbformat_minor;
1163 // We do the call with settings so we can set cache to false.
1168 // We do the call with settings so we can set cache to false.
1164 var settings = {
1169 var settings = {
1165 processData : false,
1170 processData : false,
1166 cache : false,
1171 cache : false,
1167 type : "PUT",
1172 type : "PUT",
1168 data : JSON.stringify(data),
1173 data : JSON.stringify(data),
1169 headers : {'Content-Type': 'application/json'},
1174 headers : {'Content-Type': 'application/json'},
1170 success : $.proxy(this.save_notebook_success,this),
1175 success : $.proxy(this.save_notebook_success,this),
1171 error : $.proxy(this.save_notebook_error,this)
1176 error : $.proxy(this.save_notebook_error,this)
1172 };
1177 };
1173 $([IPython.events]).trigger('notebook_saving.Notebook');
1178 $([IPython.events]).trigger('notebook_saving.Notebook');
1174 var url = $('body').data('baseProjectUrl') + 'notebooks/' + this.notebook_id;
1179 var url = $('body').data('baseProjectUrl') + 'notebooks/' + this.notebook_id;
1175 $.ajax(url, settings);
1180 $.ajax(url, settings);
1176 };
1181 };
1177
1182
1178
1183
1179 Notebook.prototype.save_notebook_success = function (data, status, xhr) {
1184 Notebook.prototype.save_notebook_success = function (data, status, xhr) {
1180 this.dirty = false;
1185 this.dirty = false;
1181 $([IPython.events]).trigger('notebook_saved.Notebook');
1186 $([IPython.events]).trigger('notebook_saved.Notebook');
1182 };
1187 };
1183
1188
1184
1189
1185 Notebook.prototype.save_notebook_error = function (xhr, status, error_msg) {
1190 Notebook.prototype.save_notebook_error = function (xhr, status, error_msg) {
1186 $([IPython.events]).trigger('notebook_save_failed.Notebook');
1191 $([IPython.events]).trigger('notebook_save_failed.Notebook');
1187 };
1192 };
1188
1193
1189
1194
1190 Notebook.prototype.load_notebook = function (notebook_id) {
1195 Notebook.prototype.load_notebook = function (notebook_id) {
1191 var that = this;
1196 var that = this;
1192 this.notebook_id = notebook_id;
1197 this.notebook_id = notebook_id;
1193 // We do the call with settings so we can set cache to false.
1198 // We do the call with settings so we can set cache to false.
1194 var settings = {
1199 var settings = {
1195 processData : false,
1200 processData : false,
1196 cache : false,
1201 cache : false,
1197 type : "GET",
1202 type : "GET",
1198 dataType : "json",
1203 dataType : "json",
1199 success : $.proxy(this.load_notebook_success,this),
1204 success : $.proxy(this.load_notebook_success,this),
1200 error : $.proxy(this.load_notebook_error,this),
1205 error : $.proxy(this.load_notebook_error,this),
1201 };
1206 };
1202 $([IPython.events]).trigger('notebook_loading.Notebook');
1207 $([IPython.events]).trigger('notebook_loading.Notebook');
1203 var url = $('body').data('baseProjectUrl') + 'notebooks/' + this.notebook_id;
1208 var url = $('body').data('baseProjectUrl') + 'notebooks/' + this.notebook_id;
1204 $.ajax(url, settings);
1209 $.ajax(url, settings);
1205 };
1210 };
1206
1211
1207
1212
1208 Notebook.prototype.load_notebook_success = function (data, status, xhr) {
1213 Notebook.prototype.load_notebook_success = function (data, status, xhr) {
1209 this.fromJSON(data);
1214 this.fromJSON(data);
1210 if (this.ncells() === 0) {
1215 if (this.ncells() === 0) {
1211 this.insert_cell_below('code');
1216 this.insert_cell_below('code');
1212 };
1217 };
1213 this.dirty = false;
1218 this.dirty = false;
1214 this.select(0);
1219 this.select(0);
1215 this.scroll_to_top();
1220 this.scroll_to_top();
1216 if (data.orig_nbformat !== undefined && data.nbformat !== data.orig_nbformat) {
1221 if (data.orig_nbformat !== undefined && data.nbformat !== data.orig_nbformat) {
1217 msg = "This notebook has been converted from an older " +
1222 msg = "This notebook has been converted from an older " +
1218 "notebook format (v"+data.orig_nbformat+") to the current notebook " +
1223 "notebook format (v"+data.orig_nbformat+") to the current notebook " +
1219 "format (v"+data.nbformat+"). The next time you save this notebook, the " +
1224 "format (v"+data.nbformat+"). The next time you save this notebook, the " +
1220 "newer notebook format will be used and older verions of IPython " +
1225 "newer notebook format will be used and older verions of IPython " +
1221 "may not be able to read it. To keep the older version, close the " +
1226 "may not be able to read it. To keep the older version, close the " +
1222 "notebook without saving it.";
1227 "notebook without saving it.";
1223 var dialog = $('<div/>');
1228 var dialog = $('<div/>');
1224 dialog.html(msg);
1229 dialog.html(msg);
1225 this.element.append(dialog);
1230 this.element.append(dialog);
1226 dialog.dialog({
1231 dialog.dialog({
1227 resizable: false,
1232 resizable: false,
1228 modal: true,
1233 modal: true,
1229 title: "Notebook converted",
1234 title: "Notebook converted",
1230 closeText: "",
1235 closeText: "",
1231 close: function(event, ui) {$(this).dialog('destroy').remove();},
1236 close: function(event, ui) {$(this).dialog('destroy').remove();},
1232 buttons : {
1237 buttons : {
1233 "OK": function () {
1238 "OK": function () {
1234 $(this).dialog('close');
1239 $(this).dialog('close');
1235 }
1240 }
1236 },
1241 },
1237 width: 400
1242 width: 400
1238 });
1243 });
1239 } else if (data.orig_nbformat_minor !== undefined && data.nbformat_minor !== data.orig_nbformat_minor) {
1244 } else if (data.orig_nbformat_minor !== undefined && data.nbformat_minor !== data.orig_nbformat_minor) {
1240 var that = this;
1245 var that = this;
1241 var orig_vs = 'v' + data.nbformat + '.' + data.orig_nbformat_minor;
1246 var orig_vs = 'v' + data.nbformat + '.' + data.orig_nbformat_minor;
1242 var this_vs = 'v' + data.nbformat + '.' + this.nbformat_minor;
1247 var this_vs = 'v' + data.nbformat + '.' + this.nbformat_minor;
1243 msg = "This notebook is version " + orig_vs + ", but we only fully support up to " +
1248 msg = "This notebook is version " + orig_vs + ", but we only fully support up to " +
1244 this_vs + ". You can still work with this notebook, but some features " +
1249 this_vs + ". You can still work with this notebook, but some features " +
1245 "introduced in later notebook versions may not be available."
1250 "introduced in later notebook versions may not be available."
1246
1251
1247 var dialog = $('<div/>');
1252 var dialog = $('<div/>');
1248 dialog.html(msg);
1253 dialog.html(msg);
1249 this.element.append(dialog);
1254 this.element.append(dialog);
1250 dialog.dialog({
1255 dialog.dialog({
1251 resizable: false,
1256 resizable: false,
1252 modal: true,
1257 modal: true,
1253 title: "Newer Notebook",
1258 title: "Newer Notebook",
1254 closeText: "",
1259 closeText: "",
1255 close: function(event, ui) {$(this).dialog('destroy').remove();},
1260 close: function(event, ui) {$(this).dialog('destroy').remove();},
1256 buttons : {
1261 buttons : {
1257 "OK": function () {
1262 "OK": function () {
1258 $(this).dialog('close');
1263 $(this).dialog('close');
1259 }
1264 }
1260 },
1265 },
1261 width: 400
1266 width: 400
1262 });
1267 });
1263
1268
1264 }
1269 }
1265 // Create the kernel after the notebook is completely loaded to prevent
1270 // Create the kernel after the notebook is completely loaded to prevent
1266 // code execution upon loading, which is a security risk.
1271 // code execution upon loading, which is a security risk.
1267 if (! this.read_only) {
1272 if (! this.read_only) {
1268 this.start_kernel();
1273 this.start_kernel();
1269 }
1274 }
1270 $([IPython.events]).trigger('notebook_loaded.Notebook');
1275 $([IPython.events]).trigger('notebook_loaded.Notebook');
1271 };
1276 };
1272
1277
1273
1278
1274 Notebook.prototype.load_notebook_error = function (xhr, textStatus, errorThrow) {
1279 Notebook.prototype.load_notebook_error = function (xhr, textStatus, errorThrow) {
1275 if (xhr.status === 500) {
1280 if (xhr.status === 500) {
1276 msg = "An error occurred while loading this notebook. Most likely " +
1281 msg = "An error occurred while loading this notebook. Most likely " +
1277 "this notebook is in a newer format than is supported by this " +
1282 "this notebook is in a newer format than is supported by this " +
1278 "version of IPython. This version can load notebook formats " +
1283 "version of IPython. This version can load notebook formats " +
1279 "v"+this.nbformat+" or earlier.";
1284 "v"+this.nbformat+" or earlier.";
1280 var dialog = $('<div/>');
1285 var dialog = $('<div/>');
1281 dialog.html(msg);
1286 dialog.html(msg);
1282 this.element.append(dialog);
1287 this.element.append(dialog);
1283 dialog.dialog({
1288 dialog.dialog({
1284 resizable: false,
1289 resizable: false,
1285 modal: true,
1290 modal: true,
1286 title: "Error loading notebook",
1291 title: "Error loading notebook",
1287 closeText: "",
1292 closeText: "",
1288 close: function(event, ui) {$(this).dialog('destroy').remove();},
1293 close: function(event, ui) {$(this).dialog('destroy').remove();},
1289 buttons : {
1294 buttons : {
1290 "OK": function () {
1295 "OK": function () {
1291 $(this).dialog('close');
1296 $(this).dialog('close');
1292 }
1297 }
1293 },
1298 },
1294 width: 400
1299 width: 400
1295 });
1300 });
1296 }
1301 }
1297 }
1302 }
1298
1303
1299 IPython.Notebook = Notebook;
1304 IPython.Notebook = Notebook;
1300
1305
1301
1306
1302 return IPython;
1307 return IPython;
1303
1308
1304 }(IPython));
1309 }(IPython));
1305
1310
General Comments 0
You need to be logged in to leave comments. Login now