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