##// END OF EJS Templates
Refactor line num. toggle into proper function, access via C-m-l....
Fernando Perez -
Show More
@@ -1,483 +1,486 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 onKeyEvent: $.proxy(this.handle_codemirror_keyevent,this)
40 onKeyEvent: $.proxy(this.handle_codemirror_keyevent,this)
41 });
41 });
42 input.append(input_area);
42 input.append(input_area);
43 var output = $('<div></div>').addClass('output vbox');
43 var output = $('<div></div>').addClass('output vbox');
44 cell.append(input).append(output);
44 cell.append(input).append(output);
45 this.element = cell;
45 this.element = cell;
46 this.collapse()
46 this.collapse()
47 };
47 };
48
48
49
49
50 CodeCell.prototype.handle_codemirror_keyevent = function (editor, event) {
50 CodeCell.prototype.handle_codemirror_keyevent = function (editor, event) {
51 // This method gets called in CodeMirror's onKeyDown/onKeyPress
51 // This method gets called in CodeMirror's onKeyDown/onKeyPress
52 // handlers and is used to provide custom key handling. Its return
52 // handlers and is used to provide custom key handling. Its return
53 // value is used to determine if CodeMirror should ignore the event:
53 // value is used to determine if CodeMirror should ignore the event:
54 // true = ignore, false = don't ignore.
54 // true = ignore, false = don't ignore.
55 if (event.keyCode === 13 && (event.shiftKey || event.ctrlKey)) {
55 if (event.keyCode === 13 && (event.shiftKey || event.ctrlKey)) {
56 // Always ignore shift-enter in CodeMirror as we handle it.
56 // Always ignore shift-enter in CodeMirror as we handle it.
57 return true;
57 return true;
58 } else if (event.keyCode === 9 && event.type == 'keydown') {
58 } else if (event.keyCode === 9 && event.type == 'keydown') {
59 // Tab completion.
59 // Tab completion.
60 var cur = editor.getCursor();
60 var cur = editor.getCursor();
61 var pre_cursor = editor.getRange({line:cur.line,ch:0},cur).trim();
61 var pre_cursor = editor.getRange({line:cur.line,ch:0},cur).trim();
62 if (pre_cursor === "") {
62 if (pre_cursor === "") {
63 // Don't autocomplete if the part of the line before the cursor
63 // Don't autocomplete if the part of the line before the cursor
64 // is empty. In this case, let CodeMirror handle indentation.
64 // is empty. In this case, let CodeMirror handle indentation.
65 return false;
65 return false;
66 } else {
66 } else {
67 // Autocomplete the current line.
67 // Autocomplete the current line.
68 event.stop();
68 event.stop();
69 var line = editor.getLine(cur.line);
69 var line = editor.getLine(cur.line);
70 this.is_completing = true;
70 this.is_completing = true;
71 this.completion_cursor = cur;
71 this.completion_cursor = cur;
72 IPython.notebook.complete_cell(this, line, cur.ch);
72 IPython.notebook.complete_cell(this, line, cur.ch);
73 return true;
73 return true;
74 }
74 }
75 } else if (event.keyCode === 8 && event.type == 'keydown') {
75 } else if (event.keyCode === 8 && event.type == 'keydown') {
76 // If backspace and the line ends with 4 spaces, remove them.
76 // If backspace and the line ends with 4 spaces, remove them.
77 var cur = editor.getCursor();
77 var cur = editor.getCursor();
78 var line = editor.getLine(cur.line);
78 var line = editor.getLine(cur.line);
79 var ending = line.slice(-4);
79 var ending = line.slice(-4);
80 if (ending === ' ') {
80 if (ending === ' ') {
81 editor.replaceRange('',
81 editor.replaceRange('',
82 {line: cur.line, ch: cur.ch-4},
82 {line: cur.line, ch: cur.ch-4},
83 {line: cur.line, ch: cur.ch}
83 {line: cur.line, ch: cur.ch}
84 );
84 );
85 event.stop();
85 event.stop();
86 return true;
86 return true;
87 } else {
87 } else {
88 return false;
88 return false;
89 };
89 };
90 } else if (event.keyCode === 76 && event.ctrlKey && event.shiftKey
90 } else if (event.keyCode === 76 && event.ctrlKey && event.shiftKey
91 && event.type == 'keydown') {
91 && event.type == 'keydown') {
92 // toggle line numbers with Ctrl-Shift-L
92 // toggle line numbers with Ctrl-Shift-L
93 if (this.code_mirror.getOption('lineNumbers') == false) {
93 this.toggle_line_numbers()
94 this.code_mirror.setOption('lineNumbers', true);
95 } else {
96 this.code_mirror.setOption('lineNumbers', false);
97 }
98 this.code_mirror.refresh()
99 }
94 }
100 else {
95 else {
101 // keypress/keyup also trigger on TAB press, and we don't want to
96 // keypress/keyup also trigger on TAB press, and we don't want to
102 // use those to disable tab completion.
97 // use those to disable tab completion.
103 if (this.is_completing && event.keyCode !== 9) {
98 if (this.is_completing && event.keyCode !== 9) {
104 var ed_cur = editor.getCursor();
99 var ed_cur = editor.getCursor();
105 var cc_cur = this.completion_cursor;
100 var cc_cur = this.completion_cursor;
106 if (ed_cur.line !== cc_cur.line || ed_cur.ch !== cc_cur.ch) {
101 if (ed_cur.line !== cc_cur.line || ed_cur.ch !== cc_cur.ch) {
107 this.is_completing = false;
102 this.is_completing = false;
108 this.completion_cursor = null;
103 this.completion_cursor = null;
109 };
104 };
110 };
105 };
111 return false;
106 return false;
112 };
107 };
113 };
108 };
114
109
115
110
116 CodeCell.prototype.finish_completing = function (matched_text, matches) {
111 CodeCell.prototype.finish_completing = function (matched_text, matches) {
117 // console.log("Got matches", matched_text, matches);
112 // console.log("Got matches", matched_text, matches);
118 if (!this.is_completing || matches.length === 0) {return;}
113 if (!this.is_completing || matches.length === 0) {return;}
119
114
120 var that = this;
115 var that = this;
121 var cur = this.completion_cursor;
116 var cur = this.completion_cursor;
122
117
123 var insert = function (selected_text) {
118 var insert = function (selected_text) {
124 that.code_mirror.replaceRange(
119 that.code_mirror.replaceRange(
125 selected_text,
120 selected_text,
126 {line: cur.line, ch: (cur.ch-matched_text.length)},
121 {line: cur.line, ch: (cur.ch-matched_text.length)},
127 {line: cur.line, ch: cur.ch}
122 {line: cur.line, ch: cur.ch}
128 );
123 );
129 };
124 };
130
125
131 if (matches.length === 1) {
126 if (matches.length === 1) {
132 insert(matches[0]);
127 insert(matches[0]);
133 setTimeout(function(){that.code_mirror.focus();}, 50);
128 setTimeout(function(){that.code_mirror.focus();}, 50);
134 return;
129 return;
135 };
130 };
136
131
137 var complete = $('<div/>').addClass('completions');
132 var complete = $('<div/>').addClass('completions');
138 var select = $('<select/>').attr('multiple','true');
133 var select = $('<select/>').attr('multiple','true');
139 for (var i=0; i<matches.length; ++i) {
134 for (var i=0; i<matches.length; ++i) {
140 select.append($('<option/>').text(matches[i]));
135 select.append($('<option/>').text(matches[i]));
141 }
136 }
142 select.children().first().attr('selected','true');
137 select.children().first().attr('selected','true');
143 select.attr('size',Math.min(10,matches.length));
138 select.attr('size',Math.min(10,matches.length));
144 var pos = this.code_mirror.cursorCoords();
139 var pos = this.code_mirror.cursorCoords();
145 complete.css('left',pos.x+'px');
140 complete.css('left',pos.x+'px');
146 complete.css('top',pos.yBot+'px');
141 complete.css('top',pos.yBot+'px');
147 complete.append(select);
142 complete.append(select);
148
143
149 $('body').append(complete);
144 $('body').append(complete);
150 var done = false;
145 var done = false;
151
146
152 var close = function () {
147 var close = function () {
153 if (done) return;
148 if (done) return;
154 done = true;
149 done = true;
155 complete.remove();
150 complete.remove();
156 that.is_completing = false;
151 that.is_completing = false;
157 that.completion_cursor = null;
152 that.completion_cursor = null;
158 };
153 };
159
154
160 var pick = function () {
155 var pick = function () {
161 insert(select.val()[0]);
156 insert(select.val()[0]);
162 close();
157 close();
163 setTimeout(function(){that.code_mirror.focus();}, 50);
158 setTimeout(function(){that.code_mirror.focus();}, 50);
164 };
159 };
165
160
166 select.blur(close);
161 select.blur(close);
167 select.keydown(function (event) {
162 select.keydown(function (event) {
168 var code = event.which;
163 var code = event.which;
169 if (code === 13 || code === 32) {
164 if (code === 13 || code === 32) {
170 // Pressing SPACE or ENTER will cause a pick
165 // Pressing SPACE or ENTER will cause a pick
171 event.stopPropagation();
166 event.stopPropagation();
172 event.preventDefault();
167 event.preventDefault();
173 pick();
168 pick();
174 } else if (code === 38 || code === 40) {
169 } else if (code === 38 || code === 40) {
175 // We don't want the document keydown handler to handle UP/DOWN,
170 // We don't want the document keydown handler to handle UP/DOWN,
176 // but we want the default action.
171 // but we want the default action.
177 event.stopPropagation();
172 event.stopPropagation();
178 } else {
173 } else {
179 // All other key presses exit completion.
174 // All other key presses exit completion.
180 event.stopPropagation();
175 event.stopPropagation();
181 event.preventDefault();
176 event.preventDefault();
182 close();
177 close();
183 that.code_mirror.focus();
178 that.code_mirror.focus();
184 }
179 }
185 });
180 });
186 // Double click also causes a pick.
181 // Double click also causes a pick.
187 select.dblclick(pick);
182 select.dblclick(pick);
188 select.focus();
183 select.focus();
189 };
184 };
190
185
186 CodeCell.prototype.toggle_line_numbers = function () {
187 if (this.code_mirror.getOption('lineNumbers') == false) {
188 this.code_mirror.setOption('lineNumbers', true);
189 } else {
190 this.code_mirror.setOption('lineNumbers', false);
191 }
192 this.code_mirror.refresh()
193 };
191
194
192 CodeCell.prototype.select = function () {
195 CodeCell.prototype.select = function () {
193 IPython.Cell.prototype.select.apply(this);
196 IPython.Cell.prototype.select.apply(this);
194 // Todo: this dance is needed because as of CodeMirror 2.12, focus is
197 // Todo: this dance is needed because as of CodeMirror 2.12, focus is
195 // not causing the cursor to blink if the editor is empty initially.
198 // not causing the cursor to blink if the editor is empty initially.
196 // While this seems to fix the issue, this should be fixed
199 // While this seems to fix the issue, this should be fixed
197 // in CodeMirror proper.
200 // in CodeMirror proper.
198 var s = this.code_mirror.getValue();
201 var s = this.code_mirror.getValue();
199 this.code_mirror.focus();
202 this.code_mirror.focus();
200 if (s === '') this.code_mirror.setValue('');
203 if (s === '') this.code_mirror.setValue('');
201 };
204 };
202
205
203
206
204 CodeCell.prototype.select_all = function () {
207 CodeCell.prototype.select_all = function () {
205 var start = {line: 0, ch: 0};
208 var start = {line: 0, ch: 0};
206 var nlines = this.code_mirror.lineCount();
209 var nlines = this.code_mirror.lineCount();
207 var last_line = this.code_mirror.getLine(nlines-1);
210 var last_line = this.code_mirror.getLine(nlines-1);
208 var end = {line: nlines-1, ch: last_line.length};
211 var end = {line: nlines-1, ch: last_line.length};
209 this.code_mirror.setSelection(start, end);
212 this.code_mirror.setSelection(start, end);
210 };
213 };
211
214
212
215
213 CodeCell.prototype.append_output = function (json) {
216 CodeCell.prototype.append_output = function (json) {
214 this.expand();
217 this.expand();
215 if (json.output_type === 'pyout') {
218 if (json.output_type === 'pyout') {
216 this.append_pyout(json);
219 this.append_pyout(json);
217 } else if (json.output_type === 'pyerr') {
220 } else if (json.output_type === 'pyerr') {
218 this.append_pyerr(json);
221 this.append_pyerr(json);
219 } else if (json.output_type === 'display_data') {
222 } else if (json.output_type === 'display_data') {
220 this.append_display_data(json);
223 this.append_display_data(json);
221 } else if (json.output_type === 'stream') {
224 } else if (json.output_type === 'stream') {
222 this.append_stream(json);
225 this.append_stream(json);
223 };
226 };
224 this.outputs.push(json);
227 this.outputs.push(json);
225 };
228 };
226
229
227
230
228 CodeCell.prototype.create_output_area = function () {
231 CodeCell.prototype.create_output_area = function () {
229 var oa = $("<div/>").addClass("hbox output_area");
232 var oa = $("<div/>").addClass("hbox output_area");
230 oa.append($('<div/>').addClass('prompt'));
233 oa.append($('<div/>').addClass('prompt'));
231 return oa;
234 return oa;
232 };
235 };
233
236
234
237
235 CodeCell.prototype.append_pyout = function (json) {
238 CodeCell.prototype.append_pyout = function (json) {
236 n = json.prompt_number || ' ';
239 n = json.prompt_number || ' ';
237 var toinsert = this.create_output_area();
240 var toinsert = this.create_output_area();
238 toinsert.find('div.prompt').addClass('output_prompt').html('Out[' + n + ']:');
241 toinsert.find('div.prompt').addClass('output_prompt').html('Out[' + n + ']:');
239 this.append_mime_type(json, toinsert);
242 this.append_mime_type(json, toinsert);
240 this.element.find('div.output').append(toinsert);
243 this.element.find('div.output').append(toinsert);
241 // If we just output latex, typeset it.
244 // If we just output latex, typeset it.
242 if (json.latex !== undefined) {
245 if (json.latex !== undefined) {
243 MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
246 MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
244 };
247 };
245 };
248 };
246
249
247
250
248 CodeCell.prototype.append_pyerr = function (json) {
251 CodeCell.prototype.append_pyerr = function (json) {
249 var tb = json.traceback;
252 var tb = json.traceback;
250 if (tb !== undefined && tb.length > 0) {
253 if (tb !== undefined && tb.length > 0) {
251 var s = '';
254 var s = '';
252 var len = tb.length;
255 var len = tb.length;
253 for (var i=0; i<len; i++) {
256 for (var i=0; i<len; i++) {
254 s = s + tb[i] + '\n';
257 s = s + tb[i] + '\n';
255 }
258 }
256 s = s + '\n';
259 s = s + '\n';
257 var toinsert = this.create_output_area();
260 var toinsert = this.create_output_area();
258 this.append_text(s, toinsert);
261 this.append_text(s, toinsert);
259 this.element.find('div.output').append(toinsert);
262 this.element.find('div.output').append(toinsert);
260 };
263 };
261 };
264 };
262
265
263
266
264 CodeCell.prototype.append_stream = function (json) {
267 CodeCell.prototype.append_stream = function (json) {
265 // temporary fix: if stream undefined (json file written prior to this patch),
268 // temporary fix: if stream undefined (json file written prior to this patch),
266 // default to most likely stdout:
269 // default to most likely stdout:
267 if (json.stream == undefined){
270 if (json.stream == undefined){
268 json.stream = 'stdout';
271 json.stream = 'stdout';
269 }
272 }
270 var subclass = "output_"+json.stream;
273 var subclass = "output_"+json.stream;
271 if (this.outputs.length > 0){
274 if (this.outputs.length > 0){
272 // have at least one output to consider
275 // have at least one output to consider
273 var last = this.outputs[this.outputs.length-1];
276 var last = this.outputs[this.outputs.length-1];
274 if (last.output_type == 'stream' && json.stream == last.stream){
277 if (last.output_type == 'stream' && json.stream == last.stream){
275 // latest output was in the same stream,
278 // latest output was in the same stream,
276 // so append directly into its pre tag
279 // so append directly into its pre tag
277 this.element.find('div.'+subclass).last().find('pre').append(json.text);
280 this.element.find('div.'+subclass).last().find('pre').append(json.text);
278 return;
281 return;
279 }
282 }
280 }
283 }
281
284
282 // If we got here, attach a new div
285 // If we got here, attach a new div
283 var toinsert = this.create_output_area();
286 var toinsert = this.create_output_area();
284 this.append_text(json.text, toinsert, "output_stream "+subclass);
287 this.append_text(json.text, toinsert, "output_stream "+subclass);
285 this.element.find('div.output').append(toinsert);
288 this.element.find('div.output').append(toinsert);
286 };
289 };
287
290
288
291
289 CodeCell.prototype.append_display_data = function (json) {
292 CodeCell.prototype.append_display_data = function (json) {
290 var toinsert = this.create_output_area();
293 var toinsert = this.create_output_area();
291 this.append_mime_type(json, toinsert)
294 this.append_mime_type(json, toinsert)
292 this.element.find('div.output').append(toinsert);
295 this.element.find('div.output').append(toinsert);
293 // If we just output latex, typeset it.
296 // If we just output latex, typeset it.
294 if (json.latex !== undefined) {
297 if (json.latex !== undefined) {
295 MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
298 MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
296 };
299 };
297 };
300 };
298
301
299
302
300 CodeCell.prototype.append_mime_type = function (json, element) {
303 CodeCell.prototype.append_mime_type = function (json, element) {
301 if (json.html !== undefined) {
304 if (json.html !== undefined) {
302 this.append_html(json.html, element);
305 this.append_html(json.html, element);
303 } else if (json.latex !== undefined) {
306 } else if (json.latex !== undefined) {
304 this.append_latex(json.latex, element);
307 this.append_latex(json.latex, element);
305 } else if (json.svg !== undefined) {
308 } else if (json.svg !== undefined) {
306 this.append_svg(json.svg, element);
309 this.append_svg(json.svg, element);
307 } else if (json.png !== undefined) {
310 } else if (json.png !== undefined) {
308 this.append_png(json.png, element);
311 this.append_png(json.png, element);
309 } else if (json.jpeg !== undefined) {
312 } else if (json.jpeg !== undefined) {
310 this.append_jpeg(json.jpeg, element);
313 this.append_jpeg(json.jpeg, element);
311 } else if (json.text !== undefined) {
314 } else if (json.text !== undefined) {
312 this.append_text(json.text, element);
315 this.append_text(json.text, element);
313 };
316 };
314 };
317 };
315
318
316
319
317 CodeCell.prototype.append_html = function (html, element) {
320 CodeCell.prototype.append_html = function (html, element) {
318 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_html rendered_html");
321 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_html rendered_html");
319 toinsert.append(html);
322 toinsert.append(html);
320 element.append(toinsert);
323 element.append(toinsert);
321 }
324 }
322
325
323
326
324 CodeCell.prototype.append_text = function (data, element, extra_class) {
327 CodeCell.prototype.append_text = function (data, element, extra_class) {
325 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_text");
328 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_text");
326 if (extra_class){
329 if (extra_class){
327 toinsert.addClass(extra_class);
330 toinsert.addClass(extra_class);
328 }
331 }
329 toinsert.append($("<pre/>").html(data));
332 toinsert.append($("<pre/>").html(data));
330 element.append(toinsert);
333 element.append(toinsert);
331 };
334 };
332
335
333
336
334 CodeCell.prototype.append_svg = function (svg, element) {
337 CodeCell.prototype.append_svg = function (svg, element) {
335 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_svg");
338 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_svg");
336 toinsert.append(svg);
339 toinsert.append(svg);
337 element.append(toinsert);
340 element.append(toinsert);
338 };
341 };
339
342
340
343
341 CodeCell.prototype.append_png = function (png, element) {
344 CodeCell.prototype.append_png = function (png, element) {
342 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_png");
345 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_png");
343 toinsert.append($("<img/>").attr('src','data:image/png;base64,'+png));
346 toinsert.append($("<img/>").attr('src','data:image/png;base64,'+png));
344 element.append(toinsert);
347 element.append(toinsert);
345 };
348 };
346
349
347
350
348 CodeCell.prototype.append_jpeg = function (jpeg, element) {
351 CodeCell.prototype.append_jpeg = function (jpeg, element) {
349 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_jpeg");
352 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_jpeg");
350 toinsert.append($("<img/>").attr('src','data:image/jpeg;base64,'+jpeg));
353 toinsert.append($("<img/>").attr('src','data:image/jpeg;base64,'+jpeg));
351 element.append(toinsert);
354 element.append(toinsert);
352 };
355 };
353
356
354
357
355 CodeCell.prototype.append_latex = function (latex, element) {
358 CodeCell.prototype.append_latex = function (latex, element) {
356 // This method cannot do the typesetting because the latex first has to
359 // This method cannot do the typesetting because the latex first has to
357 // be on the page.
360 // be on the page.
358 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_latex");
361 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_latex");
359 toinsert.append(latex);
362 toinsert.append(latex);
360 element.append(toinsert);
363 element.append(toinsert);
361 }
364 }
362
365
363
366
364 CodeCell.prototype.clear_output = function () {
367 CodeCell.prototype.clear_output = function () {
365 this.element.find("div.output").html("");
368 this.element.find("div.output").html("");
366 this.outputs = [];
369 this.outputs = [];
367 };
370 };
368
371
369
372
370 CodeCell.prototype.clear_input = function () {
373 CodeCell.prototype.clear_input = function () {
371 this.code_mirror.setValue('');
374 this.code_mirror.setValue('');
372 };
375 };
373
376
374
377
375 CodeCell.prototype.collapse = function () {
378 CodeCell.prototype.collapse = function () {
376 if (!this.collapsed) {
379 if (!this.collapsed) {
377 this.element.find('div.output').hide();
380 this.element.find('div.output').hide();
378 this.collapsed = true;
381 this.collapsed = true;
379 };
382 };
380 };
383 };
381
384
382
385
383 CodeCell.prototype.expand = function () {
386 CodeCell.prototype.expand = function () {
384 if (this.collapsed) {
387 if (this.collapsed) {
385 this.element.find('div.output').show();
388 this.element.find('div.output').show();
386 this.collapsed = false;
389 this.collapsed = false;
387 };
390 };
388 };
391 };
389
392
390
393
391 CodeCell.prototype.toggle_output = function () {
394 CodeCell.prototype.toggle_output = function () {
392 if (this.collapsed) {
395 if (this.collapsed) {
393 this.expand();
396 this.expand();
394 } else {
397 } else {
395 this.collapse();
398 this.collapse();
396 };
399 };
397 };
400 };
398
401
399 CodeCell.prototype.set_input_prompt = function (number) {
402 CodeCell.prototype.set_input_prompt = function (number) {
400 var n = number || ' ';
403 var n = number || ' ';
401 this.input_prompt_number = n
404 this.input_prompt_number = n
402 this.element.find('div.input_prompt').html('In&nbsp;[' + n + ']:');
405 this.element.find('div.input_prompt').html('In&nbsp;[' + n + ']:');
403 };
406 };
404
407
405
408
406 CodeCell.prototype.get_code = function () {
409 CodeCell.prototype.get_code = function () {
407 return this.code_mirror.getValue();
410 return this.code_mirror.getValue();
408 };
411 };
409
412
410
413
411 CodeCell.prototype.set_code = function (code) {
414 CodeCell.prototype.set_code = function (code) {
412 return this.code_mirror.setValue(code);
415 return this.code_mirror.setValue(code);
413 };
416 };
414
417
415
418
416 CodeCell.prototype.at_top = function () {
419 CodeCell.prototype.at_top = function () {
417 var cursor = this.code_mirror.getCursor();
420 var cursor = this.code_mirror.getCursor();
418 if (cursor.line === 0) {
421 if (cursor.line === 0) {
419 return true;
422 return true;
420 } else {
423 } else {
421 return false;
424 return false;
422 }
425 }
423 };
426 };
424
427
425
428
426 CodeCell.prototype.at_bottom = function () {
429 CodeCell.prototype.at_bottom = function () {
427 var cursor = this.code_mirror.getCursor();
430 var cursor = this.code_mirror.getCursor();
428 if (cursor.line === (this.code_mirror.lineCount()-1)) {
431 if (cursor.line === (this.code_mirror.lineCount()-1)) {
429 return true;
432 return true;
430 } else {
433 } else {
431 return false;
434 return false;
432 }
435 }
433 };
436 };
434
437
435
438
436 CodeCell.prototype.fromJSON = function (data) {
439 CodeCell.prototype.fromJSON = function (data) {
437 console.log('Import from JSON:', data);
440 console.log('Import from JSON:', data);
438 if (data.cell_type === 'code') {
441 if (data.cell_type === 'code') {
439 if (data.input !== undefined) {
442 if (data.input !== undefined) {
440 this.set_code(data.input);
443 this.set_code(data.input);
441 }
444 }
442 if (data.prompt_number !== undefined) {
445 if (data.prompt_number !== undefined) {
443 this.set_input_prompt(data.prompt_number);
446 this.set_input_prompt(data.prompt_number);
444 } else {
447 } else {
445 this.set_input_prompt();
448 this.set_input_prompt();
446 };
449 };
447 var len = data.outputs.length;
450 var len = data.outputs.length;
448 for (var i=0; i<len; i++) {
451 for (var i=0; i<len; i++) {
449 this.append_output(data.outputs[i]);
452 this.append_output(data.outputs[i]);
450 };
453 };
451 if (data.collapsed !== undefined) {
454 if (data.collapsed !== undefined) {
452 if (data.collapsed) {
455 if (data.collapsed) {
453 this.collapse();
456 this.collapse();
454 };
457 };
455 };
458 };
456 };
459 };
457 };
460 };
458
461
459
462
460 CodeCell.prototype.toJSON = function () {
463 CodeCell.prototype.toJSON = function () {
461 var data = {};
464 var data = {};
462 data.input = this.get_code();
465 data.input = this.get_code();
463 data.cell_type = 'code';
466 data.cell_type = 'code';
464 if (this.input_prompt_number !== ' ') {
467 if (this.input_prompt_number !== ' ') {
465 data.prompt_number = this.input_prompt_number
468 data.prompt_number = this.input_prompt_number
466 };
469 };
467 var outputs = [];
470 var outputs = [];
468 var len = this.outputs.length;
471 var len = this.outputs.length;
469 for (var i=0; i<len; i++) {
472 for (var i=0; i<len; i++) {
470 outputs[i] = this.outputs[i];
473 outputs[i] = this.outputs[i];
471 };
474 };
472 data.outputs = outputs;
475 data.outputs = outputs;
473 data.language = 'python';
476 data.language = 'python';
474 data.collapsed = this.collapsed;
477 data.collapsed = this.collapsed;
475 // console.log('Export to JSON:',data);
478 // console.log('Export to JSON:',data);
476 return data;
479 return data;
477 };
480 };
478
481
479
482
480 IPython.CodeCell = CodeCell;
483 IPython.CodeCell = CodeCell;
481
484
482 return IPython;
485 return IPython;
483 }(IPython));
486 }(IPython));
@@ -1,944 +1,954 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.element = $(selector);
17 this.element = $(selector);
18 this.element.scroll();
18 this.element.scroll();
19 this.element.data("notebook", this);
19 this.element.data("notebook", this);
20 this.next_prompt_number = 1;
20 this.next_prompt_number = 1;
21 this.kernel = null;
21 this.kernel = null;
22 this.dirty = false;
22 this.dirty = false;
23 this.msg_cell_map = {};
23 this.msg_cell_map = {};
24 this.metadata = {};
24 this.metadata = {};
25 this.control_key_active = false;
25 this.control_key_active = false;
26 this.style();
26 this.style();
27 this.create_elements();
27 this.create_elements();
28 this.bind_events();
28 this.bind_events();
29 };
29 };
30
30
31
31
32 Notebook.prototype.style = function () {
32 Notebook.prototype.style = function () {
33 $('div#notebook').addClass('border-box-sizing');
33 $('div#notebook').addClass('border-box-sizing');
34 };
34 };
35
35
36
36
37 Notebook.prototype.create_elements = function () {
37 Notebook.prototype.create_elements = function () {
38 // We add this end_space div to the end of the notebook div to:
38 // We add this end_space div to the end of the notebook div to:
39 // i) provide a margin between the last cell and the end of the notebook
39 // i) provide a margin between the last cell and the end of the notebook
40 // ii) to prevent the div from scrolling up when the last cell is being
40 // ii) to prevent the div from scrolling up when the last cell is being
41 // edited, but is too low on the page, which browsers will do automatically.
41 // edited, but is too low on the page, which browsers will do automatically.
42 var that = this;
42 var that = this;
43 var end_space = $('<div class="end_space"></div>').height(150);
43 var end_space = $('<div class="end_space"></div>').height(150);
44 end_space.dblclick(function (e) {
44 end_space.dblclick(function (e) {
45 var ncells = that.ncells();
45 var ncells = that.ncells();
46 that.insert_code_cell_below(ncells-1);
46 that.insert_code_cell_below(ncells-1);
47 });
47 });
48 this.element.append(end_space);
48 this.element.append(end_space);
49 $('div#notebook').addClass('border-box-sizing');
49 $('div#notebook').addClass('border-box-sizing');
50 };
50 };
51
51
52
52
53 Notebook.prototype.bind_events = function () {
53 Notebook.prototype.bind_events = function () {
54 var that = this;
54 var that = this;
55 $(document).keydown(function (event) {
55 $(document).keydown(function (event) {
56 // console.log(event);
56 // console.log(event);
57 if (event.which === 38) {
57 if (event.which === 38) {
58 var cell = that.selected_cell();
58 var cell = that.selected_cell();
59 if (cell.at_top()) {
59 if (cell.at_top()) {
60 event.preventDefault();
60 event.preventDefault();
61 that.select_prev();
61 that.select_prev();
62 };
62 };
63 } else if (event.which === 40) {
63 } else if (event.which === 40) {
64 var cell = that.selected_cell();
64 var cell = that.selected_cell();
65 if (cell.at_bottom()) {
65 if (cell.at_bottom()) {
66 event.preventDefault();
66 event.preventDefault();
67 that.select_next();
67 that.select_next();
68 };
68 };
69 } else if (event.which === 13 && event.shiftKey) {
69 } else if (event.which === 13 && event.shiftKey) {
70 that.execute_selected_cell();
70 that.execute_selected_cell();
71 return false;
71 return false;
72 } else if (event.which === 13 && event.ctrlKey) {
72 } else if (event.which === 13 && event.ctrlKey) {
73 that.execute_selected_cell({terminal:true});
73 that.execute_selected_cell({terminal:true});
74 return false;
74 return false;
75 } else if (event.which === 77 && event.ctrlKey) {
75 } else if (event.which === 77 && event.ctrlKey) {
76 that.control_key_active = true;
76 that.control_key_active = true;
77 return false;
77 return false;
78 } else if (event.which === 68 && that.control_key_active) {
78 } else if (event.which === 68 && that.control_key_active) {
79 // Delete selected cell = d
79 // Delete selected cell = d
80 that.delete_cell();
80 that.delete_cell();
81 that.control_key_active = false;
81 that.control_key_active = false;
82 return false;
82 return false;
83 } else if (event.which === 65 && that.control_key_active) {
83 } else if (event.which === 65 && that.control_key_active) {
84 // Insert code cell above selected = a
84 // Insert code cell above selected = a
85 that.insert_code_cell_above();
85 that.insert_code_cell_above();
86 that.control_key_active = false;
86 that.control_key_active = false;
87 return false;
87 return false;
88 } else if (event.which === 66 && that.control_key_active) {
88 } else if (event.which === 66 && that.control_key_active) {
89 // Insert code cell below selected = b
89 // Insert code cell below selected = b
90 that.insert_code_cell_below();
90 that.insert_code_cell_below();
91 that.control_key_active = false;
91 that.control_key_active = false;
92 return false;
92 return false;
93 } else if (event.which === 67 && that.control_key_active) {
93 } else if (event.which === 67 && that.control_key_active) {
94 // To code = c
94 // To code = c
95 that.to_code();
95 that.to_code();
96 that.control_key_active = false;
96 that.control_key_active = false;
97 return false;
97 return false;
98 } else if (event.which === 77 && that.control_key_active) {
98 } else if (event.which === 77 && that.control_key_active) {
99 // To markdown = m
99 // To markdown = m
100 that.to_markdown();
100 that.to_markdown();
101 that.control_key_active = false;
101 that.control_key_active = false;
102 return false;
102 return false;
103 } else if (event.which === 84 && that.control_key_active) {
103 } else if (event.which === 84 && that.control_key_active) {
104 // Toggle output = t
104 // Toggle output = t
105 that.toggle_output();
105 that.toggle_output();
106 that.control_key_active = false;
106 that.control_key_active = false;
107 return false;
107 return false;
108 } else if (event.which === 83 && that.control_key_active) {
108 } else if (event.which === 83 && that.control_key_active) {
109 // Save notebook = s
109 // Save notebook = s
110 IPython.save_widget.save_notebook();
110 IPython.save_widget.save_notebook();
111 that.control_key_active = false;
111 that.control_key_active = false;
112 return false;
112 return false;
113 } else if (event.which === 74 && that.control_key_active) {
113 } else if (event.which === 74 && that.control_key_active) {
114 // Move cell down = j
114 // Move cell down = j
115 that.move_cell_down();
115 that.move_cell_down();
116 that.control_key_active = false;
116 that.control_key_active = false;
117 return false;
117 return false;
118 } else if (event.which === 75 && that.control_key_active) {
118 } else if (event.which === 75 && that.control_key_active) {
119 // Move cell up = k
119 // Move cell up = k
120 that.move_cell_up();
120 that.move_cell_up();
121 that.control_key_active = false;
121 that.control_key_active = false;
122 return false;
122 return false;
123 } else if (event.which === 80 && that.control_key_active) {
123 } else if (event.which === 80 && that.control_key_active) {
124 // Select previous = p
124 // Select previous = p
125 that.select_prev();
125 that.select_prev();
126 that.control_key_active = false;
126 that.control_key_active = false;
127 return false;
127 return false;
128 } else if (event.which === 78 && that.control_key_active) {
128 } else if (event.which === 78 && that.control_key_active) {
129 // Select next = n
129 // Select next = n
130 that.select_next();
130 that.select_next();
131 that.control_key_active = false;
131 that.control_key_active = false;
132 return false;
132 return false;
133 } else if (event.which === 72 && that.control_key_active) {
133 } else if (event.which === 72 && that.control_key_active) {
134 // Show keyboard shortcuts = h
134 // Show keyboard shortcuts = h
135 that.show_keyboard_shortcuts();
135 that.show_keyboard_shortcuts();
136 that.control_key_active = false;
136 that.control_key_active = false;
137 return false;
137 return false;
138 } else if (event.which === 73 && that.control_key_active) {
138 } else if (event.which === 73 && that.control_key_active) {
139 // Interrupt kernel = i
139 // Interrupt kernel = i
140 IPython.notebook.kernel.interrupt();
140 IPython.notebook.kernel.interrupt();
141 that.control_key_active = false;
141 that.control_key_active = false;
142 return false;
142 return false;
143 } else if (event.which === 76 && that.control_key_active) {
144 // Toggle line numbers = l
145 that.cell_toggle_line_numbers();
146 that.control_key_active = false;
147 return false;
143 } else if (event.which === 190 && that.control_key_active) {
148 } else if (event.which === 190 && that.control_key_active) {
144 // Restart kernel = . # matches qt console
149 // Restart kernel = . # matches qt console
145 IPython.notebook.restart_kernel();
150 IPython.notebook.restart_kernel();
146 that.control_key_active = false;
151 that.control_key_active = false;
147 return false;
152 return false;
148 } else if (that.control_key_active) {
153 } else if (that.control_key_active) {
149 that.control_key_active = false;
154 that.control_key_active = false;
150 return true;
155 return true;
151 };
156 };
152 });
157 });
153
158
154 this.element.bind('collapse_pager', function () {
159 this.element.bind('collapse_pager', function () {
155 var app_height = $('div#main_app').height(); // content height
160 var app_height = $('div#main_app').height(); // content height
156 var splitter_height = $('div#pager_splitter').outerHeight(true);
161 var splitter_height = $('div#pager_splitter').outerHeight(true);
157 var new_height = app_height - splitter_height;
162 var new_height = app_height - splitter_height;
158 that.element.animate({height : new_height + 'px'}, 'fast');
163 that.element.animate({height : new_height + 'px'}, 'fast');
159 });
164 });
160
165
161 this.element.bind('expand_pager', function () {
166 this.element.bind('expand_pager', function () {
162 var app_height = $('div#main_app').height(); // content height
167 var app_height = $('div#main_app').height(); // content height
163 var splitter_height = $('div#pager_splitter').outerHeight(true);
168 var splitter_height = $('div#pager_splitter').outerHeight(true);
164 var pager_height = $('div#pager').outerHeight(true);
169 var pager_height = $('div#pager').outerHeight(true);
165 var new_height = app_height - pager_height - splitter_height;
170 var new_height = app_height - pager_height - splitter_height;
166 that.element.animate({height : new_height + 'px'}, 'fast');
171 that.element.animate({height : new_height + 'px'}, 'fast');
167 });
172 });
168
173
169 this.element.bind('collapse_left_panel', function () {
174 this.element.bind('collapse_left_panel', function () {
170 var splitter_width = $('div#left_panel_splitter').outerWidth(true);
175 var splitter_width = $('div#left_panel_splitter').outerWidth(true);
171 var new_margin = splitter_width;
176 var new_margin = splitter_width;
172 $('div#notebook_panel').animate({marginLeft : new_margin + 'px'}, 'fast');
177 $('div#notebook_panel').animate({marginLeft : new_margin + 'px'}, 'fast');
173 });
178 });
174
179
175 this.element.bind('expand_left_panel', function () {
180 this.element.bind('expand_left_panel', function () {
176 var splitter_width = $('div#left_panel_splitter').outerWidth(true);
181 var splitter_width = $('div#left_panel_splitter').outerWidth(true);
177 var left_panel_width = IPython.left_panel.width;
182 var left_panel_width = IPython.left_panel.width;
178 var new_margin = splitter_width + left_panel_width;
183 var new_margin = splitter_width + left_panel_width;
179 $('div#notebook_panel').animate({marginLeft : new_margin + 'px'}, 'fast');
184 $('div#notebook_panel').animate({marginLeft : new_margin + 'px'}, 'fast');
180 });
185 });
181
186
182 $(window).bind('beforeunload', function () {
187 $(window).bind('beforeunload', function () {
183 var kill_kernel = $('#kill_kernel').prop('checked');
188 var kill_kernel = $('#kill_kernel').prop('checked');
184 if (kill_kernel) {
189 if (kill_kernel) {
185 that.kernel.kill();
190 that.kernel.kill();
186 }
191 }
187 if (that.dirty) {
192 if (that.dirty) {
188 return "You have unsaved changes that will be lost if you leave this page.";
193 return "You have unsaved changes that will be lost if you leave this page.";
189 };
194 };
190 });
195 });
191 };
196 };
192
197
193
198
194 Notebook.prototype.show_keyboard_shortcuts = function () {
199 Notebook.prototype.show_keyboard_shortcuts = function () {
195 var dialog = $('<div/>');
200 var dialog = $('<div/>');
196 var shortcuts = [
201 var shortcuts = [
197 {key: 'Shift-Enter', help: 'run cell'},
202 {key: 'Shift-Enter', help: 'run cell'},
198 {key: 'Ctrl-Enter', help: 'run cell in terminal mode'},
203 {key: 'Ctrl-Enter', help: 'run cell in-place'},
199 {key: 'Ctrl-Shift-L', help: 'toggle line numbering'},
200 {key: 'Ctrl-m d', help: 'delete cell'},
204 {key: 'Ctrl-m d', help: 'delete cell'},
201 {key: 'Ctrl-m a', help: 'insert cell above'},
205 {key: 'Ctrl-m a', help: 'insert cell above'},
202 {key: 'Ctrl-m b', help: 'insert cell below'},
206 {key: 'Ctrl-m b', help: 'insert cell below'},
203 {key: 'Ctrl-m t', help: 'toggle output'},
207 {key: 'Ctrl-m t', help: 'toggle output'},
208 {key: 'Ctrl-m l', help: 'toggle line numbers'},
204 {key: 'Ctrl-m s', help: 'save notebook'},
209 {key: 'Ctrl-m s', help: 'save notebook'},
205 {key: 'Ctrl-m j', help: 'move cell down'},
210 {key: 'Ctrl-m j', help: 'move cell down'},
206 {key: 'Ctrl-m k', help: 'move cell up'},
211 {key: 'Ctrl-m k', help: 'move cell up'},
207 {key: 'Ctrl-m c', help: 'code cell'},
212 {key: 'Ctrl-m c', help: 'code cell'},
208 {key: 'Ctrl-m m', help: 'markdown cell'},
213 {key: 'Ctrl-m m', help: 'markdown cell'},
209 {key: 'Ctrl-m p', help: 'select previous'},
214 {key: 'Ctrl-m p', help: 'select previous'},
210 {key: 'Ctrl-m n', help: 'select next'},
215 {key: 'Ctrl-m n', help: 'select next'},
211 {key: 'Ctrl-m i', help: 'interrupt kernel'},
216 {key: 'Ctrl-m i', help: 'interrupt kernel'},
212 {key: 'Ctrl-m .', help: 'restart kernel'},
217 {key: 'Ctrl-m .', help: 'restart kernel'},
213 {key: 'Ctrl-m h', help: 'display keyboard shortcuts'}
218 {key: 'Ctrl-m h', help: 'show keyboard shortcuts'}
214 ];
219 ];
215 for (var i=0; i<shortcuts.length; i++) {
220 for (var i=0; i<shortcuts.length; i++) {
216 dialog.append($('<div>').
221 dialog.append($('<div>').
217 append($('<span/>').addClass('shortcut_key').html(shortcuts[i].key)).
222 append($('<span/>').addClass('shortcut_key').html(shortcuts[i].key)).
218 append($('<span/>').addClass('shortcut_descr').html(' : ' + shortcuts[i].help))
223 append($('<span/>').addClass('shortcut_descr').html(' : ' + shortcuts[i].help))
219 );
224 );
220 };
225 };
221 dialog.dialog({title: 'Keyboard shortcuts'});
226 dialog.dialog({title: 'Keyboard shortcuts'});
222 };
227 };
223
228
224
229
225 Notebook.prototype.scroll_to_bottom = function () {
230 Notebook.prototype.scroll_to_bottom = function () {
226 this.element.animate({scrollTop:this.element.get(0).scrollHeight}, 0);
231 this.element.animate({scrollTop:this.element.get(0).scrollHeight}, 0);
227 };
232 };
228
233
229
234
230 Notebook.prototype.scroll_to_top = function () {
235 Notebook.prototype.scroll_to_top = function () {
231 this.element.animate({scrollTop:0}, 0);
236 this.element.animate({scrollTop:0}, 0);
232 };
237 };
233
238
234
239
235 // Cell indexing, retrieval, etc.
240 // Cell indexing, retrieval, etc.
236
241
237
242
238 Notebook.prototype.cell_elements = function () {
243 Notebook.prototype.cell_elements = function () {
239 return this.element.children("div.cell");
244 return this.element.children("div.cell");
240 }
245 }
241
246
242
247
243 Notebook.prototype.ncells = function (cell) {
248 Notebook.prototype.ncells = function (cell) {
244 return this.cell_elements().length;
249 return this.cell_elements().length;
245 }
250 }
246
251
247
252
248 // TODO: we are often calling cells as cells()[i], which we should optimize
253 // TODO: we are often calling cells as cells()[i], which we should optimize
249 // to cells(i) or a new method.
254 // to cells(i) or a new method.
250 Notebook.prototype.cells = function () {
255 Notebook.prototype.cells = function () {
251 return this.cell_elements().toArray().map(function (e) {
256 return this.cell_elements().toArray().map(function (e) {
252 return $(e).data("cell");
257 return $(e).data("cell");
253 });
258 });
254 }
259 }
255
260
256
261
257 Notebook.prototype.find_cell_index = function (cell) {
262 Notebook.prototype.find_cell_index = function (cell) {
258 var result = null;
263 var result = null;
259 this.cell_elements().filter(function (index) {
264 this.cell_elements().filter(function (index) {
260 if ($(this).data("cell") === cell) {
265 if ($(this).data("cell") === cell) {
261 result = index;
266 result = index;
262 };
267 };
263 });
268 });
264 return result;
269 return result;
265 };
270 };
266
271
267
272
268 Notebook.prototype.index_or_selected = function (index) {
273 Notebook.prototype.index_or_selected = function (index) {
269 return index || this.selected_index() || 0;
274 return index || this.selected_index() || 0;
270 }
275 }
271
276
272
277
273 Notebook.prototype.select = function (index) {
278 Notebook.prototype.select = function (index) {
274 if (index !== undefined && index >= 0 && index < this.ncells()) {
279 if (index !== undefined && index >= 0 && index < this.ncells()) {
275 if (this.selected_index() !== null) {
280 if (this.selected_index() !== null) {
276 this.selected_cell().unselect();
281 this.selected_cell().unselect();
277 };
282 };
278 this.cells()[index].select();
283 this.cells()[index].select();
279 };
284 };
280 return this;
285 return this;
281 };
286 };
282
287
283
288
284 Notebook.prototype.select_next = function () {
289 Notebook.prototype.select_next = function () {
285 var index = this.selected_index();
290 var index = this.selected_index();
286 if (index !== null && index >= 0 && (index+1) < this.ncells()) {
291 if (index !== null && index >= 0 && (index+1) < this.ncells()) {
287 this.select(index+1);
292 this.select(index+1);
288 };
293 };
289 return this;
294 return this;
290 };
295 };
291
296
292
297
293 Notebook.prototype.select_prev = function () {
298 Notebook.prototype.select_prev = function () {
294 var index = this.selected_index();
299 var index = this.selected_index();
295 if (index !== null && index >= 0 && (index-1) < this.ncells()) {
300 if (index !== null && index >= 0 && (index-1) < this.ncells()) {
296 this.select(index-1);
301 this.select(index-1);
297 };
302 };
298 return this;
303 return this;
299 };
304 };
300
305
301
306
302 Notebook.prototype.selected_index = function () {
307 Notebook.prototype.selected_index = function () {
303 var result = null;
308 var result = null;
304 this.cell_elements().filter(function (index) {
309 this.cell_elements().filter(function (index) {
305 if ($(this).data("cell").selected === true) {
310 if ($(this).data("cell").selected === true) {
306 result = index;
311 result = index;
307 };
312 };
308 });
313 });
309 return result;
314 return result;
310 };
315 };
311
316
312
317
313 Notebook.prototype.cell_for_msg = function (msg_id) {
318 Notebook.prototype.cell_for_msg = function (msg_id) {
314 var cell_id = this.msg_cell_map[msg_id];
319 var cell_id = this.msg_cell_map[msg_id];
315 var result = null;
320 var result = null;
316 this.cell_elements().filter(function (index) {
321 this.cell_elements().filter(function (index) {
317 cell = $(this).data("cell");
322 cell = $(this).data("cell");
318 if (cell.cell_id === cell_id) {
323 if (cell.cell_id === cell_id) {
319 result = cell;
324 result = cell;
320 };
325 };
321 });
326 });
322 return result;
327 return result;
323 };
328 };
324
329
325
330
326 Notebook.prototype.selected_cell = function () {
331 Notebook.prototype.selected_cell = function () {
327 return this.cell_elements().eq(this.selected_index()).data("cell");
332 return this.cell_elements().eq(this.selected_index()).data("cell");
328 }
333 }
329
334
330
335
331 // Cell insertion, deletion and moving.
336 // Cell insertion, deletion and moving.
332
337
333
338
334 Notebook.prototype.delete_cell = function (index) {
339 Notebook.prototype.delete_cell = function (index) {
335 var i = index || this.selected_index();
340 var i = index || this.selected_index();
336 if (i !== null && i >= 0 && i < this.ncells()) {
341 if (i !== null && i >= 0 && i < this.ncells()) {
337 this.cell_elements().eq(i).remove();
342 this.cell_elements().eq(i).remove();
338 if (i === (this.ncells())) {
343 if (i === (this.ncells())) {
339 this.select(i-1);
344 this.select(i-1);
340 } else {
345 } else {
341 this.select(i);
346 this.select(i);
342 };
347 };
343 };
348 };
344 this.dirty = true;
349 this.dirty = true;
345 return this;
350 return this;
346 };
351 };
347
352
348
353
349 Notebook.prototype.append_cell = function (cell) {
354 Notebook.prototype.append_cell = function (cell) {
350 this.element.find('div.end_space').before(cell.element);
355 this.element.find('div.end_space').before(cell.element);
351 this.dirty = true;
356 this.dirty = true;
352 return this;
357 return this;
353 };
358 };
354
359
355
360
356 Notebook.prototype.insert_cell_below = function (cell, index) {
361 Notebook.prototype.insert_cell_below = function (cell, index) {
357 var ncells = this.ncells();
362 var ncells = this.ncells();
358 if (ncells === 0) {
363 if (ncells === 0) {
359 this.append_cell(cell);
364 this.append_cell(cell);
360 return this;
365 return this;
361 };
366 };
362 if (index >= 0 && index < ncells) {
367 if (index >= 0 && index < ncells) {
363 this.cell_elements().eq(index).after(cell.element);
368 this.cell_elements().eq(index).after(cell.element);
364 };
369 };
365 this.dirty = true;
370 this.dirty = true;
366 return this
371 return this
367 };
372 };
368
373
369
374
370 Notebook.prototype.insert_cell_above = function (cell, index) {
375 Notebook.prototype.insert_cell_above = function (cell, index) {
371 var ncells = this.ncells();
376 var ncells = this.ncells();
372 if (ncells === 0) {
377 if (ncells === 0) {
373 this.append_cell(cell);
378 this.append_cell(cell);
374 return this;
379 return this;
375 };
380 };
376 if (index >= 0 && index < ncells) {
381 if (index >= 0 && index < ncells) {
377 this.cell_elements().eq(index).before(cell.element);
382 this.cell_elements().eq(index).before(cell.element);
378 };
383 };
379 this.dirty = true;
384 this.dirty = true;
380 return this;
385 return this;
381 };
386 };
382
387
383
388
384 Notebook.prototype.move_cell_up = function (index) {
389 Notebook.prototype.move_cell_up = function (index) {
385 var i = index || this.selected_index();
390 var i = index || this.selected_index();
386 if (i !== null && i < this.ncells() && i > 0) {
391 if (i !== null && i < this.ncells() && i > 0) {
387 var pivot = this.cell_elements().eq(i-1);
392 var pivot = this.cell_elements().eq(i-1);
388 var tomove = this.cell_elements().eq(i);
393 var tomove = this.cell_elements().eq(i);
389 if (pivot !== null && tomove !== null) {
394 if (pivot !== null && tomove !== null) {
390 tomove.detach();
395 tomove.detach();
391 pivot.before(tomove);
396 pivot.before(tomove);
392 this.select(i-1);
397 this.select(i-1);
393 };
398 };
394 };
399 };
395 this.dirty = true;
400 this.dirty = true;
396 return this;
401 return this;
397 }
402 }
398
403
399
404
400 Notebook.prototype.move_cell_down = function (index) {
405 Notebook.prototype.move_cell_down = function (index) {
401 var i = index || this.selected_index();
406 var i = index || this.selected_index();
402 if (i !== null && i < (this.ncells()-1) && i >= 0) {
407 if (i !== null && i < (this.ncells()-1) && i >= 0) {
403 var pivot = this.cell_elements().eq(i+1)
408 var pivot = this.cell_elements().eq(i+1)
404 var tomove = this.cell_elements().eq(i)
409 var tomove = this.cell_elements().eq(i)
405 if (pivot !== null && tomove !== null) {
410 if (pivot !== null && tomove !== null) {
406 tomove.detach();
411 tomove.detach();
407 pivot.after(tomove);
412 pivot.after(tomove);
408 this.select(i+1);
413 this.select(i+1);
409 };
414 };
410 };
415 };
411 this.dirty = true;
416 this.dirty = true;
412 return this;
417 return this;
413 }
418 }
414
419
415
420
416 Notebook.prototype.sort_cells = function () {
421 Notebook.prototype.sort_cells = function () {
417 var ncells = this.ncells();
422 var ncells = this.ncells();
418 var sindex = this.selected_index();
423 var sindex = this.selected_index();
419 var swapped;
424 var swapped;
420 do {
425 do {
421 swapped = false
426 swapped = false
422 for (var i=1; i<ncells; i++) {
427 for (var i=1; i<ncells; i++) {
423 current = this.cell_elements().eq(i).data("cell");
428 current = this.cell_elements().eq(i).data("cell");
424 previous = this.cell_elements().eq(i-1).data("cell");
429 previous = this.cell_elements().eq(i-1).data("cell");
425 if (previous.input_prompt_number > current.input_prompt_number) {
430 if (previous.input_prompt_number > current.input_prompt_number) {
426 this.move_cell_up(i);
431 this.move_cell_up(i);
427 swapped = true;
432 swapped = true;
428 };
433 };
429 };
434 };
430 } while (swapped);
435 } while (swapped);
431 this.select(sindex);
436 this.select(sindex);
432 return this;
437 return this;
433 };
438 };
434
439
435
440
436 Notebook.prototype.insert_code_cell_above = function (index) {
441 Notebook.prototype.insert_code_cell_above = function (index) {
437 // TODO: Bounds check for i
442 // TODO: Bounds check for i
438 var i = this.index_or_selected(index);
443 var i = this.index_or_selected(index);
439 var cell = new IPython.CodeCell(this);
444 var cell = new IPython.CodeCell(this);
440 cell.set_input_prompt();
445 cell.set_input_prompt();
441 this.insert_cell_above(cell, i);
446 this.insert_cell_above(cell, i);
442 this.select(this.find_cell_index(cell));
447 this.select(this.find_cell_index(cell));
443 return cell;
448 return cell;
444 }
449 }
445
450
446
451
447 Notebook.prototype.insert_code_cell_below = function (index) {
452 Notebook.prototype.insert_code_cell_below = function (index) {
448 // TODO: Bounds check for i
453 // TODO: Bounds check for i
449 var i = this.index_or_selected(index);
454 var i = this.index_or_selected(index);
450 var cell = new IPython.CodeCell(this);
455 var cell = new IPython.CodeCell(this);
451 cell.set_input_prompt();
456 cell.set_input_prompt();
452 this.insert_cell_below(cell, i);
457 this.insert_cell_below(cell, i);
453 this.select(this.find_cell_index(cell));
458 this.select(this.find_cell_index(cell));
454 return cell;
459 return cell;
455 }
460 }
456
461
457
462
458 Notebook.prototype.insert_html_cell_above = function (index) {
463 Notebook.prototype.insert_html_cell_above = function (index) {
459 // TODO: Bounds check for i
464 // TODO: Bounds check for i
460 var i = this.index_or_selected(index);
465 var i = this.index_or_selected(index);
461 var cell = new IPython.HTMLCell(this);
466 var cell = new IPython.HTMLCell(this);
462 cell.config_mathjax();
467 cell.config_mathjax();
463 this.insert_cell_above(cell, i);
468 this.insert_cell_above(cell, i);
464 this.select(this.find_cell_index(cell));
469 this.select(this.find_cell_index(cell));
465 return cell;
470 return cell;
466 }
471 }
467
472
468
473
469 Notebook.prototype.insert_html_cell_below = function (index) {
474 Notebook.prototype.insert_html_cell_below = function (index) {
470 // TODO: Bounds check for i
475 // TODO: Bounds check for i
471 var i = this.index_or_selected(index);
476 var i = this.index_or_selected(index);
472 var cell = new IPython.HTMLCell(this);
477 var cell = new IPython.HTMLCell(this);
473 cell.config_mathjax();
478 cell.config_mathjax();
474 this.insert_cell_below(cell, i);
479 this.insert_cell_below(cell, i);
475 this.select(this.find_cell_index(cell));
480 this.select(this.find_cell_index(cell));
476 return cell;
481 return cell;
477 }
482 }
478
483
479
484
480 Notebook.prototype.insert_markdown_cell_above = function (index) {
485 Notebook.prototype.insert_markdown_cell_above = function (index) {
481 // TODO: Bounds check for i
486 // TODO: Bounds check for i
482 var i = this.index_or_selected(index);
487 var i = this.index_or_selected(index);
483 var cell = new IPython.MarkdownCell(this);
488 var cell = new IPython.MarkdownCell(this);
484 cell.config_mathjax();
489 cell.config_mathjax();
485 this.insert_cell_above(cell, i);
490 this.insert_cell_above(cell, i);
486 this.select(this.find_cell_index(cell));
491 this.select(this.find_cell_index(cell));
487 return cell;
492 return cell;
488 }
493 }
489
494
490
495
491 Notebook.prototype.insert_markdown_cell_below = function (index) {
496 Notebook.prototype.insert_markdown_cell_below = function (index) {
492 // TODO: Bounds check for i
497 // TODO: Bounds check for i
493 var i = this.index_or_selected(index);
498 var i = this.index_or_selected(index);
494 var cell = new IPython.MarkdownCell(this);
499 var cell = new IPython.MarkdownCell(this);
495 cell.config_mathjax();
500 cell.config_mathjax();
496 this.insert_cell_below(cell, i);
501 this.insert_cell_below(cell, i);
497 this.select(this.find_cell_index(cell));
502 this.select(this.find_cell_index(cell));
498 return cell;
503 return cell;
499 }
504 }
500
505
501
506
502 Notebook.prototype.to_code = function (index) {
507 Notebook.prototype.to_code = function (index) {
503 // TODO: Bounds check for i
508 // TODO: Bounds check for i
504 var i = this.index_or_selected(index);
509 var i = this.index_or_selected(index);
505 var source_element = this.cell_elements().eq(i);
510 var source_element = this.cell_elements().eq(i);
506 var source_cell = source_element.data("cell");
511 var source_cell = source_element.data("cell");
507 if (source_cell instanceof IPython.HTMLCell ||
512 if (source_cell instanceof IPython.HTMLCell ||
508 source_cell instanceof IPython.MarkdownCell) {
513 source_cell instanceof IPython.MarkdownCell) {
509 this.insert_code_cell_below(i);
514 this.insert_code_cell_below(i);
510 var target_cell = this.cells()[i+1];
515 var target_cell = this.cells()[i+1];
511 target_cell.set_code(source_cell.get_source());
516 target_cell.set_code(source_cell.get_source());
512 source_element.remove();
517 source_element.remove();
513 target_cell.select();
518 target_cell.select();
514 };
519 };
515 this.dirty = true;
520 this.dirty = true;
516 };
521 };
517
522
518
523
519 Notebook.prototype.to_markdown = function (index) {
524 Notebook.prototype.to_markdown = function (index) {
520 // TODO: Bounds check for i
525 // TODO: Bounds check for i
521 var i = this.index_or_selected(index);
526 var i = this.index_or_selected(index);
522 var source_element = this.cell_elements().eq(i);
527 var source_element = this.cell_elements().eq(i);
523 var source_cell = source_element.data("cell");
528 var source_cell = source_element.data("cell");
524 var target_cell = null;
529 var target_cell = null;
525 if (source_cell instanceof IPython.CodeCell) {
530 if (source_cell instanceof IPython.CodeCell) {
526 this.insert_markdown_cell_below(i);
531 this.insert_markdown_cell_below(i);
527 var target_cell = this.cells()[i+1];
532 var target_cell = this.cells()[i+1];
528 var text = source_cell.get_code();
533 var text = source_cell.get_code();
529 } else if (source_cell instanceof IPython.HTMLCell) {
534 } else if (source_cell instanceof IPython.HTMLCell) {
530 this.insert_markdown_cell_below(i);
535 this.insert_markdown_cell_below(i);
531 var target_cell = this.cells()[i+1];
536 var target_cell = this.cells()[i+1];
532 var text = source_cell.get_source();
537 var text = source_cell.get_source();
533 if (text === source_cell.placeholder) {
538 if (text === source_cell.placeholder) {
534 text = target_cell.placeholder;
539 text = target_cell.placeholder;
535 }
540 }
536 }
541 }
537 if (target_cell !== null) {
542 if (target_cell !== null) {
538 if (text === "") {text = target_cell.placeholder;};
543 if (text === "") {text = target_cell.placeholder;};
539 target_cell.set_source(text);
544 target_cell.set_source(text);
540 source_element.remove();
545 source_element.remove();
541 target_cell.edit();
546 target_cell.edit();
542 }
547 }
543 this.dirty = true;
548 this.dirty = true;
544 };
549 };
545
550
546
551
547 Notebook.prototype.to_html = function (index) {
552 Notebook.prototype.to_html = function (index) {
548 // TODO: Bounds check for i
553 // TODO: Bounds check for i
549 var i = this.index_or_selected(index);
554 var i = this.index_or_selected(index);
550 var source_element = this.cell_elements().eq(i);
555 var source_element = this.cell_elements().eq(i);
551 var source_cell = source_element.data("cell");
556 var source_cell = source_element.data("cell");
552 var target_cell = null;
557 var target_cell = null;
553 if (source_cell instanceof IPython.CodeCell) {
558 if (source_cell instanceof IPython.CodeCell) {
554 this.insert_html_cell_below(i);
559 this.insert_html_cell_below(i);
555 var target_cell = this.cells()[i+1];
560 var target_cell = this.cells()[i+1];
556 var text = source_cell.get_code();
561 var text = source_cell.get_code();
557 } else if (source_cell instanceof IPython.MarkdownCell) {
562 } else if (source_cell instanceof IPython.MarkdownCell) {
558 this.insert_html_cell_below(i);
563 this.insert_html_cell_below(i);
559 var target_cell = this.cells()[i+1];
564 var target_cell = this.cells()[i+1];
560 var text = source_cell.get_source();
565 var text = source_cell.get_source();
561 if (text === source_cell.placeholder) {
566 if (text === source_cell.placeholder) {
562 text = target_cell.placeholder;
567 text = target_cell.placeholder;
563 }
568 }
564 }
569 }
565 if (target_cell !== null) {
570 if (target_cell !== null) {
566 if (text === "") {text = target_cell.placeholder;};
571 if (text === "") {text = target_cell.placeholder;};
567 target_cell.set_source(text);
572 target_cell.set_source(text);
568 source_element.remove();
573 source_element.remove();
569 target_cell.edit();
574 target_cell.edit();
570 }
575 }
571 this.dirty = true;
576 this.dirty = true;
572 };
577 };
573
578
574
579
575 // Cell collapsing and output clearing
580 // Cell collapsing and output clearing
576
581
577 Notebook.prototype.collapse = function (index) {
582 Notebook.prototype.collapse = function (index) {
578 var i = this.index_or_selected(index);
583 var i = this.index_or_selected(index);
579 this.cells()[i].collapse();
584 this.cells()[i].collapse();
580 this.dirty = true;
585 this.dirty = true;
581 };
586 };
582
587
583
588
584 Notebook.prototype.expand = function (index) {
589 Notebook.prototype.expand = function (index) {
585 var i = this.index_or_selected(index);
590 var i = this.index_or_selected(index);
586 this.cells()[i].expand();
591 this.cells()[i].expand();
587 this.dirty = true;
592 this.dirty = true;
588 };
593 };
589
594
590
595
591 Notebook.prototype.toggle_output = function (index) {
596 Notebook.prototype.toggle_output = function (index) {
592 var i = this.index_or_selected(index);
597 var i = this.index_or_selected(index);
593 this.cells()[i].toggle_output();
598 this.cells()[i].toggle_output();
594 this.dirty = true;
599 this.dirty = true;
595 };
600 };
596
601
597
602
598 Notebook.prototype.set_autoindent = function (state) {
603 Notebook.prototype.set_autoindent = function (state) {
599 var cells = this.cells();
604 var cells = this.cells();
600 len = cells.length;
605 len = cells.length;
601 for (var i=0; i<len; i++) {
606 for (var i=0; i<len; i++) {
602 cells[i].set_autoindent(state)
607 cells[i].set_autoindent(state)
603 };
608 };
604 };
609 };
605
610
606
611
607 Notebook.prototype.clear_all_output = function () {
612 Notebook.prototype.clear_all_output = function () {
608 var ncells = this.ncells();
613 var ncells = this.ncells();
609 var cells = this.cells();
614 var cells = this.cells();
610 for (var i=0; i<ncells; i++) {
615 for (var i=0; i<ncells; i++) {
611 if (cells[i] instanceof IPython.CodeCell) {
616 if (cells[i] instanceof IPython.CodeCell) {
612 cells[i].clear_output();
617 cells[i].clear_output();
613 }
618 }
614 };
619 };
615 this.dirty = true;
620 this.dirty = true;
616 };
621 };
617
622
623 // Other cell functions: line numbers, ...
624
625 Notebook.prototype.cell_toggle_line_numbers = function() {
626 this.selected_cell().toggle_line_numbers()
627 };
618
628
619 // Kernel related things
629 // Kernel related things
620
630
621 Notebook.prototype.start_kernel = function () {
631 Notebook.prototype.start_kernel = function () {
622 this.kernel = new IPython.Kernel();
632 this.kernel = new IPython.Kernel();
623 var notebook_id = IPython.save_widget.get_notebook_id();
633 var notebook_id = IPython.save_widget.get_notebook_id();
624 this.kernel.start(notebook_id, $.proxy(this.kernel_started, this));
634 this.kernel.start(notebook_id, $.proxy(this.kernel_started, this));
625 };
635 };
626
636
627
637
628 Notebook.prototype.restart_kernel = function () {
638 Notebook.prototype.restart_kernel = function () {
629 var notebook_id = IPython.save_widget.get_notebook_id();
639 var notebook_id = IPython.save_widget.get_notebook_id();
630 this.kernel.restart($.proxy(this.kernel_started, this));
640 this.kernel.restart($.proxy(this.kernel_started, this));
631 };
641 };
632
642
633
643
634 Notebook.prototype.kernel_started = function () {
644 Notebook.prototype.kernel_started = function () {
635 console.log("Kernel started: ", this.kernel.kernel_id);
645 console.log("Kernel started: ", this.kernel.kernel_id);
636 this.kernel.shell_channel.onmessage = $.proxy(this.handle_shell_reply,this);
646 this.kernel.shell_channel.onmessage = $.proxy(this.handle_shell_reply,this);
637 this.kernel.iopub_channel.onmessage = $.proxy(this.handle_iopub_reply,this);
647 this.kernel.iopub_channel.onmessage = $.proxy(this.handle_iopub_reply,this);
638 };
648 };
639
649
640
650
641 Notebook.prototype.handle_shell_reply = function (e) {
651 Notebook.prototype.handle_shell_reply = function (e) {
642 reply = $.parseJSON(e.data);
652 reply = $.parseJSON(e.data);
643 var header = reply.header;
653 var header = reply.header;
644 var content = reply.content;
654 var content = reply.content;
645 var msg_type = header.msg_type;
655 var msg_type = header.msg_type;
646 // console.log(reply);
656 // console.log(reply);
647 var cell = this.cell_for_msg(reply.parent_header.msg_id);
657 var cell = this.cell_for_msg(reply.parent_header.msg_id);
648 if (msg_type === "execute_reply") {
658 if (msg_type === "execute_reply") {
649 cell.set_input_prompt(content.execution_count);
659 cell.set_input_prompt(content.execution_count);
650 this.dirty = true;
660 this.dirty = true;
651 } else if (msg_type === "complete_reply") {
661 } else if (msg_type === "complete_reply") {
652 cell.finish_completing(content.matched_text, content.matches);
662 cell.finish_completing(content.matched_text, content.matches);
653 };
663 };
654 var payload = content.payload || [];
664 var payload = content.payload || [];
655 this.handle_payload(cell, payload);
665 this.handle_payload(cell, payload);
656 };
666 };
657
667
658
668
659 Notebook.prototype.handle_payload = function (cell, payload) {
669 Notebook.prototype.handle_payload = function (cell, payload) {
660 var l = payload.length;
670 var l = payload.length;
661 for (var i=0; i<l; i++) {
671 for (var i=0; i<l; i++) {
662 if (payload[i].source === 'IPython.zmq.page.page') {
672 if (payload[i].source === 'IPython.zmq.page.page') {
663 if (payload[i].text.trim() !== '') {
673 if (payload[i].text.trim() !== '') {
664 IPython.pager.clear();
674 IPython.pager.clear();
665 IPython.pager.expand();
675 IPython.pager.expand();
666 IPython.pager.append_text(payload[i].text);
676 IPython.pager.append_text(payload[i].text);
667 }
677 }
668 } else if (payload[i].source === 'IPython.zmq.zmqshell.ZMQInteractiveShell.set_next_input') {
678 } else if (payload[i].source === 'IPython.zmq.zmqshell.ZMQInteractiveShell.set_next_input') {
669 var index = this.find_cell_index(cell);
679 var index = this.find_cell_index(cell);
670 var new_cell = this.insert_code_cell_below(index);
680 var new_cell = this.insert_code_cell_below(index);
671 new_cell.set_code(payload[i].text);
681 new_cell.set_code(payload[i].text);
672 this.dirty = true;
682 this.dirty = true;
673 }
683 }
674 };
684 };
675 };
685 };
676
686
677
687
678 Notebook.prototype.handle_iopub_reply = function (e) {
688 Notebook.prototype.handle_iopub_reply = function (e) {
679 reply = $.parseJSON(e.data);
689 reply = $.parseJSON(e.data);
680 var content = reply.content;
690 var content = reply.content;
681 // console.log(reply);
691 // console.log(reply);
682 var msg_type = reply.header.msg_type;
692 var msg_type = reply.header.msg_type;
683 var cell = this.cell_for_msg(reply.parent_header.msg_id);
693 var cell = this.cell_for_msg(reply.parent_header.msg_id);
684 var output_types = ['stream','display_data','pyout','pyerr'];
694 var output_types = ['stream','display_data','pyout','pyerr'];
685 if (output_types.indexOf(msg_type) >= 0) {
695 if (output_types.indexOf(msg_type) >= 0) {
686 this.handle_output(cell, msg_type, content);
696 this.handle_output(cell, msg_type, content);
687 } else if (msg_type === 'status') {
697 } else if (msg_type === 'status') {
688 if (content.execution_state === 'busy') {
698 if (content.execution_state === 'busy') {
689 IPython.kernel_status_widget.status_busy();
699 IPython.kernel_status_widget.status_busy();
690 } else if (content.execution_state === 'idle') {
700 } else if (content.execution_state === 'idle') {
691 IPython.kernel_status_widget.status_idle();
701 IPython.kernel_status_widget.status_idle();
692 } else if (content.execution_state === 'dead') {
702 } else if (content.execution_state === 'dead') {
693 this.handle_status_dead();
703 this.handle_status_dead();
694 };
704 };
695 }
705 }
696 };
706 };
697
707
698
708
699 Notebook.prototype.handle_status_dead = function () {
709 Notebook.prototype.handle_status_dead = function () {
700 var that = this;
710 var that = this;
701 this.kernel.stop_channels();
711 this.kernel.stop_channels();
702 var dialog = $('<div/>');
712 var dialog = $('<div/>');
703 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.');
713 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.');
704 $(document).append(dialog);
714 $(document).append(dialog);
705 dialog.dialog({
715 dialog.dialog({
706 resizable: false,
716 resizable: false,
707 modal: true,
717 modal: true,
708 title: "Dead kernel",
718 title: "Dead kernel",
709 buttons : {
719 buttons : {
710 "Yes": function () {
720 "Yes": function () {
711 that.start_kernel();
721 that.start_kernel();
712 $(this).dialog('close');
722 $(this).dialog('close');
713 },
723 },
714 "No": function () {
724 "No": function () {
715 $(this).dialog('close');
725 $(this).dialog('close');
716 }
726 }
717 }
727 }
718 });
728 });
719 };
729 };
720
730
721
731
722 Notebook.prototype.handle_output = function (cell, msg_type, content) {
732 Notebook.prototype.handle_output = function (cell, msg_type, content) {
723 var json = {};
733 var json = {};
724 json.output_type = msg_type;
734 json.output_type = msg_type;
725 if (msg_type === "stream") {
735 if (msg_type === "stream") {
726 json.text = utils.fixConsole(content.data);
736 json.text = utils.fixConsole(content.data);
727 json.stream = content.name;
737 json.stream = content.name;
728 } else if (msg_type === "display_data") {
738 } else if (msg_type === "display_data") {
729 json = this.convert_mime_types(json, content.data);
739 json = this.convert_mime_types(json, content.data);
730 } else if (msg_type === "pyout") {
740 } else if (msg_type === "pyout") {
731 json.prompt_number = content.execution_count;
741 json.prompt_number = content.execution_count;
732 json = this.convert_mime_types(json, content.data);
742 json = this.convert_mime_types(json, content.data);
733 } else if (msg_type === "pyerr") {
743 } else if (msg_type === "pyerr") {
734 json.ename = content.ename;
744 json.ename = content.ename;
735 json.evalue = content.evalue;
745 json.evalue = content.evalue;
736 var traceback = [];
746 var traceback = [];
737 for (var i=0; i<content.traceback.length; i++) {
747 for (var i=0; i<content.traceback.length; i++) {
738 traceback.push(utils.fixConsole(content.traceback[i]));
748 traceback.push(utils.fixConsole(content.traceback[i]));
739 }
749 }
740 json.traceback = traceback;
750 json.traceback = traceback;
741 };
751 };
742 cell.append_output(json);
752 cell.append_output(json);
743 this.dirty = true;
753 this.dirty = true;
744 };
754 };
745
755
746
756
747 Notebook.prototype.convert_mime_types = function (json, data) {
757 Notebook.prototype.convert_mime_types = function (json, data) {
748 if (data['text/plain'] !== undefined) {
758 if (data['text/plain'] !== undefined) {
749 json.text = utils.fixConsole(data['text/plain']);
759 json.text = utils.fixConsole(data['text/plain']);
750 };
760 };
751 if (data['text/html'] !== undefined) {
761 if (data['text/html'] !== undefined) {
752 json.html = data['text/html'];
762 json.html = data['text/html'];
753 };
763 };
754 if (data['image/svg+xml'] !== undefined) {
764 if (data['image/svg+xml'] !== undefined) {
755 json.svg = data['image/svg+xml'];
765 json.svg = data['image/svg+xml'];
756 };
766 };
757 if (data['image/png'] !== undefined) {
767 if (data['image/png'] !== undefined) {
758 json.png = data['image/png'];
768 json.png = data['image/png'];
759 };
769 };
760 if (data['image/jpeg'] !== undefined) {
770 if (data['image/jpeg'] !== undefined) {
761 json.jpeg = data['image/jpeg'];
771 json.jpeg = data['image/jpeg'];
762 };
772 };
763 if (data['text/latex'] !== undefined) {
773 if (data['text/latex'] !== undefined) {
764 json.latex = data['text/latex'];
774 json.latex = data['text/latex'];
765 };
775 };
766 if (data['application/json'] !== undefined) {
776 if (data['application/json'] !== undefined) {
767 json.json = data['application/json'];
777 json.json = data['application/json'];
768 };
778 };
769 if (data['application/javascript'] !== undefined) {
779 if (data['application/javascript'] !== undefined) {
770 json.javascript = data['application/javascript'];
780 json.javascript = data['application/javascript'];
771 }
781 }
772 return json;
782 return json;
773 };
783 };
774
784
775
785
776 Notebook.prototype.execute_selected_cell = function (options) {
786 Notebook.prototype.execute_selected_cell = function (options) {
777 // add_new: should a new cell be added if we are at the end of the nb
787 // add_new: should a new cell be added if we are at the end of the nb
778 // terminal: execute in terminal mode, which stays in the current cell
788 // terminal: execute in terminal mode, which stays in the current cell
779 default_options = {terminal: false, add_new: true}
789 default_options = {terminal: false, add_new: true}
780 $.extend(default_options, options)
790 $.extend(default_options, options)
781 var that = this;
791 var that = this;
782 var cell = that.selected_cell();
792 var cell = that.selected_cell();
783 var cell_index = that.find_cell_index(cell);
793 var cell_index = that.find_cell_index(cell);
784 if (cell instanceof IPython.CodeCell) {
794 if (cell instanceof IPython.CodeCell) {
785 cell.clear_output();
795 cell.clear_output();
786 var code = cell.get_code();
796 var code = cell.get_code();
787 var msg_id = that.kernel.execute(cell.get_code());
797 var msg_id = that.kernel.execute(cell.get_code());
788 that.msg_cell_map[msg_id] = cell.cell_id;
798 that.msg_cell_map[msg_id] = cell.cell_id;
789 } else if (cell instanceof IPython.HTMLCell) {
799 } else if (cell instanceof IPython.HTMLCell) {
790 cell.render();
800 cell.render();
791 }
801 }
792 if (default_options.terminal) {
802 if (default_options.terminal) {
793 cell.select_all();
803 cell.select_all();
794 } else {
804 } else {
795 if ((cell_index === (that.ncells()-1)) && default_options.add_new) {
805 if ((cell_index === (that.ncells()-1)) && default_options.add_new) {
796 that.insert_code_cell_below();
806 that.insert_code_cell_below();
797 // If we are adding a new cell at the end, scroll down to show it.
807 // If we are adding a new cell at the end, scroll down to show it.
798 that.scroll_to_bottom();
808 that.scroll_to_bottom();
799 } else {
809 } else {
800 that.select(cell_index+1);
810 that.select(cell_index+1);
801 };
811 };
802 };
812 };
803 this.dirty = true;
813 this.dirty = true;
804 };
814 };
805
815
806
816
807 Notebook.prototype.execute_all_cells = function () {
817 Notebook.prototype.execute_all_cells = function () {
808 var ncells = this.ncells();
818 var ncells = this.ncells();
809 for (var i=0; i<ncells; i++) {
819 for (var i=0; i<ncells; i++) {
810 this.select(i);
820 this.select(i);
811 this.execute_selected_cell({add_new:false});
821 this.execute_selected_cell({add_new:false});
812 };
822 };
813 this.scroll_to_bottom();
823 this.scroll_to_bottom();
814 };
824 };
815
825
816
826
817 Notebook.prototype.complete_cell = function (cell, line, cursor_pos) {
827 Notebook.prototype.complete_cell = function (cell, line, cursor_pos) {
818 var msg_id = this.kernel.complete(line, cursor_pos);
828 var msg_id = this.kernel.complete(line, cursor_pos);
819 this.msg_cell_map[msg_id] = cell.cell_id;
829 this.msg_cell_map[msg_id] = cell.cell_id;
820 };
830 };
821
831
822 // Persistance and loading
832 // Persistance and loading
823
833
824
834
825 Notebook.prototype.fromJSON = function (data) {
835 Notebook.prototype.fromJSON = function (data) {
826 var ncells = this.ncells();
836 var ncells = this.ncells();
827 for (var i=0; i<ncells; i++) {
837 for (var i=0; i<ncells; i++) {
828 // Always delete cell 0 as they get renumbered as they are deleted.
838 // Always delete cell 0 as they get renumbered as they are deleted.
829 this.delete_cell(0);
839 this.delete_cell(0);
830 };
840 };
831 // Save the metadata
841 // Save the metadata
832 this.metadata = data.metadata;
842 this.metadata = data.metadata;
833 // Only handle 1 worksheet for now.
843 // Only handle 1 worksheet for now.
834 var worksheet = data.worksheets[0];
844 var worksheet = data.worksheets[0];
835 if (worksheet !== undefined) {
845 if (worksheet !== undefined) {
836 var new_cells = worksheet.cells;
846 var new_cells = worksheet.cells;
837 ncells = new_cells.length;
847 ncells = new_cells.length;
838 var cell_data = null;
848 var cell_data = null;
839 var new_cell = null;
849 var new_cell = null;
840 for (var i=0; i<ncells; i++) {
850 for (var i=0; i<ncells; i++) {
841 cell_data = new_cells[i];
851 cell_data = new_cells[i];
842 if (cell_data.cell_type == 'code') {
852 if (cell_data.cell_type == 'code') {
843 new_cell = this.insert_code_cell_below();
853 new_cell = this.insert_code_cell_below();
844 new_cell.fromJSON(cell_data);
854 new_cell.fromJSON(cell_data);
845 } else if (cell_data.cell_type === 'html') {
855 } else if (cell_data.cell_type === 'html') {
846 new_cell = this.insert_html_cell_below();
856 new_cell = this.insert_html_cell_below();
847 new_cell.fromJSON(cell_data);
857 new_cell.fromJSON(cell_data);
848 } else if (cell_data.cell_type === 'markdown') {
858 } else if (cell_data.cell_type === 'markdown') {
849 new_cell = this.insert_markdown_cell_below();
859 new_cell = this.insert_markdown_cell_below();
850 new_cell.fromJSON(cell_data);
860 new_cell.fromJSON(cell_data);
851 };
861 };
852 };
862 };
853 };
863 };
854 };
864 };
855
865
856
866
857 Notebook.prototype.toJSON = function () {
867 Notebook.prototype.toJSON = function () {
858 var cells = this.cells();
868 var cells = this.cells();
859 var ncells = cells.length;
869 var ncells = cells.length;
860 cell_array = new Array(ncells);
870 cell_array = new Array(ncells);
861 for (var i=0; i<ncells; i++) {
871 for (var i=0; i<ncells; i++) {
862 cell_array[i] = cells[i].toJSON();
872 cell_array[i] = cells[i].toJSON();
863 };
873 };
864 data = {
874 data = {
865 // Only handle 1 worksheet for now.
875 // Only handle 1 worksheet for now.
866 worksheets : [{cells:cell_array}],
876 worksheets : [{cells:cell_array}],
867 metadata : this.metadata
877 metadata : this.metadata
868 }
878 }
869 return data
879 return data
870 };
880 };
871
881
872 Notebook.prototype.save_notebook = function () {
882 Notebook.prototype.save_notebook = function () {
873 if (IPython.save_widget.test_notebook_name()) {
883 if (IPython.save_widget.test_notebook_name()) {
874 var notebook_id = IPython.save_widget.get_notebook_id();
884 var notebook_id = IPython.save_widget.get_notebook_id();
875 var nbname = IPython.save_widget.get_notebook_name();
885 var nbname = IPython.save_widget.get_notebook_name();
876 // We may want to move the name/id/nbformat logic inside toJSON?
886 // We may want to move the name/id/nbformat logic inside toJSON?
877 var data = this.toJSON();
887 var data = this.toJSON();
878 data.metadata.name = nbname;
888 data.metadata.name = nbname;
879 data.nbformat = 2;
889 data.nbformat = 2;
880 // We do the call with settings so we can set cache to false.
890 // We do the call with settings so we can set cache to false.
881 var settings = {
891 var settings = {
882 processData : false,
892 processData : false,
883 cache : false,
893 cache : false,
884 type : "PUT",
894 type : "PUT",
885 data : JSON.stringify(data),
895 data : JSON.stringify(data),
886 headers : {'Content-Type': 'application/json'},
896 headers : {'Content-Type': 'application/json'},
887 success : $.proxy(this.notebook_saved,this)
897 success : $.proxy(this.notebook_saved,this)
888 };
898 };
889 IPython.save_widget.status_saving();
899 IPython.save_widget.status_saving();
890 $.ajax("/notebooks/" + notebook_id, settings);
900 $.ajax("/notebooks/" + notebook_id, settings);
891 };
901 };
892 };
902 };
893
903
894
904
895 Notebook.prototype.notebook_saved = function (data, status, xhr) {
905 Notebook.prototype.notebook_saved = function (data, status, xhr) {
896 this.dirty = false;
906 this.dirty = false;
897 setTimeout($.proxy(IPython.save_widget.status_save,IPython.save_widget),500);
907 setTimeout($.proxy(IPython.save_widget.status_save,IPython.save_widget),500);
898 }
908 }
899
909
900
910
901 Notebook.prototype.load_notebook = function (callback) {
911 Notebook.prototype.load_notebook = function (callback) {
902 var that = this;
912 var that = this;
903 var notebook_id = IPython.save_widget.get_notebook_id();
913 var notebook_id = IPython.save_widget.get_notebook_id();
904 // We do the call with settings so we can set cache to false.
914 // We do the call with settings so we can set cache to false.
905 var settings = {
915 var settings = {
906 processData : false,
916 processData : false,
907 cache : false,
917 cache : false,
908 type : "GET",
918 type : "GET",
909 dataType : "json",
919 dataType : "json",
910 success : function (data, status, xhr) {
920 success : function (data, status, xhr) {
911 that.notebook_loaded(data, status, xhr);
921 that.notebook_loaded(data, status, xhr);
912 if (callback !== undefined) {
922 if (callback !== undefined) {
913 callback();
923 callback();
914 };
924 };
915 }
925 }
916 };
926 };
917 IPython.save_widget.status_loading();
927 IPython.save_widget.status_loading();
918 $.ajax("/notebooks/" + notebook_id, settings);
928 $.ajax("/notebooks/" + notebook_id, settings);
919 }
929 }
920
930
921
931
922 Notebook.prototype.notebook_loaded = function (data, status, xhr) {
932 Notebook.prototype.notebook_loaded = function (data, status, xhr) {
923 this.fromJSON(data);
933 this.fromJSON(data);
924 if (this.ncells() === 0) {
934 if (this.ncells() === 0) {
925 this.insert_code_cell_below();
935 this.insert_code_cell_below();
926 };
936 };
927 IPython.save_widget.status_save();
937 IPython.save_widget.status_save();
928 IPython.save_widget.set_notebook_name(data.metadata.name);
938 IPython.save_widget.set_notebook_name(data.metadata.name);
929 this.start_kernel();
939 this.start_kernel();
930 this.dirty = false;
940 this.dirty = false;
931 // fromJSON always selects the last cell inserted. We need to wait
941 // fromJSON always selects the last cell inserted. We need to wait
932 // until that is done before scrolling to the top.
942 // until that is done before scrolling to the top.
933 setTimeout(function () {
943 setTimeout(function () {
934 IPython.notebook.select(0);
944 IPython.notebook.select(0);
935 IPython.notebook.scroll_to_top();
945 IPython.notebook.scroll_to_top();
936 }, 50);
946 }, 50);
937 };
947 };
938
948
939 IPython.Notebook = Notebook;
949 IPython.Notebook = Notebook;
940
950
941 return IPython;
951 return IPython;
942
952
943 }(IPython));
953 }(IPython));
944
954
@@ -1,278 +1,278 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 <link rel="stylesheet" href="static/jquery/css/themes/aristo/jquery-wijmo.css" type="text/css" />
9 <link rel="stylesheet" href="static/jquery/css/themes/aristo/jquery-wijmo.css" type="text/css" />
10 <!-- <link rel="stylesheet" href="static/jquery/css/themes/rocket/jquery-wijmo.css" type="text/css" /> -->
10 <!-- <link rel="stylesheet" href="static/jquery/css/themes/rocket/jquery-wijmo.css" type="text/css" /> -->
11 <!-- <link rel="stylesheet" href="static/jquery/css/themes/smoothness/jquery-ui-1.8.14.custom.css" type="text/css" />-->
11 <!-- <link rel="stylesheet" href="static/jquery/css/themes/smoothness/jquery-ui-1.8.14.custom.css" type="text/css" />-->
12
12
13 <!-- <script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_HTML" charset="utf-8"></script> -->
13 <!-- <script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_HTML" charset="utf-8"></script> -->
14 <script type='text/javascript' src='static/mathjax/MathJax.js?config=TeX-AMS_HTML' charset='utf-8'></script>
14 <script type='text/javascript' src='static/mathjax/MathJax.js?config=TeX-AMS_HTML' charset='utf-8'></script>
15 <script type="text/javascript">
15 <script type="text/javascript">
16 function CheckMathJax(){
16 function CheckMathJax(){
17 var div=document.getElementById("MathJaxFetchingWarning")
17 var div=document.getElementById("MathJaxFetchingWarning")
18 if(window.MathJax){
18 if(window.MathJax){
19 document.body.removeChild(div)
19 document.body.removeChild(div)
20 }
20 }
21 else{
21 else{
22 div.style.display = "block";
22 div.style.display = "block";
23 }
23 }
24 }
24 }
25 if (typeof MathJax == 'undefined') {
25 if (typeof MathJax == 'undefined') {
26 console.log("No local MathJax, loading from CDN");
26 console.log("No local MathJax, loading from CDN");
27 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"));
27 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"));
28 }else{
28 }else{
29 console.log("Using local MathJax");
29 console.log("Using local MathJax");
30 }
30 }
31 </script>
31 </script>
32
32
33 <link rel="stylesheet" href="static/codemirror/lib/codemirror.css">
33 <link rel="stylesheet" href="static/codemirror/lib/codemirror.css">
34 <link rel="stylesheet" href="static/codemirror/mode/markdown/markdown.css">
34 <link rel="stylesheet" href="static/codemirror/mode/markdown/markdown.css">
35 <link rel="stylesheet" href="static/codemirror/mode/rst/rst.css">
35 <link rel="stylesheet" href="static/codemirror/mode/rst/rst.css">
36 <link rel="stylesheet" href="static/codemirror/theme/ipython.css">
36 <link rel="stylesheet" href="static/codemirror/theme/ipython.css">
37 <link rel="stylesheet" href="static/codemirror/theme/default.css">
37 <link rel="stylesheet" href="static/codemirror/theme/default.css">
38
38
39 <link rel="stylesheet" href="static/prettify/prettify.css"/>
39 <link rel="stylesheet" href="static/prettify/prettify.css"/>
40
40
41 <link rel="stylesheet" href="static/css/boilerplate.css" type="text/css" />
41 <link rel="stylesheet" href="static/css/boilerplate.css" type="text/css" />
42 <link rel="stylesheet" href="static/css/layout.css" type="text/css" />
42 <link rel="stylesheet" href="static/css/layout.css" type="text/css" />
43 <link rel="stylesheet" href="static/css/base.css" type="text/css" />
43 <link rel="stylesheet" href="static/css/base.css" type="text/css" />
44 <link rel="stylesheet" href="static/css/notebook.css" type="text/css" />
44 <link rel="stylesheet" href="static/css/notebook.css" type="text/css" />
45 <link rel="stylesheet" href="static/css/renderedhtml.css" type="text/css" />
45 <link rel="stylesheet" href="static/css/renderedhtml.css" type="text/css" />
46
46
47
47
48 </head>
48 </head>
49
49
50 <body onload='CheckMathJax();'>
50 <body onload='CheckMathJax();'>
51
51
52 <div id="header">
52 <div id="header">
53 <span id="ipython_notebook"><h1>IPython Notebook</h1></span>
53 <span id="ipython_notebook"><h1>IPython Notebook</h1></span>
54 <span id="save_widget">
54 <span id="save_widget">
55 <input type="text" id="notebook_name" size="20"></textarea>
55 <input type="text" id="notebook_name" size="20"></textarea>
56 <span id="notebook_id" style="display:none">{{notebook_id}}</span>
56 <span id="notebook_id" style="display:none">{{notebook_id}}</span>
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="kernel_status">Idle</span>
59 <span id="kernel_status">Idle</span>
60 </div>
60 </div>
61
61
62 <div id="MathJaxFetchingWarning"
62 <div id="MathJaxFetchingWarning"
63 style="width:80%; margin:auto;padding-top:20%;text-align: justify; display:none">
63 style="width:80%; margin:auto;padding-top:20%;text-align: justify; display:none">
64 <p style="font-size:26px;">There was an issue trying to fetch MathJax.js
64 <p style="font-size:26px;">There was an issue trying to fetch MathJax.js
65 from the internet.</p>
65 from the internet.</p>
66
66
67 <p style="padding:0.2em"> With a working internet connection, you can run
67 <p style="padding:0.2em"> With a working internet connection, you can run
68 the following at a Python or IPython prompt, which will install a local
68 the following at a Python or IPython prompt, which will install a local
69 copy of MathJax:</p>
69 copy of MathJax:</p>
70
70
71 <pre style="background-color:lightblue;border:thin silver solid;padding:0.4em">
71 <pre style="background-color:lightblue;border:thin silver solid;padding:0.4em">
72 from IPython.external import mathjax; mathjax.install_mathjax()
72 from IPython.external import mathjax; mathjax.install_mathjax()
73 </pre>
73 </pre>
74 This will try to install MathJax into the directory where you installed
74 This will try to install MathJax into the directory where you installed
75 IPython. If you installed IPython to a location that requires
75 IPython. If you installed IPython to a location that requires
76 administrative privileges to write, you will need to make this call as
76 administrative privileges to write, you will need to make this call as
77 an administrator. On OSX/Linux/Unix, this can be done at the
77 an administrator. On OSX/Linux/Unix, this can be done at the
78 command-line via:
78 command-line via:
79 <pre style="background-color:lightblue;border:thin silver solid;padding:0.4em">
79 <pre style="background-color:lightblue;border:thin silver solid;padding:0.4em">
80 sudo python -c "from IPython.external import mathjax; mathjax.install_mathjax()"
80 sudo python -c "from IPython.external import mathjax; mathjax.install_mathjax()"
81 </pre>
81 </pre>
82 </p>
82 </p>
83 </div>
83 </div>
84
84
85 <div id="main_app">
85 <div id="main_app">
86
86
87 <div id="left_panel">
87 <div id="left_panel">
88
88
89 <div id="notebook_section">
89 <div id="notebook_section">
90 <h3 class="section_header">Notebook</h3>
90 <h3 class="section_header">Notebook</h3>
91 <div class="section_content">
91 <div class="section_content">
92 <div class="section_row">
92 <div class="section_row">
93 <span id="new_open" class="section_row_buttons">
93 <span id="new_open" class="section_row_buttons">
94 <button id="new_notebook">New</button>
94 <button id="new_notebook">New</button>
95 <button id="open_notebook">Open</button>
95 <button id="open_notebook">Open</button>
96 </span>
96 </span>
97 <span class="section_row_header">Actions</span>
97 <span class="section_row_header">Actions</span>
98 </div>
98 </div>
99 <div class="section_row">
99 <div class="section_row">
100 <span>
100 <span>
101 <select id="download_format">
101 <select id="download_format">
102 <option value="json">ipynb</option>
102 <option value="json">ipynb</option>
103 <option value="py">py</option>
103 <option value="py">py</option>
104 </select>
104 </select>
105 </span>
105 </span>
106 <span class="section_row_buttons">
106 <span class="section_row_buttons">
107 <button id="download_notebook">Download</button>
107 <button id="download_notebook">Download</button>
108 </span>
108 </span>
109 </div>
109 </div>
110 <div class="section_row">
110 <div class="section_row">
111 <span class="section_row_buttons">
111 <span class="section_row_buttons">
112 <span id="print_widget">
112 <span id="print_widget">
113 <button id="print_notebook">Print</button>
113 <button id="print_notebook">Print</button>
114 </span>
114 </span>
115 </span>
115 </span>
116 </div>
116 </div>
117 </div>
117 </div>
118 </div>
118 </div>
119
119
120 <div id="cell_section">
120 <div id="cell_section">
121 <h3 class="section_header">Cell</h3>
121 <h3 class="section_header">Cell</h3>
122 <div class="section_content">
122 <div class="section_content">
123 <div class="section_row">
123 <div class="section_row">
124 <span class="section_row_buttons">
124 <span class="section_row_buttons">
125 <button id="delete_cell"><u>D</u>elete</button>
125 <button id="delete_cell"><u>D</u>elete</button>
126 </span>
126 </span>
127 <span class="section_row_header">Actions</span>
127 <span class="section_row_header">Actions</span>
128 </div>
128 </div>
129 <div class="section_row">
129 <div class="section_row">
130 <span id="cell_type" class="section_row_buttons">
130 <span id="cell_type" class="section_row_buttons">
131 <button id="to_code"><u>C</u>ode</button>
131 <button id="to_code"><u>C</u>ode</button>
132 <!-- <button id="to_html">HTML</button>-->
132 <!-- <button id="to_html">HTML</button>-->
133 <button id="to_markdown"><u>M</u>arkdown</button>
133 <button id="to_markdown"><u>M</u>arkdown</button>
134 </span>
134 </span>
135 <span class="button_label">Format</span>
135 <span class="button_label">Format</span>
136 </div>
136 </div>
137 <div class="section_row">
137 <div class="section_row">
138 <span id="cell_output" class="section_row_buttons">
138 <span id="cell_output" class="section_row_buttons">
139 <button id="toggle_output"><u>T</u>oggle</button>
139 <button id="toggle_output"><u>T</u>oggle</button>
140 <button id="clear_all_output">ClearAll</button>
140 <button id="clear_all_output">ClearAll</button>
141 </span>
141 </span>
142 <span class="button_label">Output</span>
142 <span class="button_label">Output</span>
143 </div>
143 </div>
144 <div class="section_row">
144 <div class="section_row">
145 <span id="insert" class="section_row_buttons">
145 <span id="insert" class="section_row_buttons">
146 <button id="insert_cell_above"><u>A</u>bove</button>
146 <button id="insert_cell_above"><u>A</u>bove</button>
147 <button id="insert_cell_below"><u>B</u>elow</button>
147 <button id="insert_cell_below"><u>B</u>elow</button>
148 </span>
148 </span>
149 <span class="button_label">Insert</span>
149 <span class="button_label">Insert</span>
150 </div>
150 </div>
151 <div class="section_row">
151 <div class="section_row">
152 <span id="move" class="section_row_buttons">
152 <span id="move" class="section_row_buttons">
153 <button id="move_cell_up">Up</button>
153 <button id="move_cell_up">Up</button>
154 <button id="move_cell_down">Down</button>
154 <button id="move_cell_down">Down</button>
155 </span>
155 </span>
156 <span class="button_label">Move</span>
156 <span class="button_label">Move</span>
157 </div>
157 </div>
158 <div class="section_row">
158 <div class="section_row">
159 <span id="run_cells" class="section_row_buttons">
159 <span id="run_cells" class="section_row_buttons">
160 <button id="run_selected_cell">Selected</button>
160 <button id="run_selected_cell">Selected</button>
161 <button id="run_all_cells">All</button>
161 <button id="run_all_cells">All</button>
162 </span>
162 </span>
163 <span class="button_label">Run</span>
163 <span class="button_label">Run</span>
164 </div>
164 </div>
165 <div class="section_row">
165 <div class="section_row">
166 <span id="autoindent_span">
166 <span id="autoindent_span">
167 <input type="checkbox" id="autoindent" checked="true"></input>
167 <input type="checkbox" id="autoindent" checked="true"></input>
168 </span>
168 </span>
169 <span class="checkbox_label">Autoindent:</span>
169 <span class="checkbox_label">Autoindent:</span>
170 </div>
170 </div>
171 </div>
171 </div>
172 </div>
172 </div>
173
173
174 <div id="kernel_section">
174 <div id="kernel_section">
175 <h3 class="section_header">Kernel</h3>
175 <h3 class="section_header">Kernel</h3>
176 <div class="section_content">
176 <div class="section_content">
177 <div class="section_row">
177 <div class="section_row">
178 <span id="int_restart" class="section_row_buttons">
178 <span id="int_restart" class="section_row_buttons">
179 <button id="int_kernel">Interrupt</button>
179 <button id="int_kernel"><u>I</u>nterrupt</button>
180 <button id="restart_kernel">Restart</button>
180 <button id="restart_kernel">Restart</button>
181 </span>
181 </span>
182 <span class="section_row_header">Actions</span>
182 <span class="section_row_header">Actions</span>
183 </div>
183 </div>
184 <div class="section_row">
184 <div class="section_row">
185 <span id="kernel_persist">
185 <span id="kernel_persist">
186 <input type="checkbox" id="kill_kernel"></input>
186 <input type="checkbox" id="kill_kernel"></input>
187 </span>
187 </span>
188 <span class="checkbox_label">Kill kernel upon exit:</span>
188 <span class="checkbox_label">Kill kernel upon exit:</span>
189 </div>
189 </div>
190 </div>
190 </div>
191 </div>
191 </div>
192
192
193 <div id="help_section">
193 <div id="help_section">
194 <h3 class="section_header">Help</h3>
194 <h3 class="section_header">Help</h3>
195 <div class="section_content">
195 <div class="section_content">
196 <div class="section_row">
196 <div class="section_row">
197 <span id="help_buttons0" class="section_row_buttons">
197 <span id="help_buttons0" class="section_row_buttons">
198 <a id="python_help" href="http://docs.python.org" target="_blank">Python</a>
198 <a id="python_help" href="http://docs.python.org" target="_blank">Python</a>
199 <a id="ipython_help" href="http://ipython.org/documentation.html" target="_blank">IPython</a>
199 <a id="ipython_help" href="http://ipython.org/documentation.html" target="_blank">IPython</a>
200 </span>
200 </span>
201 <span class="section_row_header">Links</span>
201 <span class="section_row_header">Links</span>
202 </div>
202 </div>
203 <div class="section_row">
203 <div class="section_row">
204 <span id="help_buttons1" class="section_row_buttons">
204 <span id="help_buttons1" class="section_row_buttons">
205 <a id="numpy_help" href="http://docs.scipy.org/doc/numpy/reference/" target="_blank">NumPy</a>
205 <a id="numpy_help" href="http://docs.scipy.org/doc/numpy/reference/" target="_blank">NumPy</a>
206 <a id="scipy_help" href="http://docs.scipy.org/doc/scipy/reference/" target="_blank">SciPy</a>
206 <a id="scipy_help" href="http://docs.scipy.org/doc/scipy/reference/" target="_blank">SciPy</a>
207 </span>
207 </span>
208 </div>
208 </div>
209 <div class="section_row">
209 <div class="section_row">
210 <span id="help_buttons2" class="section_row_buttons">
210 <span id="help_buttons2" class="section_row_buttons">
211 <a id="matplotlib_help" href="http://matplotlib.sourceforge.net/" target="_blank">MPL</a>
211 <a id="matplotlib_help" href="http://matplotlib.sourceforge.net/" target="_blank">MPL</a>
212 <a id="sympy_help" href="http://docs.sympy.org/dev/index.html" target="_blank">SymPy</a>
212 <a id="sympy_help" href="http://docs.sympy.org/dev/index.html" target="_blank">SymPy</a>
213 </span>
213 </span>
214 </div>
214 </div>
215 <div class="section_row">
215 <div class="section_row">
216 <span class="help_string">run selected cell</span>
216 <span class="help_string">run selected cell</span>
217 <span class="help_string_label">Shift-Enter :</span>
217 <span class="help_string_label">Shift-Enter :</span>
218 </div>
218 </div>
219 <div class="section_row">
219 <div class="section_row">
220 <span class="help_string">run in terminal mode</span>
220 <span class="help_string">run selected cell in-place</span>
221 <span class="help_string_label">Ctrl-Enter :</span>
221 <span class="help_string_label">Ctrl-Enter :</span>
222 </div>
222 </div>
223 <div class="section_row">
223 <div class="section_row">
224 <span class="help_string">show keyboard shortcuts</span>
224 <span class="help_string">show keyboard shortcuts</span>
225 <span class="help_string_label">Ctrl-m h :</span>
225 <span class="help_string_label">Ctrl-m h :</span>
226 </div>
226 </div>
227 </div>
227 </div>
228 </div>
228 </div>
229
229
230 </div>
230 </div>
231 <div id="left_panel_splitter"></div>
231 <div id="left_panel_splitter"></div>
232 <div id="notebook_panel">
232 <div id="notebook_panel">
233 <div id="notebook"></div>
233 <div id="notebook"></div>
234 <div id="pager_splitter"></div>
234 <div id="pager_splitter"></div>
235 <div id="pager"></div>
235 <div id="pager"></div>
236 </div>
236 </div>
237
237
238 </div>
238 </div>
239
239
240 <script src="static/jquery/js/jquery-1.6.2.min.js" type="text/javascript" charset="utf-8"></script>
240 <script src="static/jquery/js/jquery-1.6.2.min.js" type="text/javascript" charset="utf-8"></script>
241 <script src="static/jquery/js/jquery-ui-1.8.14.custom.min.js" type="text/javascript" charset="utf-8"></script>
241 <script src="static/jquery/js/jquery-ui-1.8.14.custom.min.js" type="text/javascript" charset="utf-8"></script>
242 <script src="static/jquery/js/jquery.autogrow.js" type="text/javascript" charset="utf-8"></script>
242 <script src="static/jquery/js/jquery.autogrow.js" type="text/javascript" charset="utf-8"></script>
243
243
244 <script src="static/codemirror/lib/codemirror.js" charset="utf-8"></script>
244 <script src="static/codemirror/lib/codemirror.js" charset="utf-8"></script>
245 <script src="static/codemirror/mode/python/python.js" charset="utf-8"></script>
245 <script src="static/codemirror/mode/python/python.js" charset="utf-8"></script>
246 <script src="static/codemirror/mode/htmlmixed/htmlmixed.js" charset="utf-8"></script>
246 <script src="static/codemirror/mode/htmlmixed/htmlmixed.js" charset="utf-8"></script>
247 <script src="static/codemirror/mode/xml/xml.js" charset="utf-8"></script>
247 <script src="static/codemirror/mode/xml/xml.js" charset="utf-8"></script>
248 <script src="static/codemirror/mode/javascript/javascript.js" charset="utf-8"></script>
248 <script src="static/codemirror/mode/javascript/javascript.js" charset="utf-8"></script>
249 <script src="static/codemirror/mode/css/css.js" charset="utf-8"></script>
249 <script src="static/codemirror/mode/css/css.js" charset="utf-8"></script>
250 <script src="static/codemirror/mode/rst/rst.js" charset="utf-8"></script>
250 <script src="static/codemirror/mode/rst/rst.js" charset="utf-8"></script>
251 <script src="static/codemirror/mode/markdown/markdown.js" charset="utf-8"></script>
251 <script src="static/codemirror/mode/markdown/markdown.js" charset="utf-8"></script>
252
252
253 <script src="static/pagedown/Markdown.Converter.js" charset="utf-8"></script>
253 <script src="static/pagedown/Markdown.Converter.js" charset="utf-8"></script>
254
254
255 <script src="static/prettify/prettify.js" charset="utf-8"></script>
255 <script src="static/prettify/prettify.js" charset="utf-8"></script>
256
256
257 <script src="static/js/namespace.js" type="text/javascript" charset="utf-8"></script>
257 <script src="static/js/namespace.js" type="text/javascript" charset="utf-8"></script>
258 <script src="static/js/utils.js" type="text/javascript" charset="utf-8"></script>
258 <script src="static/js/utils.js" type="text/javascript" charset="utf-8"></script>
259 <script src="static/js/cell.js" type="text/javascript" charset="utf-8"></script>
259 <script src="static/js/cell.js" type="text/javascript" charset="utf-8"></script>
260 <script src="static/js/codecell.js" type="text/javascript" charset="utf-8"></script>
260 <script src="static/js/codecell.js" type="text/javascript" charset="utf-8"></script>
261 <script src="static/js/textcell.js" type="text/javascript" charset="utf-8"></script>
261 <script src="static/js/textcell.js" type="text/javascript" charset="utf-8"></script>
262 <script src="static/js/kernel.js" type="text/javascript" charset="utf-8"></script>
262 <script src="static/js/kernel.js" type="text/javascript" charset="utf-8"></script>
263 <script src="static/js/kernelstatus.js" type="text/javascript" charset="utf-8"></script>
263 <script src="static/js/kernelstatus.js" type="text/javascript" charset="utf-8"></script>
264 <script src="static/js/layout.js" type="text/javascript" charset="utf-8"></script>
264 <script src="static/js/layout.js" type="text/javascript" charset="utf-8"></script>
265 <script src="static/js/savewidget.js" type="text/javascript" charset="utf-8"></script>
265 <script src="static/js/savewidget.js" type="text/javascript" charset="utf-8"></script>
266 <script src="static/js/pager.js" type="text/javascript" charset="utf-8"></script>
266 <script src="static/js/pager.js" type="text/javascript" charset="utf-8"></script>
267 <script src="static/js/panelsection.js" type="text/javascript" charset="utf-8"></script>
267 <script src="static/js/panelsection.js" type="text/javascript" charset="utf-8"></script>
268 <script src="static/js/printwidget.js" type="text/javascript" charset="utf-8"></script>
268 <script src="static/js/printwidget.js" type="text/javascript" charset="utf-8"></script>
269 <script src="static/js/leftpanel.js" type="text/javascript" charset="utf-8"></script>
269 <script src="static/js/leftpanel.js" type="text/javascript" charset="utf-8"></script>
270 <script src="static/js/notebook.js" type="text/javascript" charset="utf-8"></script>
270 <script src="static/js/notebook.js" type="text/javascript" charset="utf-8"></script>
271 <script src="static/js/notebook_main.js" type="text/javascript" charset="utf-8"></script>
271 <script src="static/js/notebook_main.js" type="text/javascript" charset="utf-8"></script>
272
272
273
273
274 </body>
274 </body>
275
275
276 </html>
276 </html>
277
277
278
278
General Comments 0
You need to be logged in to leave comments. Login now