##// END OF EJS Templates
smart kwarg completion...
Matthias BUSSONNIER -
Show More
@@ -1,392 +1,396
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 background-color: white;
9 background-color: white;
10 /* This makes sure that the body covers the entire window and needs to
10 /* This makes sure that the body covers the entire window and needs to
11 be in a different element than the display: box in wrapper below */
11 be in a different element than the display: box in wrapper below */
12 position: absolute;
12 position: absolute;
13 left: 0px;
13 left: 0px;
14 right: 0px;
14 right: 0px;
15 top: 0px;
15 top: 0px;
16 bottom: 0px;
16 bottom: 0px;
17 overflow: hidden;
17 overflow: hidden;
18 }
18 }
19
19
20 span#save_widget {
20 span#save_widget {
21 position: static;
21 position: static;
22 left: 0px;
22 left: 0px;
23 padding: 5px 0px;
23 padding: 5px 0px;
24 margin: 0px 0px 0px 0px;
24 margin: 0px 0px 0px 0px;
25 }
25 }
26
26
27 span#quick_help_area {
27 span#quick_help_area {
28 position: static;
28 position: static;
29 padding: 5px 0px;
29 padding: 5px 0px;
30 margin: 0px 0px 0px 0px;
30 margin: 0px 0px 0px 0px;
31 }
31 }
32
32
33 input#notebook_name {
33 input#notebook_name {
34 height: 1em;
34 height: 1em;
35 line-height: 1em;
35 line-height: 1em;
36 padding: 5px;
36 padding: 5px;
37 }
37 }
38
38
39 span#kernel_status {
39 span#kernel_status {
40 position: absolute;
40 position: absolute;
41 padding: 8px 5px 5px 5px;
41 padding: 8px 5px 5px 5px;
42 right: 10px;
42 right: 10px;
43 font-weight: bold;
43 font-weight: bold;
44 }
44 }
45
45
46
46
47 .status_idle {
47 .status_idle {
48 color: gray;
48 color: gray;
49 visibility: hidden;
49 visibility: hidden;
50 }
50 }
51
51
52 .status_busy {
52 .status_busy {
53 color: red;
53 color: red;
54 }
54 }
55
55
56 .status_restarting {
56 .status_restarting {
57 color: black;
57 color: black;
58 }
58 }
59
59
60 div#left_panel {
60 div#left_panel {
61 overflow-y: auto;
61 overflow-y: auto;
62 top: 0px;
62 top: 0px;
63 left: 0px;
63 left: 0px;
64 margin: 0px;
64 margin: 0px;
65 padding: 0px;
65 padding: 0px;
66 position: absolute;
66 position: absolute;
67 }
67 }
68
68
69 div.section_header {
69 div.section_header {
70 padding: 5px;
70 padding: 5px;
71 }
71 }
72
72
73 div.section_header h3 {
73 div.section_header h3 {
74 display: inline;
74 display: inline;
75 }
75 }
76
76
77 div.section_content {
77 div.section_content {
78 padding: 5px;
78 padding: 5px;
79 }
79 }
80
80
81 span.section_row_buttons button {
81 span.section_row_buttons button {
82 width: 70px;
82 width: 70px;
83 }
83 }
84
84
85 span.section_row_buttons a {
85 span.section_row_buttons a {
86 width: 70px;
86 width: 70px;
87 }
87 }
88
88
89 .section_row {
89 .section_row {
90 margin: 5px 0px;
90 margin: 5px 0px;
91 }
91 }
92
92
93 .section_row_buttons {
93 .section_row_buttons {
94 float: right;
94 float: right;
95 }
95 }
96
96
97 #kernel_persist {
97 #kernel_persist {
98 float: right;
98 float: right;
99 }
99 }
100
100
101 .help_string {
101 .help_string {
102 float: right;
102 float: right;
103 width: 170px;
103 width: 170px;
104 padding: 0px 5px;
104 padding: 0px 5px;
105 text-align: left;
105 text-align: left;
106 font-size: 85%;
106 font-size: 85%;
107 }
107 }
108
108
109 .help_string_label {
109 .help_string_label {
110 float: right;
110 float: right;
111 font-size: 85%;
111 font-size: 85%;
112 }
112 }
113
113
114 #autoindent_span {
114 #autoindent_span {
115 float: right;
115 float: right;
116 }
116 }
117
117
118 #tooltipontab_span {
118 #tooltipontab_span {
119 float: right;
119 float: right;
120 }
120 }
121
121
122 #smartcompleter_span {
123 float: right;
124 }
125
122 .checkbox_label {
126 .checkbox_label {
123 font-size: 85%;
127 font-size: 85%;
124 float: right;
128 float: right;
125 padding: 0.3em;
129 padding: 0.3em;
126 }
130 }
127
131
128 .section_row_header {
132 .section_row_header {
129 float: left;
133 float: left;
130 font-size: 85%;
134 font-size: 85%;
131 padding: 0.4em 0em;
135 padding: 0.4em 0em;
132 font-weight: bold;
136 font-weight: bold;
133 }
137 }
134
138
135 span.button_label {
139 span.button_label {
136 padding: 0.2em 1em;
140 padding: 0.2em 1em;
137 font-size: 77%;
141 font-size: 77%;
138 float: right;
142 float: right;
139 }
143 }
140
144
141 /* This is needed because FF was adding a 2px margin top and bottom. */
145 /* This is needed because FF was adding a 2px margin top and bottom. */
142 .section_row .ui-button {
146 .section_row .ui-button {
143 margin-top: 0px;
147 margin-top: 0px;
144 margin-bottom: 0px;
148 margin-bottom: 0px;
145 }
149 }
146
150
147 #download_format {
151 #download_format {
148 float: right;
152 float: right;
149 font-size: 85%;
153 font-size: 85%;
150 width: 62px;
154 width: 62px;
151 margin: 1px 5px;
155 margin: 1px 5px;
152 }
156 }
153
157
154 div#left_panel_splitter {
158 div#left_panel_splitter {
155 width: 8px;
159 width: 8px;
156 top: 0px;
160 top: 0px;
157 left: 202px;
161 left: 202px;
158 margin: 0px;
162 margin: 0px;
159 padding: 0px;
163 padding: 0px;
160 position: absolute;
164 position: absolute;
161 }
165 }
162
166
163 div#notebook_panel {
167 div#notebook_panel {
164 /* The L margin will be set in the Javascript code*/
168 /* The L margin will be set in the Javascript code*/
165 margin: 0px 0px 0px 0px;
169 margin: 0px 0px 0px 0px;
166 padding: 0px;
170 padding: 0px;
167 }
171 }
168
172
169 div#notebook {
173 div#notebook {
170 overflow-y: scroll;
174 overflow-y: scroll;
171 overflow-x: auto;
175 overflow-x: auto;
172 width: 100%;
176 width: 100%;
173 /* This spaces the cell away from the edge of the notebook area */
177 /* This spaces the cell away from the edge of the notebook area */
174 padding: 5px 5px 15px 5px;
178 padding: 5px 5px 15px 5px;
175 margin: 0px
179 margin: 0px
176 background-color: white;
180 background-color: white;
177 }
181 }
178
182
179 div#pager_splitter {
183 div#pager_splitter {
180 height: 8px;
184 height: 8px;
181 }
185 }
182
186
183 div#pager {
187 div#pager {
184 padding: 15px;
188 padding: 15px;
185 overflow: auto;
189 overflow: auto;
186 }
190 }
187
191
188 div.cell {
192 div.cell {
189 width: 100%;
193 width: 100%;
190 padding: 5px 5px 5px 0px;
194 padding: 5px 5px 5px 0px;
191 /* This acts as a spacer between cells, that is outside the border */
195 /* This acts as a spacer between cells, that is outside the border */
192 margin: 2px 0px 2px 0px;
196 margin: 2px 0px 2px 0px;
193 }
197 }
194
198
195 div.code_cell {
199 div.code_cell {
196 background-color: white;
200 background-color: white;
197 }
201 }
198 /* any special styling for code cells that are currently running goes here */
202 /* any special styling for code cells that are currently running goes here */
199 div.code_cell.running {
203 div.code_cell.running {
200 }
204 }
201
205
202 div.prompt {
206 div.prompt {
203 /* This needs to be wide enough for 3 digit prompt numbers: In[100]: */
207 /* This needs to be wide enough for 3 digit prompt numbers: In[100]: */
204 width: 11ex;
208 width: 11ex;
205 /* This 0.4em is tuned to match the padding on the CodeMirror editor. */
209 /* This 0.4em is tuned to match the padding on the CodeMirror editor. */
206 padding: 0.4em;
210 padding: 0.4em;
207 margin: 0px;
211 margin: 0px;
208 font-family: monospace;
212 font-family: monospace;
209 text-align:right;
213 text-align:right;
210 }
214 }
211
215
212 div.input {
216 div.input {
213 page-break-inside: avoid;
217 page-break-inside: avoid;
214 }
218 }
215
219
216 /* input_area and input_prompt must match in top border and margin for alignment */
220 /* input_area and input_prompt must match in top border and margin for alignment */
217 div.input_area {
221 div.input_area {
218 color: black;
222 color: black;
219 border: 1px solid #ddd;
223 border: 1px solid #ddd;
220 border-radius: 3px;
224 border-radius: 3px;
221 background: #f7f7f7;
225 background: #f7f7f7;
222 }
226 }
223
227
224 div.input_prompt {
228 div.input_prompt {
225 color: navy;
229 color: navy;
226 border-top: 1px solid transparent;
230 border-top: 1px solid transparent;
227 }
231 }
228
232
229 div.output {
233 div.output {
230 /* This is a spacer between the input and output of each cell */
234 /* This is a spacer between the input and output of each cell */
231 margin-top: 5px;
235 margin-top: 5px;
232 }
236 }
233
237
234 div.output_prompt {
238 div.output_prompt {
235 color: darkred;
239 color: darkred;
236 }
240 }
237
241
238 /* This class is the outer container of all output sections. */
242 /* This class is the outer container of all output sections. */
239 div.output_area {
243 div.output_area {
240 padding: 0px;
244 padding: 0px;
241 page-break-inside: avoid;
245 page-break-inside: avoid;
242 }
246 }
243
247
244 /* This class is for the output subarea inside the output_area and after
248 /* This class is for the output subarea inside the output_area and after
245 the prompt div. */
249 the prompt div. */
246 div.output_subarea {
250 div.output_subarea {
247 padding: 0.4em 6.1em 0.4em 0.4em;
251 padding: 0.4em 6.1em 0.4em 0.4em;
248 }
252 }
249
253
250 /* The rest of the output_* classes are for special styling of the different
254 /* The rest of the output_* classes are for special styling of the different
251 output types */
255 output types */
252
256
253 /* all text output has this class: */
257 /* all text output has this class: */
254 div.output_text {
258 div.output_text {
255 text-align: left;
259 text-align: left;
256 color: black;
260 color: black;
257 font-family: monospace;
261 font-family: monospace;
258 }
262 }
259
263
260 /* stdout/stderr are 'text' as well as 'stream', but pyout/pyerr are *not* streams */
264 /* stdout/stderr are 'text' as well as 'stream', but pyout/pyerr are *not* streams */
261 div.output_stream {
265 div.output_stream {
262 padding-top: 0.0em;
266 padding-top: 0.0em;
263 padding-bottom: 0.0em;
267 padding-bottom: 0.0em;
264 }
268 }
265 div.output_stdout {
269 div.output_stdout {
266 }
270 }
267 div.output_stderr {
271 div.output_stderr {
268 background: #fdd; /* very light red background for stderr */
272 background: #fdd; /* very light red background for stderr */
269 }
273 }
270
274
271 div.output_latex {
275 div.output_latex {
272 text-align: left;
276 text-align: left;
273 color: black;
277 color: black;
274 }
278 }
275
279
276 div.output_html {
280 div.output_html {
277 }
281 }
278
282
279 div.output_png {
283 div.output_png {
280 }
284 }
281
285
282 div.output_jpeg {
286 div.output_jpeg {
283 }
287 }
284
288
285 div.text_cell {
289 div.text_cell {
286 background-color: white;
290 background-color: white;
287 }
291 }
288
292
289 div.text_cell_input {
293 div.text_cell_input {
290 color: black;
294 color: black;
291 }
295 }
292
296
293 div.text_cell_render {
297 div.text_cell_render {
294 font-family: "Helvetica Neue", Arial, Helvetica, Geneva, sans-serif;
298 font-family: "Helvetica Neue", Arial, Helvetica, Geneva, sans-serif;
295 outline: none;
299 outline: none;
296 resize: none;
300 resize: none;
297 width: inherit;
301 width: inherit;
298 border-style: none;
302 border-style: none;
299 padding: 5px;
303 padding: 5px;
300 color: black;
304 color: black;
301 }
305 }
302
306
303 .CodeMirror {
307 .CodeMirror {
304 line-height: 1.231; /* Changed from 1em to our global default */
308 line-height: 1.231; /* Changed from 1em to our global default */
305 }
309 }
306
310
307 .CodeMirror-scroll {
311 .CodeMirror-scroll {
308 height: auto; /* Changed to auto to autogrow */
312 height: auto; /* Changed to auto to autogrow */
309 /* The CodeMirror docs are a bit fuzzy on if overflow-y should be hidden or visible.*/
313 /* The CodeMirror docs are a bit fuzzy on if overflow-y should be hidden or visible.*/
310 /* We have found that if it is visible, vertical scrollbars appear with font size changes.*/
314 /* We have found that if it is visible, vertical scrollbars appear with font size changes.*/
311 overflow-y: hidden;
315 overflow-y: hidden;
312 overflow-x: auto; /* Changed from auto to remove scrollbar */
316 overflow-x: auto; /* Changed from auto to remove scrollbar */
313 }
317 }
314
318
315 /* CSS font colors for translated ANSI colors. */
319 /* CSS font colors for translated ANSI colors. */
316
320
317
321
318 .ansiblack {color: black;}
322 .ansiblack {color: black;}
319 .ansired {color: darkred;}
323 .ansired {color: darkred;}
320 .ansigreen {color: darkgreen;}
324 .ansigreen {color: darkgreen;}
321 .ansiyellow {color: brown;}
325 .ansiyellow {color: brown;}
322 .ansiblue {color: darkblue;}
326 .ansiblue {color: darkblue;}
323 .ansipurple {color: darkviolet;}
327 .ansipurple {color: darkviolet;}
324 .ansicyan {color: steelblue;}
328 .ansicyan {color: steelblue;}
325 .ansigrey {color: grey;}
329 .ansigrey {color: grey;}
326 .ansibold {font-weight: bold;}
330 .ansibold {font-weight: bold;}
327
331
328 .completions , .tooltip{
332 .completions , .tooltip{
329 position: absolute;
333 position: absolute;
330 z-index: 10;
334 z-index: 10;
331 overflow: auto;
335 overflow: auto;
332 border: 1px solid black;
336 border: 1px solid black;
333 }
337 }
334
338
335 .completions select {
339 .completions select {
336 background: white;
340 background: white;
337 outline: none;
341 outline: none;
338 border: none;
342 border: none;
339 padding: 0px;
343 padding: 0px;
340 margin: 0px;
344 margin: 0px;
341 font-family: monospace;
345 font-family: monospace;
342 }
346 }
343
347
344 @-moz-keyframes fadeIn {
348 @-moz-keyframes fadeIn {
345 from {opacity:0;}
349 from {opacity:0;}
346 to {opacity:1;}
350 to {opacity:1;}
347 }
351 }
348
352
349 @-webkit-keyframes fadeIn {
353 @-webkit-keyframes fadeIn {
350 from {opacity:0;}
354 from {opacity:0;}
351 to {opacity:1;}
355 to {opacity:1;}
352 }
356 }
353
357
354 @keyframes fadeIn {
358 @keyframes fadeIn {
355 from {opacity:0;}
359 from {opacity:0;}
356 to {opacity:1;}
360 to {opacity:1;}
357 }
361 }
358
362
359
363
360 .tooltip{
364 .tooltip{
361 border-radius: 0px 10px 10px 10px;
365 border-radius: 0px 10px 10px 10px;
362 box-shadow: 3px 3px 5px #999;
366 box-shadow: 3px 3px 5px #999;
363 -webkit-animation: fadeIn 200ms;
367 -webkit-animation: fadeIn 200ms;
364 -moz-animation: fadeIn 200ms;
368 -moz-animation: fadeIn 200ms;
365 animation: fadeIn 200ms;
369 animation: fadeIn 200ms;
366 vertical-align: middle;
370 vertical-align: middle;
367 background: #FDFDD8;
371 background: #FDFDD8;
368 outline: none;
372 outline: none;
369 padding: 3px;
373 padding: 3px;
370 margin: 0px;
374 margin: 0px;
371 font-family: monospace;
375 font-family: monospace;
372 }
376 }
373
377
374 @media print {
378 @media print {
375 body { overflow: visible !important; }
379 body { overflow: visible !important; }
376 .ui-widget-content { border: 0px; }
380 .ui-widget-content { border: 0px; }
377 }
381 }
378
382
379 .shortcut_key {
383 .shortcut_key {
380 display: inline-block;
384 display: inline-block;
381 width: 13ex;
385 width: 13ex;
382 text-align: right;
386 text-align: right;
383 font-family: monospace;
387 font-family: monospace;
384 }
388 }
385
389
386 .shortcut_descr {
390 .shortcut_descr {
387 }
391 }
388
392
389 /* Word-wrap output correctly. This is the CSS3 spelling, though Firefox seems
393 /* Word-wrap output correctly. This is the CSS3 spelling, though Firefox seems
390 to not honor it correctly. Webkit browsers (Chrome, rekonq, Safari) do.
394 to not honor it correctly. Webkit browsers (Chrome, rekonq, Safari) do.
391 */
395 */
392 pre, code, kbd, samp { white-space: pre-wrap; }
396 pre, code, kbd, samp { white-space: pre-wrap; }
@@ -1,587 +1,600
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
13
14 var utils = IPython.utils;
14 var utils = IPython.utils;
15
15
16 var CodeCell = function (notebook) {
16 var CodeCell = function (notebook) {
17 this.code_mirror = null;
17 this.code_mirror = null;
18 this.input_prompt_number = ' ';
18 this.input_prompt_number = ' ';
19 this.is_completing = false;
19 this.is_completing = false;
20 this.completion_cursor = null;
20 this.completion_cursor = null;
21 this.outputs = [];
21 this.outputs = [];
22 this.collapsed = false;
22 this.collapsed = false;
23 IPython.Cell.apply(this, arguments);
23 IPython.Cell.apply(this, arguments);
24 };
24 };
25
25
26
26
27 CodeCell.prototype = new IPython.Cell();
27 CodeCell.prototype = new IPython.Cell();
28
28
29
29
30 CodeCell.prototype.create_element = function () {
30 CodeCell.prototype.create_element = function () {
31 var cell = $('<div></div>').addClass('cell border-box-sizing code_cell vbox');
31 var cell = $('<div></div>').addClass('cell border-box-sizing code_cell vbox');
32 cell.attr('tabindex','2');
32 cell.attr('tabindex','2');
33 var input = $('<div></div>').addClass('input hbox');
33 var input = $('<div></div>').addClass('input hbox');
34 input.append($('<div/>').addClass('prompt input_prompt'));
34 input.append($('<div/>').addClass('prompt input_prompt'));
35 var input_area = $('<div/>').addClass('input_area box-flex1');
35 var input_area = $('<div/>').addClass('input_area box-flex1');
36 this.code_mirror = CodeMirror(input_area.get(0), {
36 this.code_mirror = CodeMirror(input_area.get(0), {
37 indentUnit : 4,
37 indentUnit : 4,
38 mode: 'python',
38 mode: 'python',
39 theme: 'ipython',
39 theme: 'ipython',
40 readOnly: this.read_only,
40 readOnly: this.read_only,
41 onKeyEvent: $.proxy(this.handle_codemirror_keyevent,this)
41 onKeyEvent: $.proxy(this.handle_codemirror_keyevent,this)
42 });
42 });
43 input.append(input_area);
43 input.append(input_area);
44 var output = $('<div></div>').addClass('output vbox');
44 var output = $('<div></div>').addClass('output vbox');
45 cell.append(input).append(output);
45 cell.append(input).append(output);
46 this.element = cell;
46 this.element = cell;
47 this.collapse()
47 this.collapse()
48 };
48 };
49
49
50 //TODO, try to diminish the number of parameters.
50 //TODO, try to diminish the number of parameters.
51 CodeCell.prototype.request_tooltip_after_time = function (pre_cursor,time,that){
51 CodeCell.prototype.request_tooltip_after_time = function (pre_cursor,time,that){
52 if (pre_cursor === "" || pre_cursor === "(" ) {
52 if (pre_cursor === "" || pre_cursor === "(" ) {
53 // don't do anything if line beggin with '(' or is empty
53 // don't do anything if line beggin with '(' or is empty
54 } else {
54 } else {
55 // Will set a timer to request tooltip in `time`
55 // Will set a timer to request tooltip in `time`
56 that.tooltip_timeout = setTimeout(function(){
56 that.tooltip_timeout = setTimeout(function(){
57 IPython.notebook.request_tool_tip(that, pre_cursor)
57 IPython.notebook.request_tool_tip(that, pre_cursor)
58 },time);
58 },time);
59 }
59 }
60 };
60 };
61
61
62 CodeCell.prototype.handle_codemirror_keyevent = function (editor, event) {
62 CodeCell.prototype.handle_codemirror_keyevent = function (editor, event) {
63 // This method gets called in CodeMirror's onKeyDown/onKeyPress
63 // This method gets called in CodeMirror's onKeyDown/onKeyPress
64 // handlers and is used to provide custom key handling. Its return
64 // handlers and is used to provide custom key handling. Its return
65 // value is used to determine if CodeMirror should ignore the event:
65 // value is used to determine if CodeMirror should ignore the event:
66 // true = ignore, false = don't ignore.
66 // true = ignore, false = don't ignore.
67
67
68 // note that we are comparing and setting the time to wait at each key press.
68 // note that we are comparing and setting the time to wait at each key press.
69 // a better wqy might be to generate a new function on each time change and
69 // a better wqy might be to generate a new function on each time change and
70 // assign it to CodeCell.prototype.request_tooltip_after_time
70 // assign it to CodeCell.prototype.request_tooltip_after_time
71 tooltip_wait_time = this.notebook.time_before_tooltip;
71 tooltip_wait_time = this.notebook.time_before_tooltip;
72 tooltip_on_tab = this.notebook.tooltip_on_tab;
72 tooltip_on_tab = this.notebook.tooltip_on_tab;
73 var that = this;
73 var that = this;
74
74
75 // whatever key is pressed, first, cancel the tooltip request before
75 // whatever key is pressed, first, cancel the tooltip request before
76 // they are sent, and remove tooltip if any
76 // they are sent, and remove tooltip if any
77 if(event.type === 'keydown' && this.tooltip_timeout != null){
77 if(event.type === 'keydown' && this.tooltip_timeout != null){
78 CodeCell.prototype.remove_and_cancell_tooltip(that.tooltip_timeout);
78 CodeCell.prototype.remove_and_cancell_tooltip(that.tooltip_timeout);
79 that.tooltip_timeout=null;
79 that.tooltip_timeout=null;
80 }
80 }
81
81
82 if (event.keyCode === 13 && (event.shiftKey || event.ctrlKey)) {
82 if (event.keyCode === 13 && (event.shiftKey || event.ctrlKey)) {
83 // Always ignore shift-enter in CodeMirror as we handle it.
83 // Always ignore shift-enter in CodeMirror as we handle it.
84 return true;
84 return true;
85 }else if (event.keyCode === 53 && event.type === 'keydown' && tooltip_wait_time >= 0) {
85 }else if (event.keyCode === 53 && event.type === 'keydown' && tooltip_wait_time >= 0) {
86 // Pressing '(' , request tooltip, don't forget to reappend it
86 // Pressing '(' , request tooltip, don't forget to reappend it
87 var cursor = editor.getCursor();
87 var cursor = editor.getCursor();
88 var pre_cursor = editor.getRange({line:cursor.line,ch:0},cursor).trim()+'(';
88 var pre_cursor = editor.getRange({line:cursor.line,ch:0},cursor).trim()+'(';
89 CodeCell.prototype.request_tooltip_after_time(pre_cursor,tooltip_wait_time,that);
89 CodeCell.prototype.request_tooltip_after_time(pre_cursor,tooltip_wait_time,that);
90 } else if (event.keyCode === 9 && event.type == 'keydown') {
90 } else if (event.keyCode === 9 && event.type == 'keydown') {
91 // Tab completion.
91 // Tab completion.
92 var cur = editor.getCursor();
92 var cur = editor.getCursor();
93 //Do not trim here because of tooltip
93 //Do not trim here because of tooltip
94 var pre_cursor = editor.getRange({line:cur.line,ch:0},cur);
94 var pre_cursor = editor.getRange({line:cur.line,ch:0},cur);
95 if (pre_cursor.trim() === "") {
95 if (pre_cursor.trim() === "") {
96 // Don't autocomplete if the part of the line before the cursor
96 // Don't autocomplete if the part of the line before the cursor
97 // is empty. In this case, let CodeMirror handle indentation.
97 // is empty. In this case, let CodeMirror handle indentation.
98 return false;
98 return false;
99 } else if ((pre_cursor.substr(-1) === "("|| pre_cursor.substr(-1) === " ") && tooltip_on_tab ) {
99 } else if ((pre_cursor.substr(-1) === "("|| pre_cursor.substr(-1) === " ") && tooltip_on_tab ) {
100 CodeCell.prototype.request_tooltip_after_time(pre_cursor,0,that);
100 CodeCell.prototype.request_tooltip_after_time(pre_cursor,0,that);
101 } else {
101 } else {
102 pre_cursor.trim();
102 pre_cursor.trim();
103 // Autocomplete the current line.
103 // Autocomplete the current line.
104 event.stop();
104 event.stop();
105 var line = editor.getLine(cur.line);
105 var line = editor.getLine(cur.line);
106 this.is_completing = true;
106 this.is_completing = true;
107 this.completion_cursor = cur;
107 this.completion_cursor = cur;
108 IPython.notebook.complete_cell(this, line, cur.ch);
108 IPython.notebook.complete_cell(this, line, cur.ch);
109 return true;
109 return true;
110 }
110 }
111 } else if (event.keyCode === 8 && event.type == 'keydown') {
111 } else if (event.keyCode === 8 && event.type == 'keydown') {
112 // If backspace and the line ends with 4 spaces, remove them.
112 // If backspace and the line ends with 4 spaces, remove them.
113 var cur = editor.getCursor();
113 var cur = editor.getCursor();
114 var line = editor.getLine(cur.line);
114 var line = editor.getLine(cur.line);
115 var ending = line.slice(-4);
115 var ending = line.slice(-4);
116 if (ending === ' ') {
116 if (ending === ' ') {
117 editor.replaceRange('',
117 editor.replaceRange('',
118 {line: cur.line, ch: cur.ch-4},
118 {line: cur.line, ch: cur.ch-4},
119 {line: cur.line, ch: cur.ch}
119 {line: cur.line, ch: cur.ch}
120 );
120 );
121 event.stop();
121 event.stop();
122 return true;
122 return true;
123 } else {
123 } else {
124 return false;
124 return false;
125 };
125 };
126 } else if (event.keyCode === 76 && event.ctrlKey && event.shiftKey
126 } else if (event.keyCode === 76 && event.ctrlKey && event.shiftKey
127 && event.type == 'keydown') {
127 && event.type == 'keydown') {
128 // toggle line numbers with Ctrl-Shift-L
128 // toggle line numbers with Ctrl-Shift-L
129 this.toggle_line_numbers();
129 this.toggle_line_numbers();
130 }
130 }
131 else {
131 else {
132 // keypress/keyup also trigger on TAB press, and we don't want to
132 // keypress/keyup also trigger on TAB press, and we don't want to
133 // use those to disable tab completion.
133 // use those to disable tab completion.
134 if (this.is_completing && event.keyCode !== 9) {
134 if (this.is_completing && event.keyCode !== 9) {
135 var ed_cur = editor.getCursor();
135 var ed_cur = editor.getCursor();
136 var cc_cur = this.completion_cursor;
136 var cc_cur = this.completion_cursor;
137 if (ed_cur.line !== cc_cur.line || ed_cur.ch !== cc_cur.ch) {
137 if (ed_cur.line !== cc_cur.line || ed_cur.ch !== cc_cur.ch) {
138 this.is_completing = false;
138 this.is_completing = false;
139 this.completion_cursor = null;
139 this.completion_cursor = null;
140 };
140 };
141 };
141 };
142 return false;
142 return false;
143 };
143 };
144 };
144 };
145
145
146 CodeCell.prototype.remove_and_cancell_tooltip = function(timeout)
146 CodeCell.prototype.remove_and_cancell_tooltip = function(timeout)
147 {
147 {
148 // note that we don't handle closing directly inside the calltip
148 // note that we don't handle closing directly inside the calltip
149 // as in the completer, because it is not focusable, so won't
149 // as in the completer, because it is not focusable, so won't
150 // get the event.
150 // get the event.
151 clearTimeout(timeout);
151 clearTimeout(timeout);
152 $('#tooltip').remove();
152 $('#tooltip').remove();
153 }
153 }
154
154
155 CodeCell.prototype.finish_tooltip = function (defstring,docstring) {
155 CodeCell.prototype.finish_tooltip = function (defstring,docstring) {
156 shortened = function(string){
156 shortened = function(string){
157 if(string.length > 200){
157 if(string.length > 200){
158 return string.trim().substring(0,197)+'...';
158 return string.trim().substring(0,197)+'...';
159 } else { return string.trim() }
159 } else { return string.trim() }
160 }
160 }
161
161
162 var that = this;
162 var that = this;
163 var tooltip = $('<div/>').attr('id', 'tooltip').addClass('tooltip');
163 var tooltip = $('<div/>').attr('id', 'tooltip').addClass('tooltip');
164 if(defstring){
164 if(defstring){
165 defstring_html= $('<pre/>').html(utils.fixConsole(defstring));
165 defstring_html= $('<pre/>').html(utils.fixConsole(defstring));
166 tooltip.append(defstring_html);
166 tooltip.append(defstring_html);
167 }
167 }
168 tooltip.append($('<pre/>').html(utils.fixConsole(shortened(docstring))));
168 tooltip.append($('<pre/>').html(utils.fixConsole(shortened(docstring))));
169 var pos = this.code_mirror.cursorCoords();
169 var pos = this.code_mirror.cursorCoords();
170 tooltip.css('left',pos.x+'px');
170 tooltip.css('left',pos.x+'px');
171 tooltip.css('top',pos.yBot+'px');
171 tooltip.css('top',pos.yBot+'px');
172 $('body').append(tooltip);
172 $('body').append(tooltip);
173
173
174 // issues with cross-closing if multiple tooltip in less than 5sec
174 // issues with cross-closing if multiple tooltip in less than 5sec
175 // keep it comented for now
175 // keep it comented for now
176 // setTimeout(CodeCell.prototype.remove_and_cancell_tooltip, 5000);
176 // setTimeout(CodeCell.prototype.remove_and_cancell_tooltip, 5000);
177 };
177 };
178
178
179
179
180 CodeCell.prototype.finish_completing = function (matched_text, matches) {
180 CodeCell.prototype.finish_completing = function (matched_text, matches) {
181 // console.log("Got matches", matched_text, matches);
181 // console.log("Got matches", matched_text, matches);
182 var newm = new Array();
183 if(this.notebook.smart_completer)
184 {
185 kwargs = new Array();
186 other = new Array();
187 for(var i=0;i<matches.length; ++i){
188 if(matches[i].substr(-1) === '='){
189 kwargs.push(matches[i]);
190 }else{other.push(matches[i]);}
191 }
192 newm = kwargs.concat(other);
193 matches=newm;
194 }
182 if (!this.is_completing || matches.length === 0) {return;}
195 if (!this.is_completing || matches.length === 0) {return;}
183
196
184 var that = this;
197 var that = this;
185 var cur = this.completion_cursor;
198 var cur = this.completion_cursor;
186
199
187 var insert = function (selected_text) {
200 var insert = function (selected_text) {
188 that.code_mirror.replaceRange(
201 that.code_mirror.replaceRange(
189 selected_text,
202 selected_text,
190 {line: cur.line, ch: (cur.ch-matched_text.length)},
203 {line: cur.line, ch: (cur.ch-matched_text.length)},
191 {line: cur.line, ch: cur.ch}
204 {line: cur.line, ch: cur.ch}
192 );
205 );
193 };
206 };
194
207
195 if (matches.length === 1) {
208 if (matches.length === 1) {
196 insert(matches[0]);
209 insert(matches[0]);
197 setTimeout(function(){that.code_mirror.focus();}, 50);
210 setTimeout(function(){that.code_mirror.focus();}, 50);
198 return;
211 return;
199 };
212 };
200
213
201 var complete = $('<div/>').addClass('completions');
214 var complete = $('<div/>').addClass('completions');
202 var select = $('<select/>').attr('multiple','true');
215 var select = $('<select/>').attr('multiple','true');
203 for (var i=0; i<matches.length; ++i) {
216 for (var i=0; i<matches.length; ++i) {
204 select.append($('<option/>').text(matches[i]));
217 select.append($('<option/>').text(matches[i]));
205 }
218 }
206 select.children().first().attr('selected','true');
219 select.children().first().attr('selected','true');
207 select.attr('size',Math.min(10,matches.length));
220 select.attr('size',Math.min(10,matches.length));
208 var pos = this.code_mirror.cursorCoords();
221 var pos = this.code_mirror.cursorCoords();
209 complete.css('left',pos.x+'px');
222 complete.css('left',pos.x+'px');
210 complete.css('top',pos.yBot+'px');
223 complete.css('top',pos.yBot+'px');
211 complete.append(select);
224 complete.append(select);
212
225
213 $('body').append(complete);
226 $('body').append(complete);
214 var done = false;
227 var done = false;
215
228
216 var close = function () {
229 var close = function () {
217 if (done) return;
230 if (done) return;
218 done = true;
231 done = true;
219 complete.remove();
232 complete.remove();
220 that.is_completing = false;
233 that.is_completing = false;
221 that.completion_cursor = null;
234 that.completion_cursor = null;
222 };
235 };
223
236
224 var pick = function () {
237 var pick = function () {
225 insert(select.val()[0]);
238 insert(select.val()[0]);
226 close();
239 close();
227 setTimeout(function(){that.code_mirror.focus();}, 50);
240 setTimeout(function(){that.code_mirror.focus();}, 50);
228 };
241 };
229
242
230 select.blur(close);
243 select.blur(close);
231 select.keydown(function (event) {
244 select.keydown(function (event) {
232 var code = event.which;
245 var code = event.which;
233 if (code === 13 || code === 32) {
246 if (code === 13 || code === 32) {
234 // Pressing SPACE or ENTER will cause a pick
247 // Pressing SPACE or ENTER will cause a pick
235 event.stopPropagation();
248 event.stopPropagation();
236 event.preventDefault();
249 event.preventDefault();
237 pick();
250 pick();
238 } else if (code === 38 || code === 40) {
251 } else if (code === 38 || code === 40) {
239 // We don't want the document keydown handler to handle UP/DOWN,
252 // We don't want the document keydown handler to handle UP/DOWN,
240 // but we want the default action.
253 // but we want the default action.
241 event.stopPropagation();
254 event.stopPropagation();
242 } else {
255 } else {
243 // All other key presses exit completion.
256 // All other key presses exit completion.
244 event.stopPropagation();
257 event.stopPropagation();
245 event.preventDefault();
258 event.preventDefault();
246 close();
259 close();
247 that.code_mirror.focus();
260 that.code_mirror.focus();
248 }
261 }
249 });
262 });
250 // Double click also causes a pick.
263 // Double click also causes a pick.
251 select.dblclick(pick);
264 select.dblclick(pick);
252 select.focus();
265 select.focus();
253 };
266 };
254
267
255 CodeCell.prototype.toggle_line_numbers = function () {
268 CodeCell.prototype.toggle_line_numbers = function () {
256 if (this.code_mirror.getOption('lineNumbers') == false) {
269 if (this.code_mirror.getOption('lineNumbers') == false) {
257 this.code_mirror.setOption('lineNumbers', true);
270 this.code_mirror.setOption('lineNumbers', true);
258 } else {
271 } else {
259 this.code_mirror.setOption('lineNumbers', false);
272 this.code_mirror.setOption('lineNumbers', false);
260 }
273 }
261 this.code_mirror.refresh()
274 this.code_mirror.refresh()
262 };
275 };
263
276
264 CodeCell.prototype.select = function () {
277 CodeCell.prototype.select = function () {
265 IPython.Cell.prototype.select.apply(this);
278 IPython.Cell.prototype.select.apply(this);
266 // Todo: this dance is needed because as of CodeMirror 2.12, focus is
279 // Todo: this dance is needed because as of CodeMirror 2.12, focus is
267 // not causing the cursor to blink if the editor is empty initially.
280 // not causing the cursor to blink if the editor is empty initially.
268 // While this seems to fix the issue, this should be fixed
281 // While this seems to fix the issue, this should be fixed
269 // in CodeMirror proper.
282 // in CodeMirror proper.
270 var s = this.code_mirror.getValue();
283 var s = this.code_mirror.getValue();
271 this.code_mirror.focus();
284 this.code_mirror.focus();
272 if (s === '') this.code_mirror.setValue('');
285 if (s === '') this.code_mirror.setValue('');
273 };
286 };
274
287
275
288
276 CodeCell.prototype.select_all = function () {
289 CodeCell.prototype.select_all = function () {
277 var start = {line: 0, ch: 0};
290 var start = {line: 0, ch: 0};
278 var nlines = this.code_mirror.lineCount();
291 var nlines = this.code_mirror.lineCount();
279 var last_line = this.code_mirror.getLine(nlines-1);
292 var last_line = this.code_mirror.getLine(nlines-1);
280 var end = {line: nlines-1, ch: last_line.length};
293 var end = {line: nlines-1, ch: last_line.length};
281 this.code_mirror.setSelection(start, end);
294 this.code_mirror.setSelection(start, end);
282 };
295 };
283
296
284
297
285 CodeCell.prototype.append_output = function (json) {
298 CodeCell.prototype.append_output = function (json) {
286 this.expand();
299 this.expand();
287 if (json.output_type === 'pyout') {
300 if (json.output_type === 'pyout') {
288 this.append_pyout(json);
301 this.append_pyout(json);
289 } else if (json.output_type === 'pyerr') {
302 } else if (json.output_type === 'pyerr') {
290 this.append_pyerr(json);
303 this.append_pyerr(json);
291 } else if (json.output_type === 'display_data') {
304 } else if (json.output_type === 'display_data') {
292 this.append_display_data(json);
305 this.append_display_data(json);
293 } else if (json.output_type === 'stream') {
306 } else if (json.output_type === 'stream') {
294 this.append_stream(json);
307 this.append_stream(json);
295 };
308 };
296 this.outputs.push(json);
309 this.outputs.push(json);
297 };
310 };
298
311
299
312
300 CodeCell.prototype.create_output_area = function () {
313 CodeCell.prototype.create_output_area = function () {
301 var oa = $("<div/>").addClass("hbox output_area");
314 var oa = $("<div/>").addClass("hbox output_area");
302 oa.append($('<div/>').addClass('prompt'));
315 oa.append($('<div/>').addClass('prompt'));
303 return oa;
316 return oa;
304 };
317 };
305
318
306
319
307 CodeCell.prototype.append_pyout = function (json) {
320 CodeCell.prototype.append_pyout = function (json) {
308 n = json.prompt_number || ' ';
321 n = json.prompt_number || ' ';
309 var toinsert = this.create_output_area();
322 var toinsert = this.create_output_area();
310 toinsert.find('div.prompt').addClass('output_prompt').html('Out[' + n + ']:');
323 toinsert.find('div.prompt').addClass('output_prompt').html('Out[' + n + ']:');
311 this.append_mime_type(json, toinsert);
324 this.append_mime_type(json, toinsert);
312 this.element.find('div.output').append(toinsert);
325 this.element.find('div.output').append(toinsert);
313 // If we just output latex, typeset it.
326 // If we just output latex, typeset it.
314 if ((json.latex !== undefined) || (json.html !== undefined)) {
327 if ((json.latex !== undefined) || (json.html !== undefined)) {
315 MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
328 MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
316 };
329 };
317 };
330 };
318
331
319
332
320 CodeCell.prototype.append_pyerr = function (json) {
333 CodeCell.prototype.append_pyerr = function (json) {
321 var tb = json.traceback;
334 var tb = json.traceback;
322 if (tb !== undefined && tb.length > 0) {
335 if (tb !== undefined && tb.length > 0) {
323 var s = '';
336 var s = '';
324 var len = tb.length;
337 var len = tb.length;
325 for (var i=0; i<len; i++) {
338 for (var i=0; i<len; i++) {
326 s = s + tb[i] + '\n';
339 s = s + tb[i] + '\n';
327 }
340 }
328 s = s + '\n';
341 s = s + '\n';
329 var toinsert = this.create_output_area();
342 var toinsert = this.create_output_area();
330 this.append_text(s, toinsert);
343 this.append_text(s, toinsert);
331 this.element.find('div.output').append(toinsert);
344 this.element.find('div.output').append(toinsert);
332 };
345 };
333 };
346 };
334
347
335
348
336 CodeCell.prototype.append_stream = function (json) {
349 CodeCell.prototype.append_stream = function (json) {
337 // temporary fix: if stream undefined (json file written prior to this patch),
350 // temporary fix: if stream undefined (json file written prior to this patch),
338 // default to most likely stdout:
351 // default to most likely stdout:
339 if (json.stream == undefined){
352 if (json.stream == undefined){
340 json.stream = 'stdout';
353 json.stream = 'stdout';
341 }
354 }
342 var subclass = "output_"+json.stream;
355 var subclass = "output_"+json.stream;
343 if (this.outputs.length > 0){
356 if (this.outputs.length > 0){
344 // have at least one output to consider
357 // have at least one output to consider
345 var last = this.outputs[this.outputs.length-1];
358 var last = this.outputs[this.outputs.length-1];
346 if (last.output_type == 'stream' && json.stream == last.stream){
359 if (last.output_type == 'stream' && json.stream == last.stream){
347 // latest output was in the same stream,
360 // latest output was in the same stream,
348 // so append directly into its pre tag
361 // so append directly into its pre tag
349 this.element.find('div.'+subclass).last().find('pre').append(json.text);
362 this.element.find('div.'+subclass).last().find('pre').append(json.text);
350 return;
363 return;
351 }
364 }
352 }
365 }
353
366
354 // If we got here, attach a new div
367 // If we got here, attach a new div
355 var toinsert = this.create_output_area();
368 var toinsert = this.create_output_area();
356 this.append_text(json.text, toinsert, "output_stream "+subclass);
369 this.append_text(json.text, toinsert, "output_stream "+subclass);
357 this.element.find('div.output').append(toinsert);
370 this.element.find('div.output').append(toinsert);
358 };
371 };
359
372
360
373
361 CodeCell.prototype.append_display_data = function (json) {
374 CodeCell.prototype.append_display_data = function (json) {
362 var toinsert = this.create_output_area();
375 var toinsert = this.create_output_area();
363 this.append_mime_type(json, toinsert)
376 this.append_mime_type(json, toinsert)
364 this.element.find('div.output').append(toinsert);
377 this.element.find('div.output').append(toinsert);
365 // If we just output latex, typeset it.
378 // If we just output latex, typeset it.
366 if ( (json.latex !== undefined) || (json.html !== undefined) ) {
379 if ( (json.latex !== undefined) || (json.html !== undefined) ) {
367 MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
380 MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
368 };
381 };
369 };
382 };
370
383
371
384
372 CodeCell.prototype.append_mime_type = function (json, element) {
385 CodeCell.prototype.append_mime_type = function (json, element) {
373 if (json.html !== undefined) {
386 if (json.html !== undefined) {
374 this.append_html(json.html, element);
387 this.append_html(json.html, element);
375 } else if (json.latex !== undefined) {
388 } else if (json.latex !== undefined) {
376 this.append_latex(json.latex, element);
389 this.append_latex(json.latex, element);
377 } else if (json.svg !== undefined) {
390 } else if (json.svg !== undefined) {
378 this.append_svg(json.svg, element);
391 this.append_svg(json.svg, element);
379 } else if (json.png !== undefined) {
392 } else if (json.png !== undefined) {
380 this.append_png(json.png, element);
393 this.append_png(json.png, element);
381 } else if (json.jpeg !== undefined) {
394 } else if (json.jpeg !== undefined) {
382 this.append_jpeg(json.jpeg, element);
395 this.append_jpeg(json.jpeg, element);
383 } else if (json.text !== undefined) {
396 } else if (json.text !== undefined) {
384 this.append_text(json.text, element);
397 this.append_text(json.text, element);
385 };
398 };
386 };
399 };
387
400
388
401
389 CodeCell.prototype.append_html = function (html, element) {
402 CodeCell.prototype.append_html = function (html, element) {
390 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_html rendered_html");
403 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_html rendered_html");
391 toinsert.append(html);
404 toinsert.append(html);
392 element.append(toinsert);
405 element.append(toinsert);
393 }
406 }
394
407
395
408
396 CodeCell.prototype.append_text = function (data, element, extra_class) {
409 CodeCell.prototype.append_text = function (data, element, extra_class) {
397 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_text");
410 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_text");
398 if (extra_class){
411 if (extra_class){
399 toinsert.addClass(extra_class);
412 toinsert.addClass(extra_class);
400 }
413 }
401 toinsert.append($("<pre/>").html(data));
414 toinsert.append($("<pre/>").html(data));
402 element.append(toinsert);
415 element.append(toinsert);
403 };
416 };
404
417
405
418
406 CodeCell.prototype.append_svg = function (svg, element) {
419 CodeCell.prototype.append_svg = function (svg, element) {
407 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_svg");
420 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_svg");
408 toinsert.append(svg);
421 toinsert.append(svg);
409 element.append(toinsert);
422 element.append(toinsert);
410 };
423 };
411
424
412
425
413 CodeCell.prototype.append_png = function (png, element) {
426 CodeCell.prototype.append_png = function (png, element) {
414 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_png");
427 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_png");
415 toinsert.append($("<img/>").attr('src','data:image/png;base64,'+png));
428 toinsert.append($("<img/>").attr('src','data:image/png;base64,'+png));
416 element.append(toinsert);
429 element.append(toinsert);
417 };
430 };
418
431
419
432
420 CodeCell.prototype.append_jpeg = function (jpeg, element) {
433 CodeCell.prototype.append_jpeg = function (jpeg, element) {
421 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_jpeg");
434 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_jpeg");
422 toinsert.append($("<img/>").attr('src','data:image/jpeg;base64,'+jpeg));
435 toinsert.append($("<img/>").attr('src','data:image/jpeg;base64,'+jpeg));
423 element.append(toinsert);
436 element.append(toinsert);
424 };
437 };
425
438
426
439
427 CodeCell.prototype.append_latex = function (latex, element) {
440 CodeCell.prototype.append_latex = function (latex, element) {
428 // This method cannot do the typesetting because the latex first has to
441 // This method cannot do the typesetting because the latex first has to
429 // be on the page.
442 // be on the page.
430 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_latex");
443 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_latex");
431 toinsert.append(latex);
444 toinsert.append(latex);
432 element.append(toinsert);
445 element.append(toinsert);
433 }
446 }
434
447
435
448
436 CodeCell.prototype.clear_output = function (stdout, stderr, other) {
449 CodeCell.prototype.clear_output = function (stdout, stderr, other) {
437 var output_div = this.element.find("div.output");
450 var output_div = this.element.find("div.output");
438 if (stdout && stderr && other){
451 if (stdout && stderr && other){
439 // clear all, no need for logic
452 // clear all, no need for logic
440 output_div.html("");
453 output_div.html("");
441 this.outputs = [];
454 this.outputs = [];
442 return;
455 return;
443 }
456 }
444 // remove html output
457 // remove html output
445 // each output_subarea that has an identifying class is in an output_area
458 // each output_subarea that has an identifying class is in an output_area
446 // which is the element to be removed.
459 // which is the element to be removed.
447 if (stdout){
460 if (stdout){
448 output_div.find("div.output_stdout").parent().remove();
461 output_div.find("div.output_stdout").parent().remove();
449 }
462 }
450 if (stderr){
463 if (stderr){
451 output_div.find("div.output_stderr").parent().remove();
464 output_div.find("div.output_stderr").parent().remove();
452 }
465 }
453 if (other){
466 if (other){
454 output_div.find("div.output_subarea").not("div.output_stderr").not("div.output_stdout").parent().remove();
467 output_div.find("div.output_subarea").not("div.output_stderr").not("div.output_stdout").parent().remove();
455 }
468 }
456
469
457 // remove cleared outputs from JSON list:
470 // remove cleared outputs from JSON list:
458 for (var i = this.outputs.length - 1; i >= 0; i--){
471 for (var i = this.outputs.length - 1; i >= 0; i--){
459 var out = this.outputs[i];
472 var out = this.outputs[i];
460 var output_type = out.output_type;
473 var output_type = out.output_type;
461 if (output_type == "display_data" && other){
474 if (output_type == "display_data" && other){
462 this.outputs.splice(i,1);
475 this.outputs.splice(i,1);
463 }else if (output_type == "stream"){
476 }else if (output_type == "stream"){
464 if (stdout && out.stream == "stdout"){
477 if (stdout && out.stream == "stdout"){
465 this.outputs.splice(i,1);
478 this.outputs.splice(i,1);
466 }else if (stderr && out.stream == "stderr"){
479 }else if (stderr && out.stream == "stderr"){
467 this.outputs.splice(i,1);
480 this.outputs.splice(i,1);
468 }
481 }
469 }
482 }
470 }
483 }
471 };
484 };
472
485
473
486
474 CodeCell.prototype.clear_input = function () {
487 CodeCell.prototype.clear_input = function () {
475 this.code_mirror.setValue('');
488 this.code_mirror.setValue('');
476 };
489 };
477
490
478
491
479 CodeCell.prototype.collapse = function () {
492 CodeCell.prototype.collapse = function () {
480 if (!this.collapsed) {
493 if (!this.collapsed) {
481 this.element.find('div.output').hide();
494 this.element.find('div.output').hide();
482 this.collapsed = true;
495 this.collapsed = true;
483 };
496 };
484 };
497 };
485
498
486
499
487 CodeCell.prototype.expand = function () {
500 CodeCell.prototype.expand = function () {
488 if (this.collapsed) {
501 if (this.collapsed) {
489 this.element.find('div.output').show();
502 this.element.find('div.output').show();
490 this.collapsed = false;
503 this.collapsed = false;
491 };
504 };
492 };
505 };
493
506
494
507
495 CodeCell.prototype.toggle_output = function () {
508 CodeCell.prototype.toggle_output = function () {
496 if (this.collapsed) {
509 if (this.collapsed) {
497 this.expand();
510 this.expand();
498 } else {
511 } else {
499 this.collapse();
512 this.collapse();
500 };
513 };
501 };
514 };
502
515
503 CodeCell.prototype.set_input_prompt = function (number) {
516 CodeCell.prototype.set_input_prompt = function (number) {
504 var n = number || ' ';
517 var n = number || ' ';
505 this.input_prompt_number = n
518 this.input_prompt_number = n
506 this.element.find('div.input_prompt').html('In&nbsp;[' + n + ']:');
519 this.element.find('div.input_prompt').html('In&nbsp;[' + n + ']:');
507 };
520 };
508
521
509
522
510 CodeCell.prototype.get_code = function () {
523 CodeCell.prototype.get_code = function () {
511 return this.code_mirror.getValue();
524 return this.code_mirror.getValue();
512 };
525 };
513
526
514
527
515 CodeCell.prototype.set_code = function (code) {
528 CodeCell.prototype.set_code = function (code) {
516 return this.code_mirror.setValue(code);
529 return this.code_mirror.setValue(code);
517 };
530 };
518
531
519
532
520 CodeCell.prototype.at_top = function () {
533 CodeCell.prototype.at_top = function () {
521 var cursor = this.code_mirror.getCursor();
534 var cursor = this.code_mirror.getCursor();
522 if (cursor.line === 0) {
535 if (cursor.line === 0) {
523 return true;
536 return true;
524 } else {
537 } else {
525 return false;
538 return false;
526 }
539 }
527 };
540 };
528
541
529
542
530 CodeCell.prototype.at_bottom = function () {
543 CodeCell.prototype.at_bottom = function () {
531 var cursor = this.code_mirror.getCursor();
544 var cursor = this.code_mirror.getCursor();
532 if (cursor.line === (this.code_mirror.lineCount()-1)) {
545 if (cursor.line === (this.code_mirror.lineCount()-1)) {
533 return true;
546 return true;
534 } else {
547 } else {
535 return false;
548 return false;
536 }
549 }
537 };
550 };
538
551
539
552
540 CodeCell.prototype.fromJSON = function (data) {
553 CodeCell.prototype.fromJSON = function (data) {
541 console.log('Import from JSON:', data);
554 console.log('Import from JSON:', data);
542 if (data.cell_type === 'code') {
555 if (data.cell_type === 'code') {
543 if (data.input !== undefined) {
556 if (data.input !== undefined) {
544 this.set_code(data.input);
557 this.set_code(data.input);
545 }
558 }
546 if (data.prompt_number !== undefined) {
559 if (data.prompt_number !== undefined) {
547 this.set_input_prompt(data.prompt_number);
560 this.set_input_prompt(data.prompt_number);
548 } else {
561 } else {
549 this.set_input_prompt();
562 this.set_input_prompt();
550 };
563 };
551 var len = data.outputs.length;
564 var len = data.outputs.length;
552 for (var i=0; i<len; i++) {
565 for (var i=0; i<len; i++) {
553 this.append_output(data.outputs[i]);
566 this.append_output(data.outputs[i]);
554 };
567 };
555 if (data.collapsed !== undefined) {
568 if (data.collapsed !== undefined) {
556 if (data.collapsed) {
569 if (data.collapsed) {
557 this.collapse();
570 this.collapse();
558 };
571 };
559 };
572 };
560 };
573 };
561 };
574 };
562
575
563
576
564 CodeCell.prototype.toJSON = function () {
577 CodeCell.prototype.toJSON = function () {
565 var data = {};
578 var data = {};
566 data.input = this.get_code();
579 data.input = this.get_code();
567 data.cell_type = 'code';
580 data.cell_type = 'code';
568 if (this.input_prompt_number !== ' ') {
581 if (this.input_prompt_number !== ' ') {
569 data.prompt_number = this.input_prompt_number
582 data.prompt_number = this.input_prompt_number
570 };
583 };
571 var outputs = [];
584 var outputs = [];
572 var len = this.outputs.length;
585 var len = this.outputs.length;
573 for (var i=0; i<len; i++) {
586 for (var i=0; i<len; i++) {
574 outputs[i] = this.outputs[i];
587 outputs[i] = this.outputs[i];
575 };
588 };
576 data.outputs = outputs;
589 data.outputs = outputs;
577 data.language = 'python';
590 data.language = 'python';
578 data.collapsed = this.collapsed;
591 data.collapsed = this.collapsed;
579 // console.log('Export to JSON:',data);
592 // console.log('Export to JSON:',data);
580 return data;
593 return data;
581 };
594 };
582
595
583
596
584 IPython.CodeCell = CodeCell;
597 IPython.CodeCell = CodeCell;
585
598
586 return IPython;
599 return IPython;
587 }(IPython));
600 }(IPython));
@@ -1,1062 +1,1068
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
15
16 var Notebook = function (selector) {
16 var Notebook = function (selector) {
17 this.read_only = IPython.read_only;
17 this.read_only = IPython.read_only;
18 this.element = $(selector);
18 this.element = $(selector);
19 this.element.scroll();
19 this.element.scroll();
20 this.element.data("notebook", this);
20 this.element.data("notebook", this);
21 this.next_prompt_number = 1;
21 this.next_prompt_number = 1;
22 this.kernel = null;
22 this.kernel = null;
23 this.dirty = false;
23 this.dirty = false;
24 this.msg_cell_map = {};
24 this.msg_cell_map = {};
25 this.metadata = {};
25 this.metadata = {};
26 this.control_key_active = false;
26 this.control_key_active = false;
27 this.style();
27 this.style();
28 this.create_elements();
28 this.create_elements();
29 this.bind_events();
29 this.bind_events();
30 this.set_tooltipontab(true);
30 this.set_tooltipontab(true);
31 this.set_smartcompleter(true);
31 this.set_timebeforetooltip(1200);
32 this.set_timebeforetooltip(1200);
32 };
33 };
33
34
34
35
35 Notebook.prototype.style = function () {
36 Notebook.prototype.style = function () {
36 $('div#notebook').addClass('border-box-sizing');
37 $('div#notebook').addClass('border-box-sizing');
37 };
38 };
38
39
39
40
40 Notebook.prototype.create_elements = function () {
41 Notebook.prototype.create_elements = function () {
41 // We add this end_space div to the end of the notebook div to:
42 // We add this end_space div to the end of the notebook div to:
42 // i) provide a margin between the last cell and the end of the notebook
43 // i) provide a margin between the last cell and the end of the notebook
43 // ii) to prevent the div from scrolling up when the last cell is being
44 // ii) to prevent the div from scrolling up when the last cell is being
44 // edited, but is too low on the page, which browsers will do automatically.
45 // edited, but is too low on the page, which browsers will do automatically.
45 var that = this;
46 var that = this;
46 var end_space = $('<div class="end_space"></div>').height(150);
47 var end_space = $('<div class="end_space"></div>').height(150);
47 end_space.dblclick(function (e) {
48 end_space.dblclick(function (e) {
48 if (that.read_only) return;
49 if (that.read_only) return;
49 var ncells = that.ncells();
50 var ncells = that.ncells();
50 that.insert_code_cell_below(ncells-1);
51 that.insert_code_cell_below(ncells-1);
51 });
52 });
52 this.element.append(end_space);
53 this.element.append(end_space);
53 $('div#notebook').addClass('border-box-sizing');
54 $('div#notebook').addClass('border-box-sizing');
54 };
55 };
55
56
56
57
57 Notebook.prototype.bind_events = function () {
58 Notebook.prototype.bind_events = function () {
58 var that = this;
59 var that = this;
59 $(document).keydown(function (event) {
60 $(document).keydown(function (event) {
60 // console.log(event);
61 // console.log(event);
61 if (that.read_only) return;
62 if (that.read_only) return;
62 if (event.which === 27) {
63 if (event.which === 27) {
63 // Intercept escape at highest level to avoid closing
64 // Intercept escape at highest level to avoid closing
64 // websocket connection with firefox
65 // websocket connection with firefox
65 event.preventDefault();
66 event.preventDefault();
66 }
67 }
67 if (event.which === 38) {
68 if (event.which === 38) {
68 var cell = that.selected_cell();
69 var cell = that.selected_cell();
69 if (cell.at_top()) {
70 if (cell.at_top()) {
70 event.preventDefault();
71 event.preventDefault();
71 that.select_prev();
72 that.select_prev();
72 };
73 };
73 } else if (event.which === 40) {
74 } else if (event.which === 40) {
74 var cell = that.selected_cell();
75 var cell = that.selected_cell();
75 if (cell.at_bottom()) {
76 if (cell.at_bottom()) {
76 event.preventDefault();
77 event.preventDefault();
77 that.select_next();
78 that.select_next();
78 };
79 };
79 } else if (event.which === 13 && event.shiftKey) {
80 } else if (event.which === 13 && event.shiftKey) {
80 that.execute_selected_cell();
81 that.execute_selected_cell();
81 return false;
82 return false;
82 } else if (event.which === 13 && event.ctrlKey) {
83 } else if (event.which === 13 && event.ctrlKey) {
83 that.execute_selected_cell({terminal:true});
84 that.execute_selected_cell({terminal:true});
84 return false;
85 return false;
85 } else if (event.which === 77 && event.ctrlKey) {
86 } else if (event.which === 77 && event.ctrlKey) {
86 that.control_key_active = true;
87 that.control_key_active = true;
87 return false;
88 return false;
88 } else if (event.which === 68 && that.control_key_active) {
89 } else if (event.which === 68 && that.control_key_active) {
89 // Delete selected cell = d
90 // Delete selected cell = d
90 that.delete_cell();
91 that.delete_cell();
91 that.control_key_active = false;
92 that.control_key_active = false;
92 return false;
93 return false;
93 } else if (event.which === 65 && that.control_key_active) {
94 } else if (event.which === 65 && that.control_key_active) {
94 // Insert code cell above selected = a
95 // Insert code cell above selected = a
95 that.insert_code_cell_above();
96 that.insert_code_cell_above();
96 that.control_key_active = false;
97 that.control_key_active = false;
97 return false;
98 return false;
98 } else if (event.which === 66 && that.control_key_active) {
99 } else if (event.which === 66 && that.control_key_active) {
99 // Insert code cell below selected = b
100 // Insert code cell below selected = b
100 that.insert_code_cell_below();
101 that.insert_code_cell_below();
101 that.control_key_active = false;
102 that.control_key_active = false;
102 return false;
103 return false;
103 } else if (event.which === 67 && that.control_key_active) {
104 } else if (event.which === 67 && that.control_key_active) {
104 // To code = c
105 // To code = c
105 that.to_code();
106 that.to_code();
106 that.control_key_active = false;
107 that.control_key_active = false;
107 return false;
108 return false;
108 } else if (event.which === 77 && that.control_key_active) {
109 } else if (event.which === 77 && that.control_key_active) {
109 // To markdown = m
110 // To markdown = m
110 that.to_markdown();
111 that.to_markdown();
111 that.control_key_active = false;
112 that.control_key_active = false;
112 return false;
113 return false;
113 } else if (event.which === 84 && that.control_key_active) {
114 } else if (event.which === 84 && that.control_key_active) {
114 // Toggle output = t
115 // Toggle output = t
115 that.toggle_output();
116 that.toggle_output();
116 that.control_key_active = false;
117 that.control_key_active = false;
117 return false;
118 return false;
118 } else if (event.which === 83 && that.control_key_active) {
119 } else if (event.which === 83 && that.control_key_active) {
119 // Save notebook = s
120 // Save notebook = s
120 IPython.save_widget.save_notebook();
121 IPython.save_widget.save_notebook();
121 that.control_key_active = false;
122 that.control_key_active = false;
122 return false;
123 return false;
123 } else if (event.which === 74 && that.control_key_active) {
124 } else if (event.which === 74 && that.control_key_active) {
124 // Move cell down = j
125 // Move cell down = j
125 that.move_cell_down();
126 that.move_cell_down();
126 that.control_key_active = false;
127 that.control_key_active = false;
127 return false;
128 return false;
128 } else if (event.which === 75 && that.control_key_active) {
129 } else if (event.which === 75 && that.control_key_active) {
129 // Move cell up = k
130 // Move cell up = k
130 that.move_cell_up();
131 that.move_cell_up();
131 that.control_key_active = false;
132 that.control_key_active = false;
132 return false;
133 return false;
133 } else if (event.which === 80 && that.control_key_active) {
134 } else if (event.which === 80 && that.control_key_active) {
134 // Select previous = p
135 // Select previous = p
135 that.select_prev();
136 that.select_prev();
136 that.control_key_active = false;
137 that.control_key_active = false;
137 return false;
138 return false;
138 } else if (event.which === 78 && that.control_key_active) {
139 } else if (event.which === 78 && that.control_key_active) {
139 // Select next = n
140 // Select next = n
140 that.select_next();
141 that.select_next();
141 that.control_key_active = false;
142 that.control_key_active = false;
142 return false;
143 return false;
143 } else if (event.which === 76 && that.control_key_active) {
144 } else if (event.which === 76 && that.control_key_active) {
144 // Toggle line numbers = l
145 // Toggle line numbers = l
145 that.cell_toggle_line_numbers();
146 that.cell_toggle_line_numbers();
146 that.control_key_active = false;
147 that.control_key_active = false;
147 return false;
148 return false;
148 } else if (event.which === 73 && that.control_key_active) {
149 } else if (event.which === 73 && that.control_key_active) {
149 // Interrupt kernel = i
150 // Interrupt kernel = i
150 IPython.notebook.kernel.interrupt();
151 IPython.notebook.kernel.interrupt();
151 that.control_key_active = false;
152 that.control_key_active = false;
152 return false;
153 return false;
153 } else if (event.which === 190 && that.control_key_active) {
154 } else if (event.which === 190 && that.control_key_active) {
154 // Restart kernel = . # matches qt console
155 // Restart kernel = . # matches qt console
155 IPython.notebook.restart_kernel();
156 IPython.notebook.restart_kernel();
156 that.control_key_active = false;
157 that.control_key_active = false;
157 return false;
158 return false;
158 } else if (event.which === 72 && that.control_key_active) {
159 } else if (event.which === 72 && that.control_key_active) {
159 // Show keyboard shortcuts = h
160 // Show keyboard shortcuts = h
160 that.toggle_keyboard_shortcuts();
161 that.toggle_keyboard_shortcuts();
161 that.control_key_active = false;
162 that.control_key_active = false;
162 return false;
163 return false;
163 } else if (that.control_key_active) {
164 } else if (that.control_key_active) {
164 that.control_key_active = false;
165 that.control_key_active = false;
165 return true;
166 return true;
166 };
167 };
167 });
168 });
168
169
169 this.element.bind('collapse_pager', function () {
170 this.element.bind('collapse_pager', function () {
170 var app_height = $('div#main_app').height(); // content height
171 var app_height = $('div#main_app').height(); // content height
171 var splitter_height = $('div#pager_splitter').outerHeight(true);
172 var splitter_height = $('div#pager_splitter').outerHeight(true);
172 var new_height = app_height - splitter_height;
173 var new_height = app_height - splitter_height;
173 that.element.animate({height : new_height + 'px'}, 'fast');
174 that.element.animate({height : new_height + 'px'}, 'fast');
174 });
175 });
175
176
176 this.element.bind('expand_pager', function () {
177 this.element.bind('expand_pager', function () {
177 var app_height = $('div#main_app').height(); // content height
178 var app_height = $('div#main_app').height(); // content height
178 var splitter_height = $('div#pager_splitter').outerHeight(true);
179 var splitter_height = $('div#pager_splitter').outerHeight(true);
179 var pager_height = $('div#pager').outerHeight(true);
180 var pager_height = $('div#pager').outerHeight(true);
180 var new_height = app_height - pager_height - splitter_height;
181 var new_height = app_height - pager_height - splitter_height;
181 that.element.animate({height : new_height + 'px'}, 'fast');
182 that.element.animate({height : new_height + 'px'}, 'fast');
182 });
183 });
183
184
184 this.element.bind('collapse_left_panel', function () {
185 this.element.bind('collapse_left_panel', function () {
185 var splitter_width = $('div#left_panel_splitter').outerWidth(true);
186 var splitter_width = $('div#left_panel_splitter').outerWidth(true);
186 var new_margin = splitter_width;
187 var new_margin = splitter_width;
187 $('div#notebook_panel').animate({marginLeft : new_margin + 'px'}, 'fast');
188 $('div#notebook_panel').animate({marginLeft : new_margin + 'px'}, 'fast');
188 });
189 });
189
190
190 this.element.bind('expand_left_panel', function () {
191 this.element.bind('expand_left_panel', function () {
191 var splitter_width = $('div#left_panel_splitter').outerWidth(true);
192 var splitter_width = $('div#left_panel_splitter').outerWidth(true);
192 var left_panel_width = IPython.left_panel.width;
193 var left_panel_width = IPython.left_panel.width;
193 var new_margin = splitter_width + left_panel_width;
194 var new_margin = splitter_width + left_panel_width;
194 $('div#notebook_panel').animate({marginLeft : new_margin + 'px'}, 'fast');
195 $('div#notebook_panel').animate({marginLeft : new_margin + 'px'}, 'fast');
195 });
196 });
196
197
197 $(window).bind('beforeunload', function () {
198 $(window).bind('beforeunload', function () {
198 var kill_kernel = $('#kill_kernel').prop('checked');
199 var kill_kernel = $('#kill_kernel').prop('checked');
199 if (kill_kernel) {
200 if (kill_kernel) {
200 that.kernel.kill();
201 that.kernel.kill();
201 }
202 }
202 if (that.dirty && ! that.read_only) {
203 if (that.dirty && ! that.read_only) {
203 return "You have unsaved changes that will be lost if you leave this page.";
204 return "You have unsaved changes that will be lost if you leave this page.";
204 };
205 };
205 });
206 });
206 };
207 };
207
208
208
209
209 Notebook.prototype.toggle_keyboard_shortcuts = function () {
210 Notebook.prototype.toggle_keyboard_shortcuts = function () {
210 // toggles display of keyboard shortcut dialog
211 // toggles display of keyboard shortcut dialog
211 var that = this;
212 var that = this;
212 if ( this.shortcut_dialog ){
213 if ( this.shortcut_dialog ){
213 // if dialog is already shown, close it
214 // if dialog is already shown, close it
214 this.shortcut_dialog.dialog("close");
215 this.shortcut_dialog.dialog("close");
215 this.shortcut_dialog = null;
216 this.shortcut_dialog = null;
216 return;
217 return;
217 }
218 }
218 var dialog = $('<div/>');
219 var dialog = $('<div/>');
219 this.shortcut_dialog = dialog;
220 this.shortcut_dialog = dialog;
220 var shortcuts = [
221 var shortcuts = [
221 {key: 'Shift-Enter', help: 'run cell'},
222 {key: 'Shift-Enter', help: 'run cell'},
222 {key: 'Ctrl-Enter', help: 'run cell in-place'},
223 {key: 'Ctrl-Enter', help: 'run cell in-place'},
223 {key: 'Ctrl-m d', help: 'delete cell'},
224 {key: 'Ctrl-m d', help: 'delete cell'},
224 {key: 'Ctrl-m a', help: 'insert cell above'},
225 {key: 'Ctrl-m a', help: 'insert cell above'},
225 {key: 'Ctrl-m b', help: 'insert cell below'},
226 {key: 'Ctrl-m b', help: 'insert cell below'},
226 {key: 'Ctrl-m t', help: 'toggle output'},
227 {key: 'Ctrl-m t', help: 'toggle output'},
227 {key: 'Ctrl-m l', help: 'toggle line numbers'},
228 {key: 'Ctrl-m l', help: 'toggle line numbers'},
228 {key: 'Ctrl-m s', help: 'save notebook'},
229 {key: 'Ctrl-m s', help: 'save notebook'},
229 {key: 'Ctrl-m j', help: 'move cell down'},
230 {key: 'Ctrl-m j', help: 'move cell down'},
230 {key: 'Ctrl-m k', help: 'move cell up'},
231 {key: 'Ctrl-m k', help: 'move cell up'},
231 {key: 'Ctrl-m c', help: 'code cell'},
232 {key: 'Ctrl-m c', help: 'code cell'},
232 {key: 'Ctrl-m m', help: 'markdown cell'},
233 {key: 'Ctrl-m m', help: 'markdown cell'},
233 {key: 'Ctrl-m p', help: 'select previous'},
234 {key: 'Ctrl-m p', help: 'select previous'},
234 {key: 'Ctrl-m n', help: 'select next'},
235 {key: 'Ctrl-m n', help: 'select next'},
235 {key: 'Ctrl-m i', help: 'interrupt kernel'},
236 {key: 'Ctrl-m i', help: 'interrupt kernel'},
236 {key: 'Ctrl-m .', help: 'restart kernel'},
237 {key: 'Ctrl-m .', help: 'restart kernel'},
237 {key: 'Ctrl-m h', help: 'show keyboard shortcuts'}
238 {key: 'Ctrl-m h', help: 'show keyboard shortcuts'}
238 ];
239 ];
239 for (var i=0; i<shortcuts.length; i++) {
240 for (var i=0; i<shortcuts.length; i++) {
240 dialog.append($('<div>').
241 dialog.append($('<div>').
241 append($('<span/>').addClass('shortcut_key').html(shortcuts[i].key)).
242 append($('<span/>').addClass('shortcut_key').html(shortcuts[i].key)).
242 append($('<span/>').addClass('shortcut_descr').html(' : ' + shortcuts[i].help))
243 append($('<span/>').addClass('shortcut_descr').html(' : ' + shortcuts[i].help))
243 );
244 );
244 };
245 };
245 dialog.bind('dialogclose', function(event) {
246 dialog.bind('dialogclose', function(event) {
246 // dialog has been closed, allow it to be drawn again.
247 // dialog has been closed, allow it to be drawn again.
247 that.shortcut_dialog = null;
248 that.shortcut_dialog = null;
248 });
249 });
249 dialog.dialog({title: 'Keyboard shortcuts'});
250 dialog.dialog({title: 'Keyboard shortcuts'});
250 };
251 };
251
252
252
253
253 Notebook.prototype.scroll_to_bottom = function () {
254 Notebook.prototype.scroll_to_bottom = function () {
254 this.element.animate({scrollTop:this.element.get(0).scrollHeight}, 0);
255 this.element.animate({scrollTop:this.element.get(0).scrollHeight}, 0);
255 };
256 };
256
257
257
258
258 Notebook.prototype.scroll_to_top = function () {
259 Notebook.prototype.scroll_to_top = function () {
259 this.element.animate({scrollTop:0}, 0);
260 this.element.animate({scrollTop:0}, 0);
260 };
261 };
261
262
262
263
263 // Cell indexing, retrieval, etc.
264 // Cell indexing, retrieval, etc.
264
265
265
266
266 Notebook.prototype.cell_elements = function () {
267 Notebook.prototype.cell_elements = function () {
267 return this.element.children("div.cell");
268 return this.element.children("div.cell");
268 }
269 }
269
270
270
271
271 Notebook.prototype.ncells = function (cell) {
272 Notebook.prototype.ncells = function (cell) {
272 return this.cell_elements().length;
273 return this.cell_elements().length;
273 }
274 }
274
275
275
276
276 // TODO: we are often calling cells as cells()[i], which we should optimize
277 // TODO: we are often calling cells as cells()[i], which we should optimize
277 // to cells(i) or a new method.
278 // to cells(i) or a new method.
278 Notebook.prototype.cells = function () {
279 Notebook.prototype.cells = function () {
279 return this.cell_elements().toArray().map(function (e) {
280 return this.cell_elements().toArray().map(function (e) {
280 return $(e).data("cell");
281 return $(e).data("cell");
281 });
282 });
282 }
283 }
283
284
284
285
285 Notebook.prototype.find_cell_index = function (cell) {
286 Notebook.prototype.find_cell_index = function (cell) {
286 var result = null;
287 var result = null;
287 this.cell_elements().filter(function (index) {
288 this.cell_elements().filter(function (index) {
288 if ($(this).data("cell") === cell) {
289 if ($(this).data("cell") === cell) {
289 result = index;
290 result = index;
290 };
291 };
291 });
292 });
292 return result;
293 return result;
293 };
294 };
294
295
295
296
296 Notebook.prototype.index_or_selected = function (index) {
297 Notebook.prototype.index_or_selected = function (index) {
297 return index || this.selected_index() || 0;
298 return index || this.selected_index() || 0;
298 }
299 }
299
300
300
301
301 Notebook.prototype.select = function (index) {
302 Notebook.prototype.select = function (index) {
302 if (index !== undefined && index >= 0 && index < this.ncells()) {
303 if (index !== undefined && index >= 0 && index < this.ncells()) {
303 if (this.selected_index() !== null) {
304 if (this.selected_index() !== null) {
304 this.selected_cell().unselect();
305 this.selected_cell().unselect();
305 };
306 };
306 this.cells()[index].select();
307 this.cells()[index].select();
307 };
308 };
308 return this;
309 return this;
309 };
310 };
310
311
311
312
312 Notebook.prototype.select_next = function () {
313 Notebook.prototype.select_next = function () {
313 var index = this.selected_index();
314 var index = this.selected_index();
314 if (index !== null && index >= 0 && (index+1) < this.ncells()) {
315 if (index !== null && index >= 0 && (index+1) < this.ncells()) {
315 this.select(index+1);
316 this.select(index+1);
316 };
317 };
317 return this;
318 return this;
318 };
319 };
319
320
320
321
321 Notebook.prototype.select_prev = function () {
322 Notebook.prototype.select_prev = function () {
322 var index = this.selected_index();
323 var index = this.selected_index();
323 if (index !== null && index >= 0 && (index-1) < this.ncells()) {
324 if (index !== null && index >= 0 && (index-1) < this.ncells()) {
324 this.select(index-1);
325 this.select(index-1);
325 };
326 };
326 return this;
327 return this;
327 };
328 };
328
329
329
330
330 Notebook.prototype.selected_index = function () {
331 Notebook.prototype.selected_index = function () {
331 var result = null;
332 var result = null;
332 this.cell_elements().filter(function (index) {
333 this.cell_elements().filter(function (index) {
333 if ($(this).data("cell").selected === true) {
334 if ($(this).data("cell").selected === true) {
334 result = index;
335 result = index;
335 };
336 };
336 });
337 });
337 return result;
338 return result;
338 };
339 };
339
340
340
341
341 Notebook.prototype.cell_for_msg = function (msg_id) {
342 Notebook.prototype.cell_for_msg = function (msg_id) {
342 var cell_id = this.msg_cell_map[msg_id];
343 var cell_id = this.msg_cell_map[msg_id];
343 var result = null;
344 var result = null;
344 this.cell_elements().filter(function (index) {
345 this.cell_elements().filter(function (index) {
345 cell = $(this).data("cell");
346 cell = $(this).data("cell");
346 if (cell.cell_id === cell_id) {
347 if (cell.cell_id === cell_id) {
347 result = cell;
348 result = cell;
348 };
349 };
349 });
350 });
350 return result;
351 return result;
351 };
352 };
352
353
353
354
354 Notebook.prototype.selected_cell = function () {
355 Notebook.prototype.selected_cell = function () {
355 return this.cell_elements().eq(this.selected_index()).data("cell");
356 return this.cell_elements().eq(this.selected_index()).data("cell");
356 }
357 }
357
358
358
359
359 // Cell insertion, deletion and moving.
360 // Cell insertion, deletion and moving.
360
361
361
362
362 Notebook.prototype.delete_cell = function (index) {
363 Notebook.prototype.delete_cell = function (index) {
363 var i = index || this.selected_index();
364 var i = index || this.selected_index();
364 if (i !== null && i >= 0 && i < this.ncells()) {
365 if (i !== null && i >= 0 && i < this.ncells()) {
365 this.cell_elements().eq(i).remove();
366 this.cell_elements().eq(i).remove();
366 if (i === (this.ncells())) {
367 if (i === (this.ncells())) {
367 this.select(i-1);
368 this.select(i-1);
368 } else {
369 } else {
369 this.select(i);
370 this.select(i);
370 };
371 };
371 };
372 };
372 this.dirty = true;
373 this.dirty = true;
373 return this;
374 return this;
374 };
375 };
375
376
376
377
377 Notebook.prototype.append_cell = function (cell) {
378 Notebook.prototype.append_cell = function (cell) {
378 this.element.find('div.end_space').before(cell.element);
379 this.element.find('div.end_space').before(cell.element);
379 this.dirty = true;
380 this.dirty = true;
380 return this;
381 return this;
381 };
382 };
382
383
383
384
384 Notebook.prototype.insert_cell_below = function (cell, index) {
385 Notebook.prototype.insert_cell_below = function (cell, index) {
385 var ncells = this.ncells();
386 var ncells = this.ncells();
386 if (ncells === 0) {
387 if (ncells === 0) {
387 this.append_cell(cell);
388 this.append_cell(cell);
388 return this;
389 return this;
389 };
390 };
390 if (index >= 0 && index < ncells) {
391 if (index >= 0 && index < ncells) {
391 this.cell_elements().eq(index).after(cell.element);
392 this.cell_elements().eq(index).after(cell.element);
392 };
393 };
393 this.dirty = true;
394 this.dirty = true;
394 return this
395 return this
395 };
396 };
396
397
397
398
398 Notebook.prototype.insert_cell_above = function (cell, index) {
399 Notebook.prototype.insert_cell_above = function (cell, index) {
399 var ncells = this.ncells();
400 var ncells = this.ncells();
400 if (ncells === 0) {
401 if (ncells === 0) {
401 this.append_cell(cell);
402 this.append_cell(cell);
402 return this;
403 return this;
403 };
404 };
404 if (index >= 0 && index < ncells) {
405 if (index >= 0 && index < ncells) {
405 this.cell_elements().eq(index).before(cell.element);
406 this.cell_elements().eq(index).before(cell.element);
406 };
407 };
407 this.dirty = true;
408 this.dirty = true;
408 return this;
409 return this;
409 };
410 };
410
411
411
412
412 Notebook.prototype.move_cell_up = function (index) {
413 Notebook.prototype.move_cell_up = function (index) {
413 var i = index || this.selected_index();
414 var i = index || this.selected_index();
414 if (i !== null && i < this.ncells() && i > 0) {
415 if (i !== null && i < this.ncells() && i > 0) {
415 var pivot = this.cell_elements().eq(i-1);
416 var pivot = this.cell_elements().eq(i-1);
416 var tomove = this.cell_elements().eq(i);
417 var tomove = this.cell_elements().eq(i);
417 if (pivot !== null && tomove !== null) {
418 if (pivot !== null && tomove !== null) {
418 tomove.detach();
419 tomove.detach();
419 pivot.before(tomove);
420 pivot.before(tomove);
420 this.select(i-1);
421 this.select(i-1);
421 };
422 };
422 };
423 };
423 this.dirty = true;
424 this.dirty = true;
424 return this;
425 return this;
425 }
426 }
426
427
427
428
428 Notebook.prototype.move_cell_down = function (index) {
429 Notebook.prototype.move_cell_down = function (index) {
429 var i = index || this.selected_index();
430 var i = index || this.selected_index();
430 if (i !== null && i < (this.ncells()-1) && i >= 0) {
431 if (i !== null && i < (this.ncells()-1) && i >= 0) {
431 var pivot = this.cell_elements().eq(i+1)
432 var pivot = this.cell_elements().eq(i+1)
432 var tomove = this.cell_elements().eq(i)
433 var tomove = this.cell_elements().eq(i)
433 if (pivot !== null && tomove !== null) {
434 if (pivot !== null && tomove !== null) {
434 tomove.detach();
435 tomove.detach();
435 pivot.after(tomove);
436 pivot.after(tomove);
436 this.select(i+1);
437 this.select(i+1);
437 };
438 };
438 };
439 };
439 this.dirty = true;
440 this.dirty = true;
440 return this;
441 return this;
441 }
442 }
442
443
443
444
444 Notebook.prototype.sort_cells = function () {
445 Notebook.prototype.sort_cells = function () {
445 var ncells = this.ncells();
446 var ncells = this.ncells();
446 var sindex = this.selected_index();
447 var sindex = this.selected_index();
447 var swapped;
448 var swapped;
448 do {
449 do {
449 swapped = false
450 swapped = false
450 for (var i=1; i<ncells; i++) {
451 for (var i=1; i<ncells; i++) {
451 current = this.cell_elements().eq(i).data("cell");
452 current = this.cell_elements().eq(i).data("cell");
452 previous = this.cell_elements().eq(i-1).data("cell");
453 previous = this.cell_elements().eq(i-1).data("cell");
453 if (previous.input_prompt_number > current.input_prompt_number) {
454 if (previous.input_prompt_number > current.input_prompt_number) {
454 this.move_cell_up(i);
455 this.move_cell_up(i);
455 swapped = true;
456 swapped = true;
456 };
457 };
457 };
458 };
458 } while (swapped);
459 } while (swapped);
459 this.select(sindex);
460 this.select(sindex);
460 return this;
461 return this;
461 };
462 };
462
463
463
464
464 Notebook.prototype.insert_code_cell_above = function (index) {
465 Notebook.prototype.insert_code_cell_above = function (index) {
465 // TODO: Bounds check for i
466 // TODO: Bounds check for i
466 var i = this.index_or_selected(index);
467 var i = this.index_or_selected(index);
467 var cell = new IPython.CodeCell(this);
468 var cell = new IPython.CodeCell(this);
468 cell.set_input_prompt();
469 cell.set_input_prompt();
469 this.insert_cell_above(cell, i);
470 this.insert_cell_above(cell, i);
470 this.select(this.find_cell_index(cell));
471 this.select(this.find_cell_index(cell));
471 return cell;
472 return cell;
472 }
473 }
473
474
474
475
475 Notebook.prototype.insert_code_cell_below = function (index) {
476 Notebook.prototype.insert_code_cell_below = function (index) {
476 // TODO: Bounds check for i
477 // TODO: Bounds check for i
477 var i = this.index_or_selected(index);
478 var i = this.index_or_selected(index);
478 var cell = new IPython.CodeCell(this);
479 var cell = new IPython.CodeCell(this);
479 cell.set_input_prompt();
480 cell.set_input_prompt();
480 this.insert_cell_below(cell, i);
481 this.insert_cell_below(cell, i);
481 this.select(this.find_cell_index(cell));
482 this.select(this.find_cell_index(cell));
482 return cell;
483 return cell;
483 }
484 }
484
485
485
486
486 Notebook.prototype.insert_html_cell_above = function (index) {
487 Notebook.prototype.insert_html_cell_above = function (index) {
487 // TODO: Bounds check for i
488 // TODO: Bounds check for i
488 var i = this.index_or_selected(index);
489 var i = this.index_or_selected(index);
489 var cell = new IPython.HTMLCell(this);
490 var cell = new IPython.HTMLCell(this);
490 cell.config_mathjax();
491 cell.config_mathjax();
491 this.insert_cell_above(cell, i);
492 this.insert_cell_above(cell, i);
492 this.select(this.find_cell_index(cell));
493 this.select(this.find_cell_index(cell));
493 return cell;
494 return cell;
494 }
495 }
495
496
496
497
497 Notebook.prototype.insert_html_cell_below = function (index) {
498 Notebook.prototype.insert_html_cell_below = function (index) {
498 // TODO: Bounds check for i
499 // TODO: Bounds check for i
499 var i = this.index_or_selected(index);
500 var i = this.index_or_selected(index);
500 var cell = new IPython.HTMLCell(this);
501 var cell = new IPython.HTMLCell(this);
501 cell.config_mathjax();
502 cell.config_mathjax();
502 this.insert_cell_below(cell, i);
503 this.insert_cell_below(cell, i);
503 this.select(this.find_cell_index(cell));
504 this.select(this.find_cell_index(cell));
504 return cell;
505 return cell;
505 }
506 }
506
507
507
508
508 Notebook.prototype.insert_markdown_cell_above = function (index) {
509 Notebook.prototype.insert_markdown_cell_above = function (index) {
509 // TODO: Bounds check for i
510 // TODO: Bounds check for i
510 var i = this.index_or_selected(index);
511 var i = this.index_or_selected(index);
511 var cell = new IPython.MarkdownCell(this);
512 var cell = new IPython.MarkdownCell(this);
512 cell.config_mathjax();
513 cell.config_mathjax();
513 this.insert_cell_above(cell, i);
514 this.insert_cell_above(cell, i);
514 this.select(this.find_cell_index(cell));
515 this.select(this.find_cell_index(cell));
515 return cell;
516 return cell;
516 }
517 }
517
518
518
519
519 Notebook.prototype.insert_markdown_cell_below = function (index) {
520 Notebook.prototype.insert_markdown_cell_below = function (index) {
520 // TODO: Bounds check for i
521 // TODO: Bounds check for i
521 var i = this.index_or_selected(index);
522 var i = this.index_or_selected(index);
522 var cell = new IPython.MarkdownCell(this);
523 var cell = new IPython.MarkdownCell(this);
523 cell.config_mathjax();
524 cell.config_mathjax();
524 this.insert_cell_below(cell, i);
525 this.insert_cell_below(cell, i);
525 this.select(this.find_cell_index(cell));
526 this.select(this.find_cell_index(cell));
526 return cell;
527 return cell;
527 }
528 }
528
529
529
530
530 Notebook.prototype.to_code = function (index) {
531 Notebook.prototype.to_code = function (index) {
531 // TODO: Bounds check for i
532 // TODO: Bounds check for i
532 var i = this.index_or_selected(index);
533 var i = this.index_or_selected(index);
533 var source_element = this.cell_elements().eq(i);
534 var source_element = this.cell_elements().eq(i);
534 var source_cell = source_element.data("cell");
535 var source_cell = source_element.data("cell");
535 if (source_cell instanceof IPython.HTMLCell ||
536 if (source_cell instanceof IPython.HTMLCell ||
536 source_cell instanceof IPython.MarkdownCell) {
537 source_cell instanceof IPython.MarkdownCell) {
537 this.insert_code_cell_below(i);
538 this.insert_code_cell_below(i);
538 var target_cell = this.cells()[i+1];
539 var target_cell = this.cells()[i+1];
539 target_cell.set_code(source_cell.get_source());
540 target_cell.set_code(source_cell.get_source());
540 source_element.remove();
541 source_element.remove();
541 target_cell.select();
542 target_cell.select();
542 };
543 };
543 this.dirty = true;
544 this.dirty = true;
544 };
545 };
545
546
546
547
547 Notebook.prototype.to_markdown = function (index) {
548 Notebook.prototype.to_markdown = function (index) {
548 // TODO: Bounds check for i
549 // TODO: Bounds check for i
549 var i = this.index_or_selected(index);
550 var i = this.index_or_selected(index);
550 var source_element = this.cell_elements().eq(i);
551 var source_element = this.cell_elements().eq(i);
551 var source_cell = source_element.data("cell");
552 var source_cell = source_element.data("cell");
552 var target_cell = null;
553 var target_cell = null;
553 if (source_cell instanceof IPython.CodeCell) {
554 if (source_cell instanceof IPython.CodeCell) {
554 this.insert_markdown_cell_below(i);
555 this.insert_markdown_cell_below(i);
555 var target_cell = this.cells()[i+1];
556 var target_cell = this.cells()[i+1];
556 var text = source_cell.get_code();
557 var text = source_cell.get_code();
557 } else if (source_cell instanceof IPython.HTMLCell) {
558 } else if (source_cell instanceof IPython.HTMLCell) {
558 this.insert_markdown_cell_below(i);
559 this.insert_markdown_cell_below(i);
559 var target_cell = this.cells()[i+1];
560 var target_cell = this.cells()[i+1];
560 var text = source_cell.get_source();
561 var text = source_cell.get_source();
561 if (text === source_cell.placeholder) {
562 if (text === source_cell.placeholder) {
562 text = target_cell.placeholder;
563 text = target_cell.placeholder;
563 }
564 }
564 }
565 }
565 if (target_cell !== null) {
566 if (target_cell !== null) {
566 if (text === "") {text = target_cell.placeholder;};
567 if (text === "") {text = target_cell.placeholder;};
567 target_cell.set_source(text);
568 target_cell.set_source(text);
568 source_element.remove();
569 source_element.remove();
569 target_cell.edit();
570 target_cell.edit();
570 }
571 }
571 this.dirty = true;
572 this.dirty = true;
572 };
573 };
573
574
574
575
575 Notebook.prototype.to_html = function (index) {
576 Notebook.prototype.to_html = function (index) {
576 // TODO: Bounds check for i
577 // TODO: Bounds check for i
577 var i = this.index_or_selected(index);
578 var i = this.index_or_selected(index);
578 var source_element = this.cell_elements().eq(i);
579 var source_element = this.cell_elements().eq(i);
579 var source_cell = source_element.data("cell");
580 var source_cell = source_element.data("cell");
580 var target_cell = null;
581 var target_cell = null;
581 if (source_cell instanceof IPython.CodeCell) {
582 if (source_cell instanceof IPython.CodeCell) {
582 this.insert_html_cell_below(i);
583 this.insert_html_cell_below(i);
583 var target_cell = this.cells()[i+1];
584 var target_cell = this.cells()[i+1];
584 var text = source_cell.get_code();
585 var text = source_cell.get_code();
585 } else if (source_cell instanceof IPython.MarkdownCell) {
586 } else if (source_cell instanceof IPython.MarkdownCell) {
586 this.insert_html_cell_below(i);
587 this.insert_html_cell_below(i);
587 var target_cell = this.cells()[i+1];
588 var target_cell = this.cells()[i+1];
588 var text = source_cell.get_source();
589 var text = source_cell.get_source();
589 if (text === source_cell.placeholder) {
590 if (text === source_cell.placeholder) {
590 text = target_cell.placeholder;
591 text = target_cell.placeholder;
591 }
592 }
592 }
593 }
593 if (target_cell !== null) {
594 if (target_cell !== null) {
594 if (text === "") {text = target_cell.placeholder;};
595 if (text === "") {text = target_cell.placeholder;};
595 target_cell.set_source(text);
596 target_cell.set_source(text);
596 source_element.remove();
597 source_element.remove();
597 target_cell.edit();
598 target_cell.edit();
598 }
599 }
599 this.dirty = true;
600 this.dirty = true;
600 };
601 };
601
602
602
603
603 // Cell collapsing and output clearing
604 // Cell collapsing and output clearing
604
605
605 Notebook.prototype.collapse = function (index) {
606 Notebook.prototype.collapse = function (index) {
606 var i = this.index_or_selected(index);
607 var i = this.index_or_selected(index);
607 this.cells()[i].collapse();
608 this.cells()[i].collapse();
608 this.dirty = true;
609 this.dirty = true;
609 };
610 };
610
611
611
612
612 Notebook.prototype.expand = function (index) {
613 Notebook.prototype.expand = function (index) {
613 var i = this.index_or_selected(index);
614 var i = this.index_or_selected(index);
614 this.cells()[i].expand();
615 this.cells()[i].expand();
615 this.dirty = true;
616 this.dirty = true;
616 };
617 };
617
618
618
619
619 Notebook.prototype.toggle_output = function (index) {
620 Notebook.prototype.toggle_output = function (index) {
620 var i = this.index_or_selected(index);
621 var i = this.index_or_selected(index);
621 this.cells()[i].toggle_output();
622 this.cells()[i].toggle_output();
622 this.dirty = true;
623 this.dirty = true;
623 };
624 };
624
625
625
626
626 Notebook.prototype.set_timebeforetooltip = function (time) {
627 Notebook.prototype.set_timebeforetooltip = function (time) {
627 console.log("change time before tooltip to : "+time);
628 console.log("change time before tooltip to : "+time);
628 this.time_before_tooltip = time;
629 this.time_before_tooltip = time;
629 };
630 };
630
631
631 Notebook.prototype.set_tooltipontab = function (state) {
632 Notebook.prototype.set_tooltipontab = function (state) {
632 console.log("change tooltip on tab to : "+state);
633 console.log("change tooltip on tab to : "+state);
633 this.tooltip_on_tab = state;
634 this.tooltip_on_tab = state;
634 };
635 };
635
636
637 Notebook.prototype.set_smartcompleter = function (state) {
638 console.log("Smart completion (kwargs first) changed to to : "+state);
639 this.smart_completer = state;
640 };
641
636 Notebook.prototype.set_autoindent = function (state) {
642 Notebook.prototype.set_autoindent = function (state) {
637 var cells = this.cells();
643 var cells = this.cells();
638 len = cells.length;
644 len = cells.length;
639 for (var i=0; i<len; i++) {
645 for (var i=0; i<len; i++) {
640 cells[i].set_autoindent(state)
646 cells[i].set_autoindent(state)
641 };
647 };
642 };
648 };
643
649
644
650
645 Notebook.prototype.clear_all_output = function () {
651 Notebook.prototype.clear_all_output = function () {
646 var ncells = this.ncells();
652 var ncells = this.ncells();
647 var cells = this.cells();
653 var cells = this.cells();
648 for (var i=0; i<ncells; i++) {
654 for (var i=0; i<ncells; i++) {
649 if (cells[i] instanceof IPython.CodeCell) {
655 if (cells[i] instanceof IPython.CodeCell) {
650 cells[i].clear_output(true,true,true);
656 cells[i].clear_output(true,true,true);
651 }
657 }
652 };
658 };
653 this.dirty = true;
659 this.dirty = true;
654 };
660 };
655
661
656 // Other cell functions: line numbers, ...
662 // Other cell functions: line numbers, ...
657
663
658 Notebook.prototype.cell_toggle_line_numbers = function() {
664 Notebook.prototype.cell_toggle_line_numbers = function() {
659 this.selected_cell().toggle_line_numbers()
665 this.selected_cell().toggle_line_numbers()
660 };
666 };
661
667
662 // Kernel related things
668 // Kernel related things
663
669
664 Notebook.prototype.start_kernel = function () {
670 Notebook.prototype.start_kernel = function () {
665 this.kernel = new IPython.Kernel();
671 this.kernel = new IPython.Kernel();
666 var notebook_id = IPython.save_widget.get_notebook_id();
672 var notebook_id = IPython.save_widget.get_notebook_id();
667 this.kernel.start(notebook_id, $.proxy(this.kernel_started, this));
673 this.kernel.start(notebook_id, $.proxy(this.kernel_started, this));
668 };
674 };
669
675
670
676
671 Notebook.prototype.restart_kernel = function () {
677 Notebook.prototype.restart_kernel = function () {
672 var that = this;
678 var that = this;
673 var notebook_id = IPython.save_widget.get_notebook_id();
679 var notebook_id = IPython.save_widget.get_notebook_id();
674
680
675 var dialog = $('<div/>');
681 var dialog = $('<div/>');
676 dialog.html('Do you want to restart the current kernel? You will lose all variables defined in it.');
682 dialog.html('Do you want to restart the current kernel? You will lose all variables defined in it.');
677 $(document).append(dialog);
683 $(document).append(dialog);
678 dialog.dialog({
684 dialog.dialog({
679 resizable: false,
685 resizable: false,
680 modal: true,
686 modal: true,
681 title: "Restart kernel or continue running?",
687 title: "Restart kernel or continue running?",
682 buttons : {
688 buttons : {
683 "Restart": function () {
689 "Restart": function () {
684 that.kernel.restart($.proxy(that.kernel_started, that));
690 that.kernel.restart($.proxy(that.kernel_started, that));
685 $(this).dialog('close');
691 $(this).dialog('close');
686 },
692 },
687 "Continue running": function () {
693 "Continue running": function () {
688 $(this).dialog('close');
694 $(this).dialog('close');
689 }
695 }
690 }
696 }
691 });
697 });
692 };
698 };
693
699
694
700
695 Notebook.prototype.kernel_started = function () {
701 Notebook.prototype.kernel_started = function () {
696 console.log("Kernel started: ", this.kernel.kernel_id);
702 console.log("Kernel started: ", this.kernel.kernel_id);
697 this.kernel.shell_channel.onmessage = $.proxy(this.handle_shell_reply,this);
703 this.kernel.shell_channel.onmessage = $.proxy(this.handle_shell_reply,this);
698 this.kernel.iopub_channel.onmessage = $.proxy(this.handle_iopub_reply,this);
704 this.kernel.iopub_channel.onmessage = $.proxy(this.handle_iopub_reply,this);
699 };
705 };
700
706
701
707
702 Notebook.prototype.handle_shell_reply = function (e) {
708 Notebook.prototype.handle_shell_reply = function (e) {
703 reply = $.parseJSON(e.data);
709 reply = $.parseJSON(e.data);
704 var header = reply.header;
710 var header = reply.header;
705 var content = reply.content;
711 var content = reply.content;
706 var msg_type = header.msg_type;
712 var msg_type = header.msg_type;
707 // console.log(reply);
713 // console.log(reply);
708 var cell = this.cell_for_msg(reply.parent_header.msg_id);
714 var cell = this.cell_for_msg(reply.parent_header.msg_id);
709 if (msg_type === "execute_reply") {
715 if (msg_type === "execute_reply") {
710 cell.set_input_prompt(content.execution_count);
716 cell.set_input_prompt(content.execution_count);
711 cell.element.removeClass("running");
717 cell.element.removeClass("running");
712 this.dirty = true;
718 this.dirty = true;
713 } else if (msg_type === "complete_reply") {
719 } else if (msg_type === "complete_reply") {
714 cell.finish_completing(content.matched_text, content.matches);
720 cell.finish_completing(content.matched_text, content.matches);
715 } else if (msg_type === "object_info_reply"){
721 } else if (msg_type === "object_info_reply"){
716 //console.log('back from object_info_request : ')
722 //console.log('back from object_info_request : ')
717 rep = reply.content;
723 rep = reply.content;
718 if(rep.found)
724 if(rep.found)
719 {
725 {
720 cell.finish_tooltip(rep.definition,rep.docstring);
726 cell.finish_tooltip(rep.definition,rep.docstring);
721 }
727 }
722 } else {
728 } else {
723 //console.log("unknown reply:"+msg_type);
729 //console.log("unknown reply:"+msg_type);
724 }
730 }
725 // when having a rely from object_info_reply,
731 // when having a rely from object_info_reply,
726 // no payload so no nned to handle it
732 // no payload so no nned to handle it
727 if(typeof(content.payload)!='undefined') {
733 if(typeof(content.payload)!='undefined') {
728 var payload = content.payload || [];
734 var payload = content.payload || [];
729 this.handle_payload(cell, payload);
735 this.handle_payload(cell, payload);
730 }
736 }
731 };
737 };
732
738
733
739
734 Notebook.prototype.handle_payload = function (cell, payload) {
740 Notebook.prototype.handle_payload = function (cell, payload) {
735 var l = payload.length;
741 var l = payload.length;
736 console.log(payload);
742 console.log(payload);
737 for (var i=0; i<l; i++) {
743 for (var i=0; i<l; i++) {
738 if (payload[i].source === 'IPython.zmq.page.page') {
744 if (payload[i].source === 'IPython.zmq.page.page') {
739 if (payload[i].text.trim() !== '') {
745 if (payload[i].text.trim() !== '') {
740 IPython.pager.clear();
746 IPython.pager.clear();
741 IPython.pager.expand();
747 IPython.pager.expand();
742 IPython.pager.append_text(payload[i].text);
748 IPython.pager.append_text(payload[i].text);
743 }
749 }
744 } else if (payload[i].source === 'IPython.zmq.zmqshell.ZMQInteractiveShell.set_next_input') {
750 } else if (payload[i].source === 'IPython.zmq.zmqshell.ZMQInteractiveShell.set_next_input') {
745 var index = this.find_cell_index(cell);
751 var index = this.find_cell_index(cell);
746 var new_cell = this.insert_code_cell_below(index);
752 var new_cell = this.insert_code_cell_below(index);
747 new_cell.set_code(payload[i].text);
753 new_cell.set_code(payload[i].text);
748 this.dirty = true;
754 this.dirty = true;
749 }
755 }
750 };
756 };
751 };
757 };
752
758
753
759
754 Notebook.prototype.handle_iopub_reply = function (e) {
760 Notebook.prototype.handle_iopub_reply = function (e) {
755 reply = $.parseJSON(e.data);
761 reply = $.parseJSON(e.data);
756 var content = reply.content;
762 var content = reply.content;
757 // console.log(reply);
763 // console.log(reply);
758 var msg_type = reply.header.msg_type;
764 var msg_type = reply.header.msg_type;
759 var cell = this.cell_for_msg(reply.parent_header.msg_id);
765 var cell = this.cell_for_msg(reply.parent_header.msg_id);
760 var output_types = ['stream','display_data','pyout','pyerr'];
766 var output_types = ['stream','display_data','pyout','pyerr'];
761 if (output_types.indexOf(msg_type) >= 0) {
767 if (output_types.indexOf(msg_type) >= 0) {
762 this.handle_output(cell, msg_type, content);
768 this.handle_output(cell, msg_type, content);
763 } else if (msg_type === 'status') {
769 } else if (msg_type === 'status') {
764 if (content.execution_state === 'busy') {
770 if (content.execution_state === 'busy') {
765 IPython.kernel_status_widget.status_busy();
771 IPython.kernel_status_widget.status_busy();
766 } else if (content.execution_state === 'idle') {
772 } else if (content.execution_state === 'idle') {
767 IPython.kernel_status_widget.status_idle();
773 IPython.kernel_status_widget.status_idle();
768 } else if (content.execution_state === 'dead') {
774 } else if (content.execution_state === 'dead') {
769 this.handle_status_dead();
775 this.handle_status_dead();
770 };
776 };
771 } else if (msg_type === 'clear_output') {
777 } else if (msg_type === 'clear_output') {
772 cell.clear_output(content.stdout, content.stderr, content.other);
778 cell.clear_output(content.stdout, content.stderr, content.other);
773 };
779 };
774 };
780 };
775
781
776
782
777 Notebook.prototype.handle_status_dead = function () {
783 Notebook.prototype.handle_status_dead = function () {
778 var that = this;
784 var that = this;
779 this.kernel.stop_channels();
785 this.kernel.stop_channels();
780 var dialog = $('<div/>');
786 var dialog = $('<div/>');
781 dialog.html('The kernel has died, would you like to restart it? If you do not restart the kernel, you will be able to save the notebook, but running code will not work until the notebook is reopened.');
787 dialog.html('The kernel has died, would you like to restart it? If you do not restart the kernel, you will be able to save the notebook, but running code will not work until the notebook is reopened.');
782 $(document).append(dialog);
788 $(document).append(dialog);
783 dialog.dialog({
789 dialog.dialog({
784 resizable: false,
790 resizable: false,
785 modal: true,
791 modal: true,
786 title: "Dead kernel",
792 title: "Dead kernel",
787 buttons : {
793 buttons : {
788 "Restart": function () {
794 "Restart": function () {
789 that.start_kernel();
795 that.start_kernel();
790 $(this).dialog('close');
796 $(this).dialog('close');
791 },
797 },
792 "Continue running": function () {
798 "Continue running": function () {
793 $(this).dialog('close');
799 $(this).dialog('close');
794 }
800 }
795 }
801 }
796 });
802 });
797 };
803 };
798
804
799
805
800 Notebook.prototype.handle_output = function (cell, msg_type, content) {
806 Notebook.prototype.handle_output = function (cell, msg_type, content) {
801 var json = {};
807 var json = {};
802 json.output_type = msg_type;
808 json.output_type = msg_type;
803 if (msg_type === "stream") {
809 if (msg_type === "stream") {
804 json.text = utils.fixConsole(content.data);
810 json.text = utils.fixConsole(content.data);
805 json.stream = content.name;
811 json.stream = content.name;
806 } else if (msg_type === "display_data") {
812 } else if (msg_type === "display_data") {
807 json = this.convert_mime_types(json, content.data);
813 json = this.convert_mime_types(json, content.data);
808 } else if (msg_type === "pyout") {
814 } else if (msg_type === "pyout") {
809 json.prompt_number = content.execution_count;
815 json.prompt_number = content.execution_count;
810 json = this.convert_mime_types(json, content.data);
816 json = this.convert_mime_types(json, content.data);
811 } else if (msg_type === "pyerr") {
817 } else if (msg_type === "pyerr") {
812 json.ename = content.ename;
818 json.ename = content.ename;
813 json.evalue = content.evalue;
819 json.evalue = content.evalue;
814 var traceback = [];
820 var traceback = [];
815 for (var i=0; i<content.traceback.length; i++) {
821 for (var i=0; i<content.traceback.length; i++) {
816 traceback.push(utils.fixConsole(content.traceback[i]));
822 traceback.push(utils.fixConsole(content.traceback[i]));
817 }
823 }
818 json.traceback = traceback;
824 json.traceback = traceback;
819 };
825 };
820 cell.append_output(json);
826 cell.append_output(json);
821 this.dirty = true;
827 this.dirty = true;
822 };
828 };
823
829
824
830
825 Notebook.prototype.convert_mime_types = function (json, data) {
831 Notebook.prototype.convert_mime_types = function (json, data) {
826 if (data['text/plain'] !== undefined) {
832 if (data['text/plain'] !== undefined) {
827 json.text = utils.fixConsole(data['text/plain']);
833 json.text = utils.fixConsole(data['text/plain']);
828 };
834 };
829 if (data['text/html'] !== undefined) {
835 if (data['text/html'] !== undefined) {
830 json.html = data['text/html'];
836 json.html = data['text/html'];
831 };
837 };
832 if (data['image/svg+xml'] !== undefined) {
838 if (data['image/svg+xml'] !== undefined) {
833 json.svg = data['image/svg+xml'];
839 json.svg = data['image/svg+xml'];
834 };
840 };
835 if (data['image/png'] !== undefined) {
841 if (data['image/png'] !== undefined) {
836 json.png = data['image/png'];
842 json.png = data['image/png'];
837 };
843 };
838 if (data['image/jpeg'] !== undefined) {
844 if (data['image/jpeg'] !== undefined) {
839 json.jpeg = data['image/jpeg'];
845 json.jpeg = data['image/jpeg'];
840 };
846 };
841 if (data['text/latex'] !== undefined) {
847 if (data['text/latex'] !== undefined) {
842 json.latex = data['text/latex'];
848 json.latex = data['text/latex'];
843 };
849 };
844 if (data['application/json'] !== undefined) {
850 if (data['application/json'] !== undefined) {
845 json.json = data['application/json'];
851 json.json = data['application/json'];
846 };
852 };
847 if (data['application/javascript'] !== undefined) {
853 if (data['application/javascript'] !== undefined) {
848 json.javascript = data['application/javascript'];
854 json.javascript = data['application/javascript'];
849 }
855 }
850 return json;
856 return json;
851 };
857 };
852
858
853
859
854 Notebook.prototype.execute_selected_cell = function (options) {
860 Notebook.prototype.execute_selected_cell = function (options) {
855 // add_new: should a new cell be added if we are at the end of the nb
861 // add_new: should a new cell be added if we are at the end of the nb
856 // terminal: execute in terminal mode, which stays in the current cell
862 // terminal: execute in terminal mode, which stays in the current cell
857 default_options = {terminal: false, add_new: true}
863 default_options = {terminal: false, add_new: true}
858 $.extend(default_options, options)
864 $.extend(default_options, options)
859 var that = this;
865 var that = this;
860 var cell = that.selected_cell();
866 var cell = that.selected_cell();
861 var cell_index = that.find_cell_index(cell);
867 var cell_index = that.find_cell_index(cell);
862 if (cell instanceof IPython.CodeCell) {
868 if (cell instanceof IPython.CodeCell) {
863 cell.clear_output(true, true, true);
869 cell.clear_output(true, true, true);
864 cell.set_input_prompt('*');
870 cell.set_input_prompt('*');
865 cell.element.addClass("running");
871 cell.element.addClass("running");
866 var code = cell.get_code();
872 var code = cell.get_code();
867 var msg_id = that.kernel.execute(cell.get_code());
873 var msg_id = that.kernel.execute(cell.get_code());
868 that.msg_cell_map[msg_id] = cell.cell_id;
874 that.msg_cell_map[msg_id] = cell.cell_id;
869 } else if (cell instanceof IPython.HTMLCell) {
875 } else if (cell instanceof IPython.HTMLCell) {
870 cell.render();
876 cell.render();
871 }
877 }
872 if (default_options.terminal) {
878 if (default_options.terminal) {
873 cell.select_all();
879 cell.select_all();
874 } else {
880 } else {
875 if ((cell_index === (that.ncells()-1)) && default_options.add_new) {
881 if ((cell_index === (that.ncells()-1)) && default_options.add_new) {
876 that.insert_code_cell_below();
882 that.insert_code_cell_below();
877 // If we are adding a new cell at the end, scroll down to show it.
883 // If we are adding a new cell at the end, scroll down to show it.
878 that.scroll_to_bottom();
884 that.scroll_to_bottom();
879 } else {
885 } else {
880 that.select(cell_index+1);
886 that.select(cell_index+1);
881 };
887 };
882 };
888 };
883 this.dirty = true;
889 this.dirty = true;
884 };
890 };
885
891
886
892
887 Notebook.prototype.execute_all_cells = function () {
893 Notebook.prototype.execute_all_cells = function () {
888 var ncells = this.ncells();
894 var ncells = this.ncells();
889 for (var i=0; i<ncells; i++) {
895 for (var i=0; i<ncells; i++) {
890 this.select(i);
896 this.select(i);
891 this.execute_selected_cell({add_new:false});
897 this.execute_selected_cell({add_new:false});
892 };
898 };
893 this.scroll_to_bottom();
899 this.scroll_to_bottom();
894 };
900 };
895
901
896
902
897 Notebook.prototype.request_tool_tip = function (cell,func) {
903 Notebook.prototype.request_tool_tip = function (cell,func) {
898 // Feel free to shorten this logic if you are better
904 // Feel free to shorten this logic if you are better
899 // than me in regEx
905 // than me in regEx
900 // basicaly you shoul be able to get xxx.xxx.xxx from
906 // basicaly you shoul be able to get xxx.xxx.xxx from
901 // something(range(10), kwarg=smth) ; xxx.xxx.xxx( firstarg, rand(234,23), kwarg1=2,
907 // something(range(10), kwarg=smth) ; xxx.xxx.xxx( firstarg, rand(234,23), kwarg1=2,
902 // remove everything between matchin bracket (need to iterate)
908 // remove everything between matchin bracket (need to iterate)
903 matchBracket = /\([^\(\)]+\)/g;
909 matchBracket = /\([^\(\)]+\)/g;
904 oldfunc = func;
910 oldfunc = func;
905 func = func.replace(matchBracket,"");
911 func = func.replace(matchBracket,"");
906 while( oldfunc != func )
912 while( oldfunc != func )
907 {
913 {
908 oldfunc = func;
914 oldfunc = func;
909 func = func.replace(matchBracket,"");
915 func = func.replace(matchBracket,"");
910 }
916 }
911 // remove everythin after last open bracket
917 // remove everythin after last open bracket
912 endBracket = /\([^\(]*$/g;
918 endBracket = /\([^\(]*$/g;
913 func = func.replace(endBracket,"");
919 func = func.replace(endBracket,"");
914 var re = /[a-zA-Z._]+$/g;
920 var re = /[a-zA-Z._]+$/g;
915 var msg_id = this.kernel.object_info_request(re.exec(func));
921 var msg_id = this.kernel.object_info_request(re.exec(func));
916 this.msg_cell_map[msg_id] = cell.cell_id;
922 this.msg_cell_map[msg_id] = cell.cell_id;
917 };
923 };
918
924
919 Notebook.prototype.complete_cell = function (cell, line, cursor_pos) {
925 Notebook.prototype.complete_cell = function (cell, line, cursor_pos) {
920 var msg_id = this.kernel.complete(line, cursor_pos);
926 var msg_id = this.kernel.complete(line, cursor_pos);
921 this.msg_cell_map[msg_id] = cell.cell_id;
927 this.msg_cell_map[msg_id] = cell.cell_id;
922 };
928 };
923
929
924 // Persistance and loading
930 // Persistance and loading
925
931
926
932
927 Notebook.prototype.fromJSON = function (data) {
933 Notebook.prototype.fromJSON = function (data) {
928 var ncells = this.ncells();
934 var ncells = this.ncells();
929 for (var i=0; i<ncells; i++) {
935 for (var i=0; i<ncells; i++) {
930 // Always delete cell 0 as they get renumbered as they are deleted.
936 // Always delete cell 0 as they get renumbered as they are deleted.
931 this.delete_cell(0);
937 this.delete_cell(0);
932 };
938 };
933 // Save the metadata
939 // Save the metadata
934 this.metadata = data.metadata;
940 this.metadata = data.metadata;
935 // Only handle 1 worksheet for now.
941 // Only handle 1 worksheet for now.
936 var worksheet = data.worksheets[0];
942 var worksheet = data.worksheets[0];
937 if (worksheet !== undefined) {
943 if (worksheet !== undefined) {
938 var new_cells = worksheet.cells;
944 var new_cells = worksheet.cells;
939 ncells = new_cells.length;
945 ncells = new_cells.length;
940 var cell_data = null;
946 var cell_data = null;
941 var new_cell = null;
947 var new_cell = null;
942 for (var i=0; i<ncells; i++) {
948 for (var i=0; i<ncells; i++) {
943 cell_data = new_cells[i];
949 cell_data = new_cells[i];
944 if (cell_data.cell_type == 'code') {
950 if (cell_data.cell_type == 'code') {
945 new_cell = this.insert_code_cell_below();
951 new_cell = this.insert_code_cell_below();
946 new_cell.fromJSON(cell_data);
952 new_cell.fromJSON(cell_data);
947 } else if (cell_data.cell_type === 'html') {
953 } else if (cell_data.cell_type === 'html') {
948 new_cell = this.insert_html_cell_below();
954 new_cell = this.insert_html_cell_below();
949 new_cell.fromJSON(cell_data);
955 new_cell.fromJSON(cell_data);
950 } else if (cell_data.cell_type === 'markdown') {
956 } else if (cell_data.cell_type === 'markdown') {
951 new_cell = this.insert_markdown_cell_below();
957 new_cell = this.insert_markdown_cell_below();
952 new_cell.fromJSON(cell_data);
958 new_cell.fromJSON(cell_data);
953 };
959 };
954 };
960 };
955 };
961 };
956 };
962 };
957
963
958
964
959 Notebook.prototype.toJSON = function () {
965 Notebook.prototype.toJSON = function () {
960 var cells = this.cells();
966 var cells = this.cells();
961 var ncells = cells.length;
967 var ncells = cells.length;
962 cell_array = new Array(ncells);
968 cell_array = new Array(ncells);
963 for (var i=0; i<ncells; i++) {
969 for (var i=0; i<ncells; i++) {
964 cell_array[i] = cells[i].toJSON();
970 cell_array[i] = cells[i].toJSON();
965 };
971 };
966 data = {
972 data = {
967 // Only handle 1 worksheet for now.
973 // Only handle 1 worksheet for now.
968 worksheets : [{cells:cell_array}],
974 worksheets : [{cells:cell_array}],
969 metadata : this.metadata
975 metadata : this.metadata
970 }
976 }
971 return data
977 return data
972 };
978 };
973
979
974 Notebook.prototype.save_notebook = function () {
980 Notebook.prototype.save_notebook = function () {
975 if (IPython.save_widget.test_notebook_name()) {
981 if (IPython.save_widget.test_notebook_name()) {
976 var notebook_id = IPython.save_widget.get_notebook_id();
982 var notebook_id = IPython.save_widget.get_notebook_id();
977 var nbname = IPython.save_widget.get_notebook_name();
983 var nbname = IPython.save_widget.get_notebook_name();
978 // We may want to move the name/id/nbformat logic inside toJSON?
984 // We may want to move the name/id/nbformat logic inside toJSON?
979 var data = this.toJSON();
985 var data = this.toJSON();
980 data.metadata.name = nbname;
986 data.metadata.name = nbname;
981 data.nbformat = 2;
987 data.nbformat = 2;
982 // We do the call with settings so we can set cache to false.
988 // We do the call with settings so we can set cache to false.
983 var settings = {
989 var settings = {
984 processData : false,
990 processData : false,
985 cache : false,
991 cache : false,
986 type : "PUT",
992 type : "PUT",
987 data : JSON.stringify(data),
993 data : JSON.stringify(data),
988 headers : {'Content-Type': 'application/json'},
994 headers : {'Content-Type': 'application/json'},
989 success : $.proxy(this.notebook_saved,this),
995 success : $.proxy(this.notebook_saved,this),
990 error : $.proxy(this.notebook_save_failed,this)
996 error : $.proxy(this.notebook_save_failed,this)
991 };
997 };
992 IPython.save_widget.status_saving();
998 IPython.save_widget.status_saving();
993 var url = $('body').data('baseProjectUrl') + 'notebooks/' + notebook_id
999 var url = $('body').data('baseProjectUrl') + 'notebooks/' + notebook_id
994 $.ajax(url, settings);
1000 $.ajax(url, settings);
995 };
1001 };
996 };
1002 };
997
1003
998
1004
999 Notebook.prototype.notebook_saved = function (data, status, xhr) {
1005 Notebook.prototype.notebook_saved = function (data, status, xhr) {
1000 this.dirty = false;
1006 this.dirty = false;
1001 IPython.save_widget.notebook_saved();
1007 IPython.save_widget.notebook_saved();
1002 IPython.save_widget.status_save();
1008 IPython.save_widget.status_save();
1003 }
1009 }
1004
1010
1005
1011
1006 Notebook.prototype.notebook_save_failed = function (xhr, status, error_msg) {
1012 Notebook.prototype.notebook_save_failed = function (xhr, status, error_msg) {
1007 // Notify the user and reset the save button
1013 // Notify the user and reset the save button
1008 // TODO: Handle different types of errors (timeout etc.)
1014 // TODO: Handle different types of errors (timeout etc.)
1009 alert('An unexpected error occured while saving the notebook.');
1015 alert('An unexpected error occured while saving the notebook.');
1010 IPython.save_widget.reset_status();
1016 IPython.save_widget.reset_status();
1011 }
1017 }
1012
1018
1013
1019
1014 Notebook.prototype.load_notebook = function (callback) {
1020 Notebook.prototype.load_notebook = function (callback) {
1015 var that = this;
1021 var that = this;
1016 var notebook_id = IPython.save_widget.get_notebook_id();
1022 var notebook_id = IPython.save_widget.get_notebook_id();
1017 // We do the call with settings so we can set cache to false.
1023 // We do the call with settings so we can set cache to false.
1018 var settings = {
1024 var settings = {
1019 processData : false,
1025 processData : false,
1020 cache : false,
1026 cache : false,
1021 type : "GET",
1027 type : "GET",
1022 dataType : "json",
1028 dataType : "json",
1023 success : function (data, status, xhr) {
1029 success : function (data, status, xhr) {
1024 that.notebook_loaded(data, status, xhr);
1030 that.notebook_loaded(data, status, xhr);
1025 if (callback !== undefined) {
1031 if (callback !== undefined) {
1026 callback();
1032 callback();
1027 };
1033 };
1028 }
1034 }
1029 };
1035 };
1030 IPython.save_widget.status_loading();
1036 IPython.save_widget.status_loading();
1031 var url = $('body').data('baseProjectUrl') + 'notebooks/' + notebook_id
1037 var url = $('body').data('baseProjectUrl') + 'notebooks/' + notebook_id
1032 $.ajax(url, settings);
1038 $.ajax(url, settings);
1033 }
1039 }
1034
1040
1035
1041
1036 Notebook.prototype.notebook_loaded = function (data, status, xhr) {
1042 Notebook.prototype.notebook_loaded = function (data, status, xhr) {
1037 var allowed = xhr.getResponseHeader('Allow');
1043 var allowed = xhr.getResponseHeader('Allow');
1038 this.fromJSON(data);
1044 this.fromJSON(data);
1039 if (this.ncells() === 0) {
1045 if (this.ncells() === 0) {
1040 this.insert_code_cell_below();
1046 this.insert_code_cell_below();
1041 };
1047 };
1042 IPython.save_widget.status_save();
1048 IPython.save_widget.status_save();
1043 IPython.save_widget.set_notebook_name(data.metadata.name);
1049 IPython.save_widget.set_notebook_name(data.metadata.name);
1044 this.dirty = false;
1050 this.dirty = false;
1045 if (! this.read_only) {
1051 if (! this.read_only) {
1046 this.start_kernel();
1052 this.start_kernel();
1047 }
1053 }
1048 // fromJSON always selects the last cell inserted. We need to wait
1054 // fromJSON always selects the last cell inserted. We need to wait
1049 // until that is done before scrolling to the top.
1055 // until that is done before scrolling to the top.
1050 setTimeout(function () {
1056 setTimeout(function () {
1051 IPython.notebook.select(0);
1057 IPython.notebook.select(0);
1052 IPython.notebook.scroll_to_top();
1058 IPython.notebook.scroll_to_top();
1053 }, 50);
1059 }, 50);
1054 };
1060 };
1055
1061
1056 IPython.Notebook = Notebook;
1062 IPython.Notebook = Notebook;
1057
1063
1058
1064
1059 return IPython;
1065 return IPython;
1060
1066
1061 }(IPython));
1067 }(IPython));
1062
1068
@@ -1,327 +1,333
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 // PanelSection
9 // PanelSection
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
15
16 // Base PanelSection class
16 // Base PanelSection class
17
17
18 var PanelSection = function (selector) {
18 var PanelSection = function (selector) {
19 this.selector = selector;
19 this.selector = selector;
20 if (this.selector !== undefined) {
20 if (this.selector !== undefined) {
21 this.element = $(selector);
21 this.element = $(selector);
22 this.header = this.element.find('div.section_header');
22 this.header = this.element.find('div.section_header');
23 this.content = this.element.find('div.section_content');
23 this.content = this.element.find('div.section_content');
24 this.style();
24 this.style();
25 this.bind_events();
25 this.bind_events();
26 }
26 }
27 this.expanded = true;
27 this.expanded = true;
28 };
28 };
29
29
30
30
31 PanelSection.prototype.style = function () {
31 PanelSection.prototype.style = function () {
32 this.header.addClass('ui-widget ui-state-default ui-helper-clearfix');
32 this.header.addClass('ui-widget ui-state-default ui-helper-clearfix');
33 this.header.attr('title', "Click to Show/Hide Section");
33 this.header.attr('title', "Click to Show/Hide Section");
34 this.content.addClass('ui-widget section_content');
34 this.content.addClass('ui-widget section_content');
35 };
35 };
36
36
37
37
38 PanelSection.prototype.bind_events = function () {
38 PanelSection.prototype.bind_events = function () {
39 var that = this;
39 var that = this;
40 this.header.click(function () {
40 this.header.click(function () {
41 that.toggle();
41 that.toggle();
42 });
42 });
43 this.header.hover(function () {
43 this.header.hover(function () {
44 that.header.toggleClass('ui-state-hover');
44 that.header.toggleClass('ui-state-hover');
45 });
45 });
46 };
46 };
47
47
48
48
49 PanelSection.prototype.expand = function () {
49 PanelSection.prototype.expand = function () {
50 if (!this.expanded) {
50 if (!this.expanded) {
51 this.content.slideDown('fast');
51 this.content.slideDown('fast');
52 this.expanded = true;
52 this.expanded = true;
53 };
53 };
54 };
54 };
55
55
56
56
57 PanelSection.prototype.collapse = function () {
57 PanelSection.prototype.collapse = function () {
58 if (this.expanded) {
58 if (this.expanded) {
59 this.content.slideUp('fast');
59 this.content.slideUp('fast');
60 this.expanded = false;
60 this.expanded = false;
61 };
61 };
62 };
62 };
63
63
64
64
65 PanelSection.prototype.toggle = function () {
65 PanelSection.prototype.toggle = function () {
66 if (this.expanded === true) {
66 if (this.expanded === true) {
67 this.collapse();
67 this.collapse();
68 } else {
68 } else {
69 this.expand();
69 this.expand();
70 };
70 };
71 };
71 };
72
72
73
73
74 PanelSection.prototype.create_children = function () {};
74 PanelSection.prototype.create_children = function () {};
75
75
76
76
77 // NotebookSection
77 // NotebookSection
78
78
79 var NotebookSection = function () {
79 var NotebookSection = function () {
80 PanelSection.apply(this, arguments);
80 PanelSection.apply(this, arguments);
81 };
81 };
82
82
83
83
84 NotebookSection.prototype = new PanelSection();
84 NotebookSection.prototype = new PanelSection();
85
85
86
86
87 NotebookSection.prototype.style = function () {
87 NotebookSection.prototype.style = function () {
88 PanelSection.prototype.style.apply(this);
88 PanelSection.prototype.style.apply(this);
89 this.content.addClass('ui-helper-clearfix');
89 this.content.addClass('ui-helper-clearfix');
90 this.content.find('div.section_row').addClass('ui-helper-clearfix');
90 this.content.find('div.section_row').addClass('ui-helper-clearfix');
91 this.content.find('#new_open').buttonset();
91 this.content.find('#new_open').buttonset();
92 this.content.find('#new_notebook').attr('title', "Create a new notebook");
92 this.content.find('#new_notebook').attr('title', "Create a new notebook");
93 this.content.find('#open_notebook').attr('title', "Open an existing notebook");
93 this.content.find('#open_notebook').attr('title', "Open an existing notebook");
94 this.content.find('#download_notebook').button();
94 this.content.find('#download_notebook').button();
95 this.content.find('#download_notebook').attr('title',
95 this.content.find('#download_notebook').attr('title',
96 "Download the notebook in the specified format," +
96 "Download the notebook in the specified format," +
97 " either full ipynb notebook or as a Python script." +
97 " either full ipynb notebook or as a Python script." +
98 " Make sure to save before downloading, to ensure the file is up to date."
98 " Make sure to save before downloading, to ensure the file is up to date."
99 );
99 );
100 // upload notebook doesn't exist:
100 // upload notebook doesn't exist:
101 this.content.find('#upload_notebook').button();
101 this.content.find('#upload_notebook').button();
102 this.content.find('#download_format').addClass('ui-widget ui-widget-content');
102 this.content.find('#download_format').addClass('ui-widget ui-widget-content');
103 this.content.find('#download_format option').addClass('ui-widget ui-widget-content');
103 this.content.find('#download_format option').addClass('ui-widget ui-widget-content');
104 };
104 };
105
105
106
106
107 NotebookSection.prototype.bind_events = function () {
107 NotebookSection.prototype.bind_events = function () {
108 PanelSection.prototype.bind_events.apply(this);
108 PanelSection.prototype.bind_events.apply(this);
109 var that = this;
109 var that = this;
110 this.content.find('#new_notebook').click(function () {
110 this.content.find('#new_notebook').click(function () {
111 window.open($('body').data('baseProjectUrl')+'new');
111 window.open($('body').data('baseProjectUrl')+'new');
112 });
112 });
113 this.content.find('#open_notebook').click(function () {
113 this.content.find('#open_notebook').click(function () {
114 window.open($('body').data('baseProjectUrl'));
114 window.open($('body').data('baseProjectUrl'));
115 });
115 });
116 this.content.find('#download_notebook').click(function () {
116 this.content.find('#download_notebook').click(function () {
117 var format = that.content.find('#download_format').val();
117 var format = that.content.find('#download_format').val();
118 var notebook_id = IPython.save_widget.get_notebook_id();
118 var notebook_id = IPython.save_widget.get_notebook_id();
119 var url = $('body').data('baseProjectUrl') + 'notebooks/' + notebook_id + '?format=' + format;
119 var url = $('body').data('baseProjectUrl') + 'notebooks/' + notebook_id + '?format=' + format;
120 window.open(url,'_newtab');
120 window.open(url,'_newtab');
121 });
121 });
122 };
122 };
123
123
124 // ConfigSection
124 // ConfigSection
125
125
126 var ConfigSection = function () {
126 var ConfigSection = function () {
127 PanelSection.apply(this, arguments);
127 PanelSection.apply(this, arguments);
128 };
128 };
129
129
130 ConfigSection.prototype = new PanelSection();
130 ConfigSection.prototype = new PanelSection();
131
131
132 ConfigSection.prototype.style = function () {
132 ConfigSection.prototype.style = function () {
133 PanelSection.prototype.style.apply(this);
133 PanelSection.prototype.style.apply(this);
134 this.content.addClass('ui-helper-clearfix');
134 this.content.addClass('ui-helper-clearfix');
135 this.content.find('div.section_row').addClass('ui-helper-clearfix');
135 this.content.find('div.section_row').addClass('ui-helper-clearfix');
136
136
137 this.content.find('#tooltipontab').attr('title', 'Show tooltip if yuo press <Tab> after "(" or a white space');
137 this.content.find('#tooltipontab').attr('title', 'Show tooltip if yuo press <Tab> after "(" or a white space');
138 this.content.find('#tooltipontab_label').attr('title', 'Show Tooltip when pressing Tab');
138 this.content.find('#tooltipontab_label').attr('title', 'Show Tooltip when pressing Tab');
139
139
140 this.content.find('#timebeforetooltip').attr('title', 'Time before a tooltip auto-appear when "(" is pressed (negative value supress tooltip)');
140 this.content.find('#timebeforetooltip').attr('title', 'Time before a tooltip auto-appear when "(" is pressed (negative value supress tooltip)');
141 this.content.find('#timebeforetooltip_label').attr('title', 'Time before a tooltip auto-appear when "(" is pressed (negative value supress tooltip)');
141 this.content.find('#timebeforetooltip_label').attr('title', 'Time before a tooltip auto-appear when "(" is pressed (negative value supress tooltip)');
142
142
143 this.content.find('#smartcompleter').attr('title', 'When inside function call, completer try to propose kwargs first');
144 this.content.find('#smartcompleter_label').attr('title', 'When inside function call, completer try to propose kwargs first');
143 };
145 };
144
146
145
147
146 ConfigSection.prototype.bind_events = function () {
148 ConfigSection.prototype.bind_events = function () {
147 PanelSection.prototype.bind_events.apply(this);
149 PanelSection.prototype.bind_events.apply(this);
148 this.content.find('#tooltipontab').change(function () {
150 this.content.find('#tooltipontab').change(function () {
149 var state = $('#tooltipontab').prop('checked');
151 var state = $('#tooltipontab').prop('checked');
150 IPython.notebook.set_tooltipontab(state);
152 IPython.notebook.set_tooltipontab(state);
151 });
153 });
152 this.content.find('#timebeforetooltip').change(function () {
154 this.content.find('#timebeforetooltip').change(function () {
153 var state = $('#timebeforetooltip').prop('value');
155 var state = $('#timebeforetooltip').prop('value');
154 IPython.notebook.set_timebeforetooltip(state);
156 IPython.notebook.set_timebeforetooltip(state);
155 });
157 });
158 this.content.find('#smartcompleter').change(function () {
159 var state = $('#smartcompleter').prop('checked');
160 IPython.notebook.set_smartcompleter(state);
161 });
156 };
162 };
157
163
158 // CellSection
164 // CellSection
159
165
160 var CellSection = function () {
166 var CellSection = function () {
161 PanelSection.apply(this, arguments);
167 PanelSection.apply(this, arguments);
162 };
168 };
163
169
164 CellSection.prototype = new PanelSection();
170 CellSection.prototype = new PanelSection();
165
171
166
172
167 CellSection.prototype.style = function () {
173 CellSection.prototype.style = function () {
168 PanelSection.prototype.style.apply(this);
174 PanelSection.prototype.style.apply(this);
169 this.content.addClass('ui-helper-clearfix');
175 this.content.addClass('ui-helper-clearfix');
170 this.content.find('div.section_row').addClass('ui-helper-clearfix');
176 this.content.find('div.section_row').addClass('ui-helper-clearfix');
171 this.content.find('#delete_cell').button();
177 this.content.find('#delete_cell').button();
172 this.content.find('#delete_cell').attr('title', "Delete the selected cell");
178 this.content.find('#delete_cell').attr('title', "Delete the selected cell");
173
179
174 this.content.find('#insert').buttonset();
180 this.content.find('#insert').buttonset();
175 this.content.find('#insert_cell_above').attr('title', "Insert new cell above selected");
181 this.content.find('#insert_cell_above').attr('title', "Insert new cell above selected");
176 this.content.find('#insert_cell_below').attr('title', "Insert new cell below selected");
182 this.content.find('#insert_cell_below').attr('title', "Insert new cell below selected");
177
183
178 this.content.find('#move').buttonset();
184 this.content.find('#move').buttonset();
179 this.content.find('#move_cell_up').attr('title', "Move selected cell up one in the Notebook");
185 this.content.find('#move_cell_up').attr('title', "Move selected cell up one in the Notebook");
180 this.content.find('#move_cell_down').attr('title', "Move selected cell down one in the Notebook");
186 this.content.find('#move_cell_down').attr('title', "Move selected cell down one in the Notebook");
181
187
182 this.content.find('#cell_type').buttonset();
188 this.content.find('#cell_type').buttonset();
183 this.content.find('#to_markdown').attr('title', 'Change selected cell to markdown (for text)')
189 this.content.find('#to_markdown').attr('title', 'Change selected cell to markdown (for text)')
184 this.content.find('#to_code').attr('title', 'Change selected cell to code (for execution)')
190 this.content.find('#to_code').attr('title', 'Change selected cell to code (for execution)')
185
191
186 this.content.find('#cell_output').buttonset();
192 this.content.find('#cell_output').buttonset();
187 this.content.find('#toggle_output').attr('title', 'Toggle visibility of the output of code cells')
193 this.content.find('#toggle_output').attr('title', 'Toggle visibility of the output of code cells')
188 this.content.find('#clear_all_output').attr('title', 'Clear output of all code cells (actually removes the data, unlike toggle)')
194 this.content.find('#clear_all_output').attr('title', 'Clear output of all code cells (actually removes the data, unlike toggle)')
189
195
190 this.content.find('#run_cells').buttonset();
196 this.content.find('#run_cells').buttonset();
191 this.content.find('#run_selected_cell').attr('title', 'Submit the selected cell for execution')
197 this.content.find('#run_selected_cell').attr('title', 'Submit the selected cell for execution')
192 this.content.find('#run_all_cells').attr('title', 'Run *all* code cells in the notebook in order')
198 this.content.find('#run_all_cells').attr('title', 'Run *all* code cells in the notebook in order')
193 this.content.find('#autoindent').attr('title', 'Autoindent code as-you-type')
199 this.content.find('#autoindent').attr('title', 'Autoindent code as-you-type')
194 this.content.find('#autoindent_label').attr('title', 'Autoindent code as-you-type')
200 this.content.find('#autoindent_label').attr('title', 'Autoindent code as-you-type')
195 };
201 };
196
202
197
203
198 CellSection.prototype.bind_events = function () {
204 CellSection.prototype.bind_events = function () {
199 PanelSection.prototype.bind_events.apply(this);
205 PanelSection.prototype.bind_events.apply(this);
200 this.content.find('#toggle_output').click(function () {
206 this.content.find('#toggle_output').click(function () {
201 IPython.notebook.toggle_output();
207 IPython.notebook.toggle_output();
202 });
208 });
203 this.content.find('#clear_all_output').click(function () {
209 this.content.find('#clear_all_output').click(function () {
204 IPython.notebook.clear_all_output();
210 IPython.notebook.clear_all_output();
205 });
211 });
206 this.content.find('#delete_cell').click(function () {
212 this.content.find('#delete_cell').click(function () {
207 IPython.notebook.delete_cell();
213 IPython.notebook.delete_cell();
208 });
214 });
209 this.content.find('#insert_cell_above').click(function () {
215 this.content.find('#insert_cell_above').click(function () {
210 IPython.notebook.insert_code_cell_above();
216 IPython.notebook.insert_code_cell_above();
211 });
217 });
212 this.content.find('#insert_cell_below').click(function () {
218 this.content.find('#insert_cell_below').click(function () {
213 IPython.notebook.insert_code_cell_below();
219 IPython.notebook.insert_code_cell_below();
214 });
220 });
215 this.content.find('#move_cell_up').click(function () {
221 this.content.find('#move_cell_up').click(function () {
216 IPython.notebook.move_cell_up();
222 IPython.notebook.move_cell_up();
217 });
223 });
218 this.content.find('#move_cell_down').click(function () {
224 this.content.find('#move_cell_down').click(function () {
219 IPython.notebook.move_cell_down();
225 IPython.notebook.move_cell_down();
220 });
226 });
221 this.content.find('#to_code').click(function () {
227 this.content.find('#to_code').click(function () {
222 IPython.notebook.to_code();
228 IPython.notebook.to_code();
223 });
229 });
224 this.content.find('#to_markdown').click(function () {
230 this.content.find('#to_markdown').click(function () {
225 IPython.notebook.to_markdown();
231 IPython.notebook.to_markdown();
226 });
232 });
227 this.content.find('#run_selected_cell').click(function () {
233 this.content.find('#run_selected_cell').click(function () {
228 IPython.notebook.execute_selected_cell();
234 IPython.notebook.execute_selected_cell();
229 });
235 });
230 this.content.find('#run_all_cells').click(function () {
236 this.content.find('#run_all_cells').click(function () {
231 IPython.notebook.execute_all_cells();
237 IPython.notebook.execute_all_cells();
232 });
238 });
233 this.content.find('#autoindent').change(function () {
239 this.content.find('#autoindent').change(function () {
234 var state = $('#autoindent').prop('checked');
240 var state = $('#autoindent').prop('checked');
235 IPython.notebook.set_autoindent(state);
241 IPython.notebook.set_autoindent(state);
236 });
242 });
237 this.content.find('#tooltipontab').change(function () {
243 this.content.find('#tooltipontab').change(function () {
238 var state = $('#tooltipontab').prop('checked');
244 var state = $('#tooltipontab').prop('checked');
239 IPython.notebook.set_tooltipontab(state);
245 IPython.notebook.set_tooltipontab(state);
240 });
246 });
241 };
247 };
242
248
243
249
244 // KernelSection
250 // KernelSection
245
251
246 var KernelSection = function () {
252 var KernelSection = function () {
247 PanelSection.apply(this, arguments);
253 PanelSection.apply(this, arguments);
248 };
254 };
249
255
250
256
251 KernelSection.prototype = new PanelSection();
257 KernelSection.prototype = new PanelSection();
252
258
253
259
254 KernelSection.prototype.style = function () {
260 KernelSection.prototype.style = function () {
255 PanelSection.prototype.style.apply(this);
261 PanelSection.prototype.style.apply(this);
256 this.content.addClass('ui-helper-clearfix');
262 this.content.addClass('ui-helper-clearfix');
257 this.content.find('div.section_row').addClass('ui-helper-clearfix');
263 this.content.find('div.section_row').addClass('ui-helper-clearfix');
258 this.content.find('#int_restart').buttonset();
264 this.content.find('#int_restart').buttonset();
259 this.content.find("#int_kernel").attr('title', "Interrupt the kernel with SIGINT/Ctrl-C");
265 this.content.find("#int_kernel").attr('title', "Interrupt the kernel with SIGINT/Ctrl-C");
260 this.content.find("#restart_kernel").attr('title',
266 this.content.find("#restart_kernel").attr('title',
261 "Restart the kernel. This will shutdown the current kernel," +
267 "Restart the kernel. This will shutdown the current kernel," +
262 " and start a new, clean kernel in its place, connected to this Notebook." +
268 " and start a new, clean kernel in its place, connected to this Notebook." +
263 " This may break the connection of other clients connected to this kernel." );
269 " This may break the connection of other clients connected to this kernel." );
264 var kill_tip = "Kill the kernel on exit. If unchecked, the kernel will remain" +
270 var kill_tip = "Kill the kernel on exit. If unchecked, the kernel will remain" +
265 " active after closing the session, allowing you to reconnect and resume later.";
271 " active after closing the session, allowing you to reconnect and resume later.";
266 this.content.find('#kill_kernel').attr('title', kill_tip);
272 this.content.find('#kill_kernel').attr('title', kill_tip);
267 this.content.find('#kill_kernel_label').attr('title', kill_tip);
273 this.content.find('#kill_kernel_label').attr('title', kill_tip);
268
274
269 };
275 };
270
276
271
277
272 KernelSection.prototype.bind_events = function () {
278 KernelSection.prototype.bind_events = function () {
273 PanelSection.prototype.bind_events.apply(this);
279 PanelSection.prototype.bind_events.apply(this);
274 this.content.find('#restart_kernel').click(function () {
280 this.content.find('#restart_kernel').click(function () {
275 IPython.notebook.restart_kernel();
281 IPython.notebook.restart_kernel();
276 });
282 });
277 this.content.find('#int_kernel').click(function () {
283 this.content.find('#int_kernel').click(function () {
278 IPython.notebook.kernel.interrupt();
284 IPython.notebook.kernel.interrupt();
279 });
285 });
280 };
286 };
281
287
282
288
283 // HelpSection
289 // HelpSection
284
290
285 var HelpSection = function () {
291 var HelpSection = function () {
286 PanelSection.apply(this, arguments);
292 PanelSection.apply(this, arguments);
287 };
293 };
288
294
289
295
290 HelpSection.prototype = new PanelSection();
296 HelpSection.prototype = new PanelSection();
291
297
292
298
293 HelpSection.prototype.style = function () {
299 HelpSection.prototype.style = function () {
294 PanelSection.prototype.style.apply(this);
300 PanelSection.prototype.style.apply(this);
295 PanelSection.prototype.style.apply(this);
301 PanelSection.prototype.style.apply(this);
296 this.content.addClass('ui-helper-clearfix');
302 this.content.addClass('ui-helper-clearfix');
297 this.content.find('div.section_row').addClass('ui-helper-clearfix');
303 this.content.find('div.section_row').addClass('ui-helper-clearfix');
298 this.content.find('#help_buttons0').buttonset();
304 this.content.find('#help_buttons0').buttonset();
299 this.content.find('#help_buttons1').buttonset();
305 this.content.find('#help_buttons1').buttonset();
300 this.content.find('#help_buttons2').buttonset();
306 this.content.find('#help_buttons2').buttonset();
301 this.content.find('#python_help').attr('title', "Open the online Python documentation in a new tab")
307 this.content.find('#python_help').attr('title', "Open the online Python documentation in a new tab")
302 this.content.find('#ipython_help').attr('title', "Open the online IPython documentation in a new tab")
308 this.content.find('#ipython_help').attr('title', "Open the online IPython documentation in a new tab")
303 this.content.find('#numpy_help').attr('title', "Open the online NumPy documentation in a new tab")
309 this.content.find('#numpy_help').attr('title', "Open the online NumPy documentation in a new tab")
304 this.content.find('#scipy_help').attr('title', "Open the online SciPy documentation in a new tab")
310 this.content.find('#scipy_help').attr('title', "Open the online SciPy documentation in a new tab")
305 this.content.find('#matplotlib_help').attr('title', "Open the online Matplotlib documentation in a new tab")
311 this.content.find('#matplotlib_help').attr('title', "Open the online Matplotlib documentation in a new tab")
306 this.content.find('#sympy_help').attr('title', "Open the online SymPy documentation in a new tab")
312 this.content.find('#sympy_help').attr('title', "Open the online SymPy documentation in a new tab")
307 };
313 };
308
314
309
315
310 HelpSection.prototype.bind_events = function () {
316 HelpSection.prototype.bind_events = function () {
311 PanelSection.prototype.bind_events.apply(this);
317 PanelSection.prototype.bind_events.apply(this);
312 };
318 };
313
319
314
320
315 // Set module variables
321 // Set module variables
316
322
317 IPython.PanelSection = PanelSection;
323 IPython.PanelSection = PanelSection;
318 IPython.NotebookSection = NotebookSection;
324 IPython.NotebookSection = NotebookSection;
319 IPython.CellSection = CellSection;
325 IPython.CellSection = CellSection;
320 IPython.ConfigSection = ConfigSection;
326 IPython.ConfigSection = ConfigSection;
321 IPython.KernelSection = KernelSection;
327 IPython.KernelSection = KernelSection;
322 IPython.HelpSection = HelpSection;
328 IPython.HelpSection = HelpSection;
323
329
324 return IPython;
330 return IPython;
325
331
326 }(IPython));
332 }(IPython));
327
333
@@ -1,321 +1,327
1 <!DOCTYPE HTML>
1 <!DOCTYPE HTML>
2 <html>
2 <html>
3
3
4 <head>
4 <head>
5 <meta charset="utf-8">
5 <meta charset="utf-8">
6
6
7 <title>IPython Notebook</title>
7 <title>IPython Notebook</title>
8
8
9 <!-- <script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_HTML" charset="utf-8"></script> -->
9 <!-- <script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_HTML" charset="utf-8"></script> -->
10 <script type='text/javascript' src='static/mathjax/MathJax.js?config=TeX-AMS_HTML' charset='utf-8'></script>
10 <script type='text/javascript' src='static/mathjax/MathJax.js?config=TeX-AMS_HTML' charset='utf-8'></script>
11 <script type="text/javascript">
11 <script type="text/javascript">
12 function CheckMathJax(){
12 function CheckMathJax(){
13 var div=document.getElementById("MathJaxFetchingWarning")
13 var div=document.getElementById("MathJaxFetchingWarning")
14 if(window.MathJax){
14 if(window.MathJax){
15 document.body.removeChild(div)
15 document.body.removeChild(div)
16 }
16 }
17 else{
17 else{
18 div.style.display = "block";
18 div.style.display = "block";
19 }
19 }
20 }
20 }
21 if (typeof MathJax == 'undefined') {
21 if (typeof MathJax == 'undefined') {
22 console.log("No local MathJax, loading from CDN");
22 console.log("No local MathJax, loading from CDN");
23 document.write(unescape("%3Cscript type='text/javascript' src='http://cdn.mathjax.org/mathjax/latest/MathJax.js%3Fconfig=TeX-AMS_HTML' charset='utf-8'%3E%3C/script%3E"));
23 document.write(unescape("%3Cscript type='text/javascript' src='http://cdn.mathjax.org/mathjax/latest/MathJax.js%3Fconfig=TeX-AMS_HTML' charset='utf-8'%3E%3C/script%3E"));
24 }else{
24 }else{
25 console.log("Using local MathJax");
25 console.log("Using local MathJax");
26 }
26 }
27 </script>
27 </script>
28
28
29 <link rel="stylesheet" href="static/jquery/css/themes/aristo/jquery-wijmo.css" type="text/css" />
29 <link rel="stylesheet" href="static/jquery/css/themes/aristo/jquery-wijmo.css" type="text/css" />
30 <link rel="stylesheet" href="static/codemirror/lib/codemirror.css">
30 <link rel="stylesheet" href="static/codemirror/lib/codemirror.css">
31 <link rel="stylesheet" href="static/codemirror/mode/markdown/markdown.css">
31 <link rel="stylesheet" href="static/codemirror/mode/markdown/markdown.css">
32 <link rel="stylesheet" href="static/codemirror/mode/rst/rst.css">
32 <link rel="stylesheet" href="static/codemirror/mode/rst/rst.css">
33 <link rel="stylesheet" href="static/codemirror/theme/ipython.css">
33 <link rel="stylesheet" href="static/codemirror/theme/ipython.css">
34 <link rel="stylesheet" href="static/codemirror/theme/default.css">
34 <link rel="stylesheet" href="static/codemirror/theme/default.css">
35
35
36 <link rel="stylesheet" href="static/prettify/prettify.css"/>
36 <link rel="stylesheet" href="static/prettify/prettify.css"/>
37
37
38 <link rel="stylesheet" href="static/css/boilerplate.css" type="text/css" />
38 <link rel="stylesheet" href="static/css/boilerplate.css" type="text/css" />
39 <link rel="stylesheet" href="static/css/layout.css" type="text/css" />
39 <link rel="stylesheet" href="static/css/layout.css" type="text/css" />
40 <link rel="stylesheet" href="static/css/base.css" type="text/css" />
40 <link rel="stylesheet" href="static/css/base.css" type="text/css" />
41 <link rel="stylesheet" href="static/css/notebook.css" type="text/css" />
41 <link rel="stylesheet" href="static/css/notebook.css" type="text/css" />
42 <link rel="stylesheet" href="static/css/renderedhtml.css" type="text/css" />
42 <link rel="stylesheet" href="static/css/renderedhtml.css" type="text/css" />
43
43
44 <meta name="read_only" content="{{read_only}}"/>
44 <meta name="read_only" content="{{read_only}}"/>
45
45
46 </head>
46 </head>
47
47
48 <body onload='CheckMathJax();'
48 <body onload='CheckMathJax();'
49 data-project={{project}} data-notebook-id={{notebook_id}}
49 data-project={{project}} data-notebook-id={{notebook_id}}
50 data-base-project-url={{base_project_url}} data-base-kernel-url={{base_kernel_url}}
50 data-base-project-url={{base_project_url}} data-base-kernel-url={{base_kernel_url}}
51 >
51 >
52
52
53 <div id="header">
53 <div id="header">
54 <span id="ipython_notebook"><h1>IPython Notebook</h1></span>
54 <span id="ipython_notebook"><h1>IPython Notebook</h1></span>
55 <span id="save_widget">
55 <span id="save_widget">
56 <input type="text" id="notebook_name" size="20"></textarea>
56 <input type="text" id="notebook_name" size="20"></textarea>
57 <button id="save_notebook"><u>S</u>ave</button>
57 <button id="save_notebook"><u>S</u>ave</button>
58 </span>
58 </span>
59 <span id="quick_help_area">
59 <span id="quick_help_area">
60 <button id="quick_help">Quick<u>H</u>elp</button>
60 <button id="quick_help">Quick<u>H</u>elp</button>
61 </span>
61 </span>
62
62
63 <span id="login_widget">
63 <span id="login_widget">
64 {% comment This is a temporary workaround to hide the logout button %}
64 {% comment This is a temporary workaround to hide the logout button %}
65 {% comment when appropriate until notebook.html is templated %}
65 {% comment when appropriate until notebook.html is templated %}
66 {% if current_user and current_user != 'anonymous' %}
66 {% if current_user and current_user != 'anonymous' %}
67 <button id="logout">Logout</button>
67 <button id="logout">Logout</button>
68 {% end %}
68 {% end %}
69 </span>
69 </span>
70
70
71 <span id="kernel_status">Idle</span>
71 <span id="kernel_status">Idle</span>
72 </div>
72 </div>
73
73
74 <div id="MathJaxFetchingWarning"
74 <div id="MathJaxFetchingWarning"
75 style="width:80%; margin:auto;padding-top:20%;text-align: justify; display:none">
75 style="width:80%; margin:auto;padding-top:20%;text-align: justify; display:none">
76 <p style="font-size:26px;">There was an issue trying to fetch MathJax.js
76 <p style="font-size:26px;">There was an issue trying to fetch MathJax.js
77 from the internet.</p>
77 from the internet.</p>
78
78
79 <p style="padding:0.2em"> With a working internet connection, you can run
79 <p style="padding:0.2em"> With a working internet connection, you can run
80 the following at a Python or IPython prompt, which will install a local
80 the following at a Python or IPython prompt, which will install a local
81 copy of MathJax:</p>
81 copy of MathJax:</p>
82
82
83 <pre style="background-color:lightblue;border:thin silver solid;padding:0.4em">
83 <pre style="background-color:lightblue;border:thin silver solid;padding:0.4em">
84 from IPython.external import mathjax; mathjax.install_mathjax()
84 from IPython.external import mathjax; mathjax.install_mathjax()
85 </pre>
85 </pre>
86 This will try to install MathJax into the directory where you installed
86 This will try to install MathJax into the directory where you installed
87 IPython. If you installed IPython to a location that requires
87 IPython. If you installed IPython to a location that requires
88 administrative privileges to write, you will need to make this call as
88 administrative privileges to write, you will need to make this call as
89 an administrator. On OSX/Linux/Unix, this can be done at the
89 an administrator. On OSX/Linux/Unix, this can be done at the
90 command-line via:
90 command-line via:
91 <pre style="background-color:lightblue;border:thin silver solid;padding:0.4em">
91 <pre style="background-color:lightblue;border:thin silver solid;padding:0.4em">
92 sudo python -c "from IPython.external import mathjax; mathjax.install_mathjax()"
92 sudo python -c "from IPython.external import mathjax; mathjax.install_mathjax()"
93 </pre>
93 </pre>
94 </p>
94 </p>
95 </div>
95 </div>
96
96
97 <div id="main_app">
97 <div id="main_app">
98
98
99 <div id="left_panel">
99 <div id="left_panel">
100
100
101 <div id="notebook_section">
101 <div id="notebook_section">
102 <div class="section_header">
102 <div class="section_header">
103 <h3>Notebook</h3>
103 <h3>Notebook</h3>
104 </div>
104 </div>
105 <div class="section_content">
105 <div class="section_content">
106 <div class="section_row">
106 <div class="section_row">
107 <span id="new_open" class="section_row_buttons">
107 <span id="new_open" class="section_row_buttons">
108 <button id="new_notebook">New</button>
108 <button id="new_notebook">New</button>
109 <button id="open_notebook">Open</button>
109 <button id="open_notebook">Open</button>
110 </span>
110 </span>
111 <span class="section_row_header">Actions</span>
111 <span class="section_row_header">Actions</span>
112 </div>
112 </div>
113 <div class="section_row">
113 <div class="section_row">
114 <span>
114 <span>
115 <select id="download_format">
115 <select id="download_format">
116 <option value="json">ipynb</option>
116 <option value="json">ipynb</option>
117 <option value="py">py</option>
117 <option value="py">py</option>
118 </select>
118 </select>
119 </span>
119 </span>
120 <span class="section_row_buttons">
120 <span class="section_row_buttons">
121 <button id="download_notebook">Download</button>
121 <button id="download_notebook">Download</button>
122 </span>
122 </span>
123 </div>
123 </div>
124 <div class="section_row">
124 <div class="section_row">
125 <span class="section_row_buttons">
125 <span class="section_row_buttons">
126 <span id="print_widget">
126 <span id="print_widget">
127 <button id="print_notebook">Print</button>
127 <button id="print_notebook">Print</button>
128 </span>
128 </span>
129 </span>
129 </span>
130 </div>
130 </div>
131 </div>
131 </div>
132 </div>
132 </div>
133
133
134 <div id="cell_section">
134 <div id="cell_section">
135 <div class="section_header">
135 <div class="section_header">
136 <h3>Cell</h3>
136 <h3>Cell</h3>
137 </div>
137 </div>
138 <div class="section_content">
138 <div class="section_content">
139 <div class="section_row">
139 <div class="section_row">
140 <span class="section_row_buttons">
140 <span class="section_row_buttons">
141 <button id="delete_cell"><u>D</u>elete</button>
141 <button id="delete_cell"><u>D</u>elete</button>
142 </span>
142 </span>
143 <span class="section_row_header">Actions</span>
143 <span class="section_row_header">Actions</span>
144 </div>
144 </div>
145 <div class="section_row">
145 <div class="section_row">
146 <span id="cell_type" class="section_row_buttons">
146 <span id="cell_type" class="section_row_buttons">
147 <button id="to_code"><u>C</u>ode</button>
147 <button id="to_code"><u>C</u>ode</button>
148 <!-- <button id="to_html">HTML</button>-->
148 <!-- <button id="to_html">HTML</button>-->
149 <button id="to_markdown"><u>M</u>arkdown</button>
149 <button id="to_markdown"><u>M</u>arkdown</button>
150 </span>
150 </span>
151 <span class="button_label">Format</span>
151 <span class="button_label">Format</span>
152 </div>
152 </div>
153 <div class="section_row">
153 <div class="section_row">
154 <span id="cell_output" class="section_row_buttons">
154 <span id="cell_output" class="section_row_buttons">
155 <button id="toggle_output"><u>T</u>oggle</button>
155 <button id="toggle_output"><u>T</u>oggle</button>
156 <button id="clear_all_output">ClearAll</button>
156 <button id="clear_all_output">ClearAll</button>
157 </span>
157 </span>
158 <span class="button_label">Output</span>
158 <span class="button_label">Output</span>
159 </div>
159 </div>
160 <div class="section_row">
160 <div class="section_row">
161 <span id="insert" class="section_row_buttons">
161 <span id="insert" class="section_row_buttons">
162 <button id="insert_cell_above"><u>A</u>bove</button>
162 <button id="insert_cell_above"><u>A</u>bove</button>
163 <button id="insert_cell_below"><u>B</u>elow</button>
163 <button id="insert_cell_below"><u>B</u>elow</button>
164 </span>
164 </span>
165 <span class="button_label">Insert</span>
165 <span class="button_label">Insert</span>
166 </div>
166 </div>
167 <div class="section_row">
167 <div class="section_row">
168 <span id="move" class="section_row_buttons">
168 <span id="move" class="section_row_buttons">
169 <button id="move_cell_up">Up</button>
169 <button id="move_cell_up">Up</button>
170 <button id="move_cell_down">Down</button>
170 <button id="move_cell_down">Down</button>
171 </span>
171 </span>
172 <span class="button_label">Move</span>
172 <span class="button_label">Move</span>
173 </div>
173 </div>
174 <div class="section_row">
174 <div class="section_row">
175 <span id="run_cells" class="section_row_buttons">
175 <span id="run_cells" class="section_row_buttons">
176 <button id="run_selected_cell">Selected</button>
176 <button id="run_selected_cell">Selected</button>
177 <button id="run_all_cells">All</button>
177 <button id="run_all_cells">All</button>
178 </span>
178 </span>
179 <span class="button_label">Run</span>
179 <span class="button_label">Run</span>
180 </div>
180 </div>
181 <div class="section_row">
181 <div class="section_row">
182 <span id="autoindent_span">
182 <span id="autoindent_span">
183 <input type="checkbox" id="autoindent" checked="true"></input>
183 <input type="checkbox" id="autoindent" checked="true"></input>
184 </span>
184 </span>
185 <span class="checkbox_label" id="autoindent_label">Autoindent:</span>
185 <span class="checkbox_label" id="autoindent_label">Autoindent:</span>
186 </div>
186 </div>
187 </div>
187 </div>
188 </div>
188 </div>
189
189
190 <div id="kernel_section">
190 <div id="kernel_section">
191 <div class="section_header">
191 <div class="section_header">
192 <h3>Kernel</h3>
192 <h3>Kernel</h3>
193 </div>
193 </div>
194 <div class="section_content">
194 <div class="section_content">
195 <div class="section_row">
195 <div class="section_row">
196 <span id="int_restart" class="section_row_buttons">
196 <span id="int_restart" class="section_row_buttons">
197 <button id="int_kernel"><u>I</u>nterrupt</button>
197 <button id="int_kernel"><u>I</u>nterrupt</button>
198 <button id="restart_kernel">Restart</button>
198 <button id="restart_kernel">Restart</button>
199 </span>
199 </span>
200 <span class="section_row_header">Actions</span>
200 <span class="section_row_header">Actions</span>
201 </div>
201 </div>
202 <div class="section_row">
202 <div class="section_row">
203 <span id="kernel_persist">
203 <span id="kernel_persist">
204 {% if kill_kernel %}
204 {% if kill_kernel %}
205 <input type="checkbox" id="kill_kernel" checked="true"></input>
205 <input type="checkbox" id="kill_kernel" checked="true"></input>
206 {% else %}
206 {% else %}
207 <input type="checkbox" id="kill_kernel"></input>
207 <input type="checkbox" id="kill_kernel"></input>
208 {% end %}
208 {% end %}
209 </span>
209 </span>
210 <span class="checkbox_label" id="kill_kernel_label">Kill kernel upon exit:</span>
210 <span class="checkbox_label" id="kill_kernel_label">Kill kernel upon exit:</span>
211 </div>
211 </div>
212 </div>
212 </div>
213 </div>
213 </div>
214
214
215 <div id="help_section">
215 <div id="help_section">
216 <div class="section_header">
216 <div class="section_header">
217 <h3>Help</h3>
217 <h3>Help</h3>
218 </div>
218 </div>
219 <div class="section_content">
219 <div class="section_content">
220 <div class="section_row">
220 <div class="section_row">
221 <span id="help_buttons0" class="section_row_buttons">
221 <span id="help_buttons0" class="section_row_buttons">
222 <a id="python_help" href="http://docs.python.org" target="_blank">Python</a>
222 <a id="python_help" href="http://docs.python.org" target="_blank">Python</a>
223 <a id="ipython_help" href="http://ipython.org/documentation.html" target="_blank">IPython</a>
223 <a id="ipython_help" href="http://ipython.org/documentation.html" target="_blank">IPython</a>
224 </span>
224 </span>
225 <span class="section_row_header">Links</span>
225 <span class="section_row_header">Links</span>
226 </div>
226 </div>
227 <div class="section_row">
227 <div class="section_row">
228 <span id="help_buttons1" class="section_row_buttons">
228 <span id="help_buttons1" class="section_row_buttons">
229 <a id="numpy_help" href="http://docs.scipy.org/doc/numpy/reference/" target="_blank">NumPy</a>
229 <a id="numpy_help" href="http://docs.scipy.org/doc/numpy/reference/" target="_blank">NumPy</a>
230 <a id="scipy_help" href="http://docs.scipy.org/doc/scipy/reference/" target="_blank">SciPy</a>
230 <a id="scipy_help" href="http://docs.scipy.org/doc/scipy/reference/" target="_blank">SciPy</a>
231 </span>
231 </span>
232 </div>
232 </div>
233 <div class="section_row">
233 <div class="section_row">
234 <span id="help_buttons2" class="section_row_buttons">
234 <span id="help_buttons2" class="section_row_buttons">
235 <a id="matplotlib_help" href="http://matplotlib.sourceforge.net/" target="_blank">MPL</a>
235 <a id="matplotlib_help" href="http://matplotlib.sourceforge.net/" target="_blank">MPL</a>
236 <a id="sympy_help" href="http://docs.sympy.org/dev/index.html" target="_blank">SymPy</a>
236 <a id="sympy_help" href="http://docs.sympy.org/dev/index.html" target="_blank">SymPy</a>
237 </span>
237 </span>
238 </div>
238 </div>
239 <div class="section_row">
239 <div class="section_row">
240 <span class="help_string">run selected cell</span>
240 <span class="help_string">run selected cell</span>
241 <span class="help_string_label">Shift-Enter :</span>
241 <span class="help_string_label">Shift-Enter :</span>
242 </div>
242 </div>
243 <div class="section_row">
243 <div class="section_row">
244 <span class="help_string">run selected cell in-place</span>
244 <span class="help_string">run selected cell in-place</span>
245 <span class="help_string_label">Ctrl-Enter :</span>
245 <span class="help_string_label">Ctrl-Enter :</span>
246 </div>
246 </div>
247 <div class="section_row">
247 <div class="section_row">
248 <span class="help_string">show keyboard shortcuts</span>
248 <span class="help_string">show keyboard shortcuts</span>
249 <span class="help_string_label">Ctrl-m h :</span>
249 <span class="help_string_label">Ctrl-m h :</span>
250 </div>
250 </div>
251 </div>
251 </div>
252 </div>
252 </div>
253
253
254 <div id="config_section">
254 <div id="config_section">
255 <div class="section_header">
255 <div class="section_header">
256 <h3>Config</h3>
256 <h3>Config</h3>
257 </div>
257 </div>
258 <div class="section_content">
258 <div class="section_content">
259 <div class="section_row">
259 <div class="section_row">
260 <span id="tooltipontab_span">
260 <span id="tooltipontab_span">
261 <input type="checkbox" id="tooltipontab" checked="true"></input>
261 <input type="checkbox" id="tooltipontab" checked="true"></input>
262 </span>
262 </span>
263 <span class="checkbox_label" id="tooltipontab_label">Tooltip on tab:</span>
263 <span class="checkbox_label" id="tooltipontab_label">Tooltip on tab:</span>
264 </div>
264 </div>
265 <div class="section_row">
265 <div class="section_row">
266 <span id="smartcompleter_span">
267 <input type="checkbox" id="smartcompleter" checked="true"></input>
268 </span>
269 <span class="checkbox_label" id="smartcompleter_label">Smart completer:</span>
270 </div>
271 <div class="section_row">
266 <span id="tooltipontab_span">
272 <span id="tooltipontab_span">
267 <input type="text" id="timebeforetooltip" value="1200"></input>
273 <input type="text" id="timebeforetooltip" value="1200"></input>
268 </span>
274 </span>
269 <span class="numeric_input_label" id="timebeforetooltip_label">Time before tooltip : </span>
275 <span class="numeric_input_label" id="timebeforetooltip_label">Time before tooltip : </span>
270 </div>
276 </div>
271 </div>
277 </div>
272 </div>
278 </div>
273
279
274 </div>
280 </div>
275 <div id="left_panel_splitter"></div>
281 <div id="left_panel_splitter"></div>
276 <div id="notebook_panel">
282 <div id="notebook_panel">
277 <div id="notebook"></div>
283 <div id="notebook"></div>
278 <div id="pager_splitter"></div>
284 <div id="pager_splitter"></div>
279 <div id="pager"></div>
285 <div id="pager"></div>
280 </div>
286 </div>
281
287
282 </div>
288 </div>
283
289
284 <script src="static/jquery/js/jquery-1.6.2.min.js" type="text/javascript" charset="utf-8"></script>
290 <script src="static/jquery/js/jquery-1.6.2.min.js" type="text/javascript" charset="utf-8"></script>
285 <script src="static/jquery/js/jquery-ui-1.8.14.custom.min.js" type="text/javascript" charset="utf-8"></script>
291 <script src="static/jquery/js/jquery-ui-1.8.14.custom.min.js" type="text/javascript" charset="utf-8"></script>
286 <script src="static/jquery/js/jquery.autogrow.js" type="text/javascript" charset="utf-8"></script>
292 <script src="static/jquery/js/jquery.autogrow.js" type="text/javascript" charset="utf-8"></script>
287
293
288 <script src="static/codemirror/lib/codemirror.js" charset="utf-8"></script>
294 <script src="static/codemirror/lib/codemirror.js" charset="utf-8"></script>
289 <script src="static/codemirror/mode/python/python.js" charset="utf-8"></script>
295 <script src="static/codemirror/mode/python/python.js" charset="utf-8"></script>
290 <script src="static/codemirror/mode/htmlmixed/htmlmixed.js" charset="utf-8"></script>
296 <script src="static/codemirror/mode/htmlmixed/htmlmixed.js" charset="utf-8"></script>
291 <script src="static/codemirror/mode/xml/xml.js" charset="utf-8"></script>
297 <script src="static/codemirror/mode/xml/xml.js" charset="utf-8"></script>
292 <script src="static/codemirror/mode/javascript/javascript.js" charset="utf-8"></script>
298 <script src="static/codemirror/mode/javascript/javascript.js" charset="utf-8"></script>
293 <script src="static/codemirror/mode/css/css.js" charset="utf-8"></script>
299 <script src="static/codemirror/mode/css/css.js" charset="utf-8"></script>
294 <script src="static/codemirror/mode/rst/rst.js" charset="utf-8"></script>
300 <script src="static/codemirror/mode/rst/rst.js" charset="utf-8"></script>
295 <script src="static/codemirror/mode/markdown/markdown.js" charset="utf-8"></script>
301 <script src="static/codemirror/mode/markdown/markdown.js" charset="utf-8"></script>
296
302
297 <script src="static/pagedown/Markdown.Converter.js" charset="utf-8"></script>
303 <script src="static/pagedown/Markdown.Converter.js" charset="utf-8"></script>
298
304
299 <script src="static/prettify/prettify.js" charset="utf-8"></script>
305 <script src="static/prettify/prettify.js" charset="utf-8"></script>
300
306
301 <script src="static/js/namespace.js" type="text/javascript" charset="utf-8"></script>
307 <script src="static/js/namespace.js" type="text/javascript" charset="utf-8"></script>
302 <script src="static/js/utils.js" type="text/javascript" charset="utf-8"></script>
308 <script src="static/js/utils.js" type="text/javascript" charset="utf-8"></script>
303 <script src="static/js/cell.js" type="text/javascript" charset="utf-8"></script>
309 <script src="static/js/cell.js" type="text/javascript" charset="utf-8"></script>
304 <script src="static/js/codecell.js" type="text/javascript" charset="utf-8"></script>
310 <script src="static/js/codecell.js" type="text/javascript" charset="utf-8"></script>
305 <script src="static/js/textcell.js" type="text/javascript" charset="utf-8"></script>
311 <script src="static/js/textcell.js" type="text/javascript" charset="utf-8"></script>
306 <script src="static/js/kernel.js" type="text/javascript" charset="utf-8"></script>
312 <script src="static/js/kernel.js" type="text/javascript" charset="utf-8"></script>
307 <script src="static/js/kernelstatus.js" type="text/javascript" charset="utf-8"></script>
313 <script src="static/js/kernelstatus.js" type="text/javascript" charset="utf-8"></script>
308 <script src="static/js/layout.js" type="text/javascript" charset="utf-8"></script>
314 <script src="static/js/layout.js" type="text/javascript" charset="utf-8"></script>
309 <script src="static/js/savewidget.js" type="text/javascript" charset="utf-8"></script>
315 <script src="static/js/savewidget.js" type="text/javascript" charset="utf-8"></script>
310 <script src="static/js/quickhelp.js" type="text/javascript" charset="utf-8"></script>
316 <script src="static/js/quickhelp.js" type="text/javascript" charset="utf-8"></script>
311 <script src="static/js/loginwidget.js" type="text/javascript" charset="utf-8"></script>
317 <script src="static/js/loginwidget.js" type="text/javascript" charset="utf-8"></script>
312 <script src="static/js/pager.js" type="text/javascript" charset="utf-8"></script>
318 <script src="static/js/pager.js" type="text/javascript" charset="utf-8"></script>
313 <script src="static/js/panelsection.js" type="text/javascript" charset="utf-8"></script>
319 <script src="static/js/panelsection.js" type="text/javascript" charset="utf-8"></script>
314 <script src="static/js/printwidget.js" type="text/javascript" charset="utf-8"></script>
320 <script src="static/js/printwidget.js" type="text/javascript" charset="utf-8"></script>
315 <script src="static/js/leftpanel.js" type="text/javascript" charset="utf-8"></script>
321 <script src="static/js/leftpanel.js" type="text/javascript" charset="utf-8"></script>
316 <script src="static/js/notebook.js" type="text/javascript" charset="utf-8"></script>
322 <script src="static/js/notebook.js" type="text/javascript" charset="utf-8"></script>
317 <script src="static/js/notebookmain.js" type="text/javascript" charset="utf-8"></script>
323 <script src="static/js/notebookmain.js" type="text/javascript" charset="utf-8"></script>
318
324
319 </body>
325 </body>
320
326
321 </html>
327 </html>
General Comments 0
You need to be logged in to leave comments. Login now