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