##// END OF EJS Templates
Status monitoring added to notebook....
Brian Granger -
Show More
@@ -1,202 +1,221 b''
1 1 /**
2 2 * HTML5 ✰ Boilerplate
3 3 *
4 4 * style.css contains a reset, font normalization and some base styles.
5 5 *
6 6 * Credit is left where credit is due.
7 7 * Much inspiration was taken from these projects:
8 8 * - yui.yahooapis.com/2.8.1/build/base/base.css
9 9 * - camendesign.com/design/
10 10 * - praegnanz.de/weblog/htmlcssjs-kickstart
11 11 */
12 12
13 13
14 14 /**
15 15 * html5doctor.com Reset Stylesheet (Eric Meyer's Reset Reloaded + HTML5 baseline)
16 16 * v1.6.1 2010-09-17 | Authors: Eric Meyer & Richard Clark
17 17 * html5doctor.com/html-5-reset-stylesheet/
18 18 */
19 19
20 20 html, body, div, span, object, iframe,
21 21 h1, h2, h3, h4, h5, h6, p, blockquote, pre,
22 22 abbr, address, cite, code, del, dfn, em, img, ins, kbd, q, samp,
23 23 small, strong, sub, sup, var, b, i, dl, dt, dd, ol, ul, li,
24 24 fieldset, form, label, legend,
25 25 table, caption, tbody, tfoot, thead, tr, th, td,
26 26 article, aside, canvas, details, figcaption, figure,
27 27 footer, header, hgroup, menu, nav, section, summary,
28 28 time, mark, audio, video {
29 29 margin: 0;
30 30 padding: 0;
31 31 border: 0;
32 32 font-size: 100%;
33 33 font: inherit;
34 34 vertical-align: baseline;
35 35 }
36 36
37 37 article, aside, details, figcaption, figure,
38 38 footer, header, hgroup, menu, nav, section {
39 39 display: block;
40 40 }
41 41
42 42 blockquote, q { quotes: none; }
43 43
44 44 blockquote:before, blockquote:after,
45 45 q:before, q:after { content: ""; content: none; }
46 46
47 47 ins { background-color: #ff9; color: #000; text-decoration: none; }
48 48
49 49 mark { background-color: #ff9; color: #000; font-style: italic; font-weight: bold; }
50 50
51 51 del { text-decoration: line-through; }
52 52
53 53 abbr[title], dfn[title] { border-bottom: 1px dotted; cursor: help; }
54 54
55 55 table { border-collapse: collapse; border-spacing: 0; }
56 56
57 57 hr { display: block; height: 1px; border: 0; border-top: 1px solid #ccc; margin: 1em 0; padding: 0; }
58 58
59 59 input, select { vertical-align: middle; }
60 60
61 61 /* Normalize monospace sizing:
62 62 en.wikipedia.org/wiki/MediaWiki_talk:Common.css/Archive_11#Teletype_style_fix_for_Chrome */
63 63 pre, code, kbd, samp { font-family: monospace, sans-serif; }
64 64
65 65
66 66
67 67 body {
68 68 background-color: white;
69 69 font-size: 10pt;
70 70 }
71 71
72 72 span#ipython_notebook h1 {
73 73 font-family: "Helvetica Neue", Arial, Helvetica, Geneva, sans-serif;
74 74 font-size: 32pt;
75 75 padding: 10px;
76 76 margin: 10px;
77 77 }
78 78
79 79 div#toolbar {
80 80 width: 100%;
81 81 height: auto;
82 82 border-bottom-width: 2px;
83 83 border-bottom-style: solid;
84 84 border-bottom-color: black;
85 85 padding: 5px;
86 86 }
87 87
88 span#kernel_status {
89 position: absolute;
90 top: 12%;
91 right: 10px;
92 font-weight: bold;
93 }
94
95 .status_idle {
96 color: gray;
97 }
98
99 .status_busy {
100 color: red;
101 }
102
103 .status_restarting {
104 color: black;
105 }
106
88 107 div.notebook {
89 108 width: 790px;
90 109 height: 650px; /*We might have to detect window height for this*/
91 110 overflow: auto;
92 111 margin-left: auto;
93 112 margin-right: auto;
94 113 padding-top: 5px;
95 114 padding-bottom: 5px;
96 115 background-color: white;
97 116 }
98 117
99 118 div.cell {
100 119 width: 740px;
101 120 margin: 5px auto 5px 5px;
102 121 padding: 5px;
103 122 position: relative;
104 123 display: table;
105 124 }
106 125
107 126 div.code_cell {
108 127 background-color: white;
109 128 }
110 129
111 130 div.prompt {
112 131 vertical-align: top;
113 132 display: table-cell;
114 133 width: 80px;
115 134 padding: 0px;
116 135 margin: 0px;
117 136 font-family: Menlo, "Courier New", Courier, mono;
118 137 font-weight: normal;
119 138 font-style: normal;
120 139 }
121 140
122 141 div.input {
123 142 display: table-row;
124 143 padding: 0px;
125 144 margin: 0px;
126 145 }
127 146
128 147 div.input_prompt {
129 148 color: blue;
130 149 }
131 150
132 151 textarea.input_area {
133 152 text-align: left;
134 153 font-family: Menlo, "Courier New", Courier, mono;
135 154 font-size: inherit;
136 155 border-style: none;
137 156 display: table-cell;
138 157 padding: 0px;
139 158 margin: 0px;
140 159 overflow: auto;
141 160 font-weight: normal;
142 161 font-style: normal;
143 162 width: 650px;
144 163 outline: none;
145 164 resize: none;
146 165 }
147 166
148 167 div.output {
149 168 display: table-row;
150 169 padding: 0px;
151 170 margin: 0px;
152 171 }
153 172
154 173 div.output_prompt {
155 174 color: red;
156 175 }
157 176
158 177 div.output_area {
159 178 text-align: left;
160 179 font-family: Menlo, "Courier New", Courier, mono;
161 180 padding: 0px;
162 181 margin: 0px;
163 182 display: table-cell;
164 183 width: 650px;
165 184 }
166 185
167 186 div.text_cell {
168 187 background-color: white;
169 188 }
170 189
171 190 textarea.text_cell_input {
172 191 font-family: "Helvetica Neue", Arial, Helvetica, Geneva, sans-serif;
173 192 font-size: inherit;
174 193 outline: none;
175 194 resize: none;
176 195 width: inherit;
177 196 border-style: none;
178 197 padding: 0;
179 198 margin: 0;
180 199 color: black;
181 200 }
182 201
183 202 div.text_cell_render {
184 203 font-family: "Helvetica Neue", Arial, Helvetica, Geneva, sans-serif;
185 204 font-size: inherit;
186 205 outline: none;
187 206 resize: none;
188 207 width: inherit;
189 208 border-style: none;
190 209 padding: 0;
191 210 margin: 0;
192 211 color: black;
193 212 }
194 213
195 214 div.text_cell_render em {
196 215 font-style: italic;
197 216 }
198 217
199 218 div.text_cell_render strong {
200 219 font-weight: bold;
201 220 }
202 221
@@ -1,833 +1,864 b''
1 1 var IPYTHON = {};
2 2
3 3
4 4
5 5 // $.get("/notebooks/number2.nb",function (data, status, xhr) {console.log(data);});
6 6 //
7 7 // settings = {
8 8 // processData : false,
9 9 // cache : false,
10 10 // type : "DELETE",
11 11 // success : function (data, status, xhr) {console.log(data);}
12 12 // }
13 13 // $.ajax("/notebooks/number2.nb",settings)
14 14 //
15 15 // settings = {
16 16 // processData : false,
17 17 // cache : false,
18 18 // type : "PUT",
19 19 // success : function (data, status, xhr) {console.log(data);}
20 20 // }
21 21 // $.ajax("/notebooks/number2.nb",settings)
22 22
23 23
24 24 //============================================================================
25 25 // Utilities
26 26 //============================================================================
27 27
28 28
29 29 var uuid = function () {
30 30 // http://www.ietf.org/rfc/rfc4122.txt
31 31 var s = [];
32 32 var hexDigits = "0123456789ABCDEF";
33 33 for (var i = 0; i < 32; i++) {
34 34 s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
35 35 }
36 36 s[12] = "4"; // bits 12-15 of the time_hi_and_version field to 0010
37 37 s[16] = hexDigits.substr((s[16] & 0x3) | 0x8, 1); // bits 6-7 of the clock_seq_hi_and_reserved to 01
38 38
39 39 var uuid = s.join("");
40 40 return uuid;
41 41 };
42 42
43 43
44 44 //Fix raw text to parse correctly in crazy XML
45 45 function xmlencode(string) {
46 46 return string.replace(/\&/g,'&'+'amp;')
47 47 .replace(/</g,'&'+'lt;')
48 48 .replace(/>/g,'&'+'gt;')
49 49 .replace(/\'/g,'&'+'apos;')
50 50 .replace(/\"/g,'&'+'quot;')
51 51 .replace(/`/g,'&'+'#96;')
52 52 }
53 53
54 54 //Map from terminal commands to CSS classes
55 55 attrib = {
56 56 "30":"cblack", "31":"cred",
57 57 "32":"cgreen", "33":"cyellow",
58 58 "34":"cblue", "36":"ccyan",
59 59 "37":"cwhite", "01":"cbold"}
60 60
61 61 //Fixes escaped console commands, IE colors. Turns them into HTML
62 62 function fixConsole(txt) {
63 63 txt = xmlencode(txt)
64 64 var re = /\033\[([\d;]*?)m/
65 65 var opened = false
66 66 var cmds = []
67 67 var opener = ""
68 68 var closer = ""
69 69
70 70 while (re.test(txt)) {
71 71 var cmds = txt.match(re)[1].split(";")
72 72 closer = opened?"</span>":""
73 73 opened = cmds.length > 1 || cmds[0] != 0
74 74 var rep = []
75 75 for (var i in cmds)
76 76 if (typeof(attrib[cmds[i]]) != "undefined")
77 77 rep.push(attrib[cmds[i]])
78 78 opener = rep.length > 0?"<span class=\""+rep.join(" ")+"\">":""
79 79 txt = txt.replace(re, closer + opener)
80 80 }
81 81 if (opened) txt += "</span>"
82 82 return txt.trim()
83 83 }
84 84
85 85 //============================================================================
86 86 // Notebook
87 87 //============================================================================
88 88
89 89
90 90 var Notebook = function (selector) {
91 91 this.element = $(selector);
92 92 this.element.scroll();
93 93 this.element.data("notebook", this);
94 94 this.next_prompt_number = 1;
95 95 this.kernel = null;
96 96 this.msg_cell_map = {};
97 97 this.bind_events();
98 98 this.start_kernel();
99 99 };
100 100
101 101
102 102 Notebook.prototype.bind_events = function () {
103 103 var that = this;
104 104 $(document).keydown(function (event) {
105 console.log(event);
105 // console.log(event);
106 106 if (event.which == 38 && event.shiftKey) {
107 107 event.preventDefault();
108 108 that.select_prev();
109 109 } else if (event.which == 40 && event.shiftKey) {
110 110 event.preventDefault();
111 111 that.select_next();
112 112 } else if (event.which == 13 && event.shiftKey) {
113 113 // The focus is not quite working here.
114 114 var cell = that.selected_cell();
115 115 var cell_index = that.find_cell_index(cell);
116 116 if (cell instanceof CodeCell) {
117 117 event.preventDefault();
118 118 cell.clear_output();
119 119 var msg_id = that.kernel.execute(cell.get_code());
120 120 that.msg_cell_map[msg_id] = cell.cell_id;
121 121 if (cell_index === (that.ncells()-1)) {
122 122 that.insert_code_cell_after();
123 123 } else {
124 124 that.select(cell_index+1);
125 125 };
126 126 }
127 127 } else if (event.which == 9) {
128 128 event.preventDefault();
129 129 var cell = that.selected_cell();
130 130 if (cell instanceof CodeCell) {
131 131 var ta = cell.element.find("textarea.input_area");
132 132 ta.val(ta.val() + " ");
133 133 };
134 134 };
135 135 });
136 136 };
137 137
138 138
139 139 // Cell indexing, retrieval, etc.
140 140
141 141
142 142 Notebook.prototype.cell_elements = function () {
143 143 return this.element.children("div.cell");
144 144 }
145 145
146 146
147 147 Notebook.prototype.ncells = function (cell) {
148 148 return this.cell_elements().length;
149 149 }
150 150
151 151
152 152 // TODO: we are often calling cells as cells()[i], which we should optimize
153 153 // to cells(i) or a new method.
154 154 Notebook.prototype.cells = function () {
155 155 return this.cell_elements().toArray().map(function (e) {
156 156 return $(e).data("cell");
157 157 });
158 158 }
159 159
160 160
161 161 Notebook.prototype.find_cell_index = function (cell) {
162 162 var result = null;
163 163 this.cell_elements().filter(function (index) {
164 164 if ($(this).data("cell") === cell) {
165 165 result = index;
166 166 };
167 167 });
168 168 return result;
169 169 };
170 170
171 171
172 172 Notebook.prototype.index_or_selected = function (index) {
173 173 return index || this.selected_index() || 0;
174 174 }
175 175
176 176
177 177 Notebook.prototype.select = function (index) {
178 178 if (index !== undefined && index >= 0 && index < this.ncells()) {
179 179 if (this.selected_index() !== null) {
180 180 this.selected_cell().unselect();
181 181 };
182 182 this.cells()[index].select();
183 183 };
184 184 return this;
185 185 };
186 186
187 187
188 188 Notebook.prototype.select_next = function () {
189 189 var index = this.selected_index();
190 190 if (index !== null && index >= 0 && (index+1) < this.ncells()) {
191 191 this.select(index+1);
192 192 };
193 193 return this;
194 194 };
195 195
196 196
197 197 Notebook.prototype.select_prev = function () {
198 198 var index = this.selected_index();
199 199 if (index !== null && index >= 0 && (index-1) < this.ncells()) {
200 200 this.select(index-1);
201 201 };
202 202 return this;
203 203 };
204 204
205 205
206 206 Notebook.prototype.selected_index = function () {
207 207 var result = null;
208 208 this.cell_elements().filter(function (index) {
209 209 if ($(this).data("cell").selected === true) {
210 210 result = index;
211 211 };
212 212 });
213 213 return result;
214 214 };
215 215
216 216
217 217 Notebook.prototype.cell_for_msg = function (msg_id) {
218 218 var cell_id = this.msg_cell_map[msg_id];
219 219 var result = null;
220 220 this.cell_elements().filter(function (index) {
221 221 cell = $(this).data("cell");
222 222 if (cell.cell_id === cell_id) {
223 223 result = cell;
224 224 };
225 225 });
226 226 return result;
227 227 };
228 228
229 229
230 230 Notebook.prototype.selected_cell = function () {
231 231 return this.cell_elements().eq(this.selected_index()).data("cell");
232 232 }
233 233
234 234
235 235 // Cell insertion, deletion and moving.
236 236
237 237
238 238 Notebook.prototype.delete_cell = function (index) {
239 239 var i = index || this.selected_index();
240 240 if (i !== null && i >= 0 && i < this.ncells()) {
241 241 this.cell_elements().eq(i).remove();
242 242 if (i === (this.ncells())) {
243 243 this.select(i-1);
244 244 } else {
245 245 this.select(i);
246 246 };
247 247 };
248 248 return this;
249 249 };
250 250
251 251
252 252 Notebook.prototype.append_cell = function (cell) {
253 253 this.element.append(cell.element);
254 254 return this;
255 255 };
256 256
257 257
258 258 Notebook.prototype.insert_cell_after = function (cell, index) {
259 259 var ncells = this.ncells();
260 260 if (ncells === 0) {
261 261 this.append_cell(cell);
262 262 return this;
263 263 };
264 264 if (index >= 0 && index < ncells) {
265 265 this.cell_elements().eq(index).after(cell.element);
266 266 };
267 267 return this
268 268 };
269 269
270 270
271 271 Notebook.prototype.insert_cell_before = function (cell, index) {
272 272 var ncells = this.ncells();
273 273 if (ncells === 0) {
274 274 this.append_cell(cell);
275 275 return this;
276 276 };
277 277 if (index >= 0 && index < ncells) {
278 278 this.cell_elements().eq(index).before(cell.element);
279 279 };
280 280 return this;
281 281 };
282 282
283 283
284 284 Notebook.prototype.move_cell_up = function (index) {
285 285 var i = index || this.selected_index();
286 286 if (i !== null && i < this.ncells() && i > 0) {
287 287 var pivot = this.cell_elements().eq(i-1);
288 288 var tomove = this.cell_elements().eq(i);
289 289 if (pivot !== null && tomove !== null) {
290 290 tomove.detach();
291 291 pivot.before(tomove);
292 292 this.select(i-1);
293 293 };
294 294 };
295 295 return this;
296 296 }
297 297
298 298
299 299 Notebook.prototype.move_cell_down = function (index) {
300 300 var i = index || this.selected_index();
301 301 if (i !== null && i < (this.ncells()-1) && i >= 0) {
302 302 var pivot = this.cell_elements().eq(i+1)
303 303 var tomove = this.cell_elements().eq(i)
304 304 if (pivot !== null && tomove !== null) {
305 305 tomove.detach();
306 306 pivot.after(tomove);
307 307 this.select(i+1);
308 308 };
309 309 };
310 310 return this;
311 311 }
312 312
313 313
314 314 Notebook.prototype.sort_cells = function () {
315 315 var ncells = this.ncells();
316 316 var sindex = this.selected_index();
317 317 var swapped;
318 318 do {
319 319 swapped = false
320 320 for (var i=1; i<ncells; i++) {
321 321 current = this.cell_elements().eq(i).data("cell");
322 322 previous = this.cell_elements().eq(i-1).data("cell");
323 323 if (previous.input_prompt_number > current.input_prompt_number) {
324 324 this.move_cell_up(i);
325 325 swapped = true;
326 326 };
327 327 };
328 328 } while (swapped);
329 329 this.select(sindex);
330 330 return this;
331 331 };
332 332
333 333
334 334 Notebook.prototype.insert_code_cell_before = function (index) {
335 335 // TODO: Bounds check for i
336 336 var i = this.index_or_selected(index);
337 337 var cell = new CodeCell(this);
338 338 cell.set_input_prompt(this.next_prompt_number);
339 339 this.next_prompt_number = this.next_prompt_number + 1;
340 340 this.insert_cell_before(cell, i);
341 341 this.select(this.find_cell_index(cell));
342 342 return this;
343 343 }
344 344
345 345
346 346 Notebook.prototype.insert_code_cell_after = function (index) {
347 347 // TODO: Bounds check for i
348 348 var i = this.index_or_selected(index);
349 349 var cell = new CodeCell(this);
350 350 cell.set_input_prompt(this.next_prompt_number);
351 351 this.next_prompt_number = this.next_prompt_number + 1;
352 352 this.insert_cell_after(cell, i);
353 353 this.select(this.find_cell_index(cell));
354 354 return this;
355 355 }
356 356
357 357
358 358 Notebook.prototype.insert_text_cell_before = function (index) {
359 359 // TODO: Bounds check for i
360 360 var i = this.index_or_selected(index);
361 361 var cell = new TextCell(this);
362 362 cell.config_mathjax();
363 363 this.insert_cell_before(cell, i);
364 364 this.select(this.find_cell_index(cell));
365 365 return this;
366 366 }
367 367
368 368
369 369 Notebook.prototype.insert_text_cell_after = function (index) {
370 370 // TODO: Bounds check for i
371 371 var i = this.index_or_selected(index);
372 372 var cell = new TextCell(this);
373 373 cell.config_mathjax();
374 374 this.insert_cell_after(cell, i);
375 375 this.select(this.find_cell_index(cell));
376 376 return this;
377 377 }
378 378
379 379
380 380 Notebook.prototype.text_to_code = function (index) {
381 381 // TODO: Bounds check for i
382 382 var i = this.index_or_selected(index);
383 383 var source_element = this.cell_elements().eq(i);
384 384 var source_cell = source_element.data("cell");
385 385 if (source_cell instanceof TextCell) {
386 386 this.insert_code_cell_after(i);
387 387 var target_cell = this.cells()[i+1];
388 388 var text = source_element.find("textarea.text_cell_input").val();
389 389 target_cell.element.find("textarea.input_area").val(text);
390 390 source_element.remove();
391 391 };
392 392 };
393 393
394 394
395 395 Notebook.prototype.code_to_text = function (index) {
396 396 // TODO: Bounds check for i
397 397 var i = this.index_or_selected(index);
398 398 var source_element = this.cell_elements().eq(i);
399 399 var source_cell = source_element.data("cell");
400 400 if (source_cell instanceof CodeCell) {
401 401 this.insert_text_cell_after(i);
402 402 var target_cell = this.cells()[i+1];
403 403 var text = source_element.find("textarea.input_area").val();
404 404 if (text === "") {text = target_cell.placeholder;};
405 405 target_cell.element.find("textarea.text_cell_input").val(text);
406 406 target_cell.element.find("textarea.text_cell_input").html(text);
407 407 target_cell.element.find("div.text_cell_render").html(text);
408 408
409 409 source_element.remove();
410 410 };
411 411 };
412 412
413 413
414 414 // Cell collapsing
415 415
416 416 Notebook.prototype.collapse = function (index) {
417 417 var i = this.index_or_selected(index);
418 418 this.cells()[i].collapse();
419 419 };
420 420
421 421
422 422 Notebook.prototype.expand = function (index) {
423 423 var i = this.index_or_selected(index);
424 424 this.cells()[i].expand();
425 425 };
426 426
427 427
428 428 // Kernel related things
429 429
430 430 Notebook.prototype.start_kernel = function () {
431 431 this.kernel = new Kernel();
432 432 this.kernel.start_kernel(this._kernel_started, this);
433 433 };
434 434
435 435
436 436 Notebook.prototype._kernel_started = function () {
437 437 console.log("Kernel started: ", this.kernel.kernel_id);
438 438 var that = this;
439 439
440 440 this.kernel.shell_channel.onmessage = function (e) {
441 441 reply = $.parseJSON(e.data);
442 442 console.log(reply);
443 443 var msg_type = reply.msg_type;
444 444 var cell = that.cell_for_msg(reply.parent_header.msg_id);
445 445 if (msg_type === "execute_reply") {
446 446 cell.set_prompt(reply.content.execution_count);
447 447 };
448 448 };
449 449
450 450 this.kernel.iopub_channel.onmessage = function (e) {
451 451 reply = $.parseJSON(e.data);
452 452 console.log(reply);
453 453 var msg_type = reply.msg_type;
454 454 var cell = that.cell_for_msg(reply.parent_header.msg_id);
455 455 if (msg_type === "stream") {
456 456 cell.expand();
457 457 cell.append_stream(reply.content.data + "\n");
458 458 } else if (msg_type === "pyout" || msg_type === "display_data") {
459 459 cell.expand();
460 460 cell.append_display_data(reply.content.data);
461 } else if (msg_type === "status") {
462 if (reply.content.execution_state === "busy") {
463 that.kernel.status_busy();
464 } else if (reply.content.execution_state === "idle") {
465 that.kernel.status_idle();
466 };
461 467 };
462 468 };
463 469 };
464 470
465 471
466 472 Notebook.prototype._handle_execute_reply = function (reply, cell) {
467 473 cell.set_prompt(reply.content.execution_count);
468 474 };
469 475
470 476
471 477 //============================================================================
472 478 // Cell
473 479 //============================================================================
474 480
475 481
476 482 var Cell = function (notebook) {
477 483 this.notebook = notebook;
478 484 this.selected = false;
479 485 this.element;
480 486 this.create_element();
481 487 if (this.element !== undefined) {
482 488 this.element.data("cell", this);
483 489 this.bind_events();
484 490 }
485 491 this.cell_id = uuid();
486 492 };
487 493
488 494
489 495 Cell.prototype.select = function () {
490 496 this.element.addClass('ui-widget-content ui-corner-all');
491 497 this.selected = true;
492 498 // TODO: we need t test across browsers to see if both of these are needed.
493 499 // In the meantime, there should not be any harm in having them both.
494 500 this.element.find('textarea').trigger('focusin');
495 501 this.element.find('textarea').trigger('focus');
496 502 };
497 503
498 504
499 505 Cell.prototype.unselect = function () {
500 506 this.element.removeClass('ui-widget-content ui-corner-all');
501 507 this.selected = false;
502 508 };
503 509
504 510
505 511 Cell.prototype.bind_events = function () {
506 512 var that = this;
507 513 var nb = that.notebook
508 514 that.element.click(function (event) {
509 515 if (that.selected === false) {
510 516 nb.select(nb.find_cell_index(that));
511 517 };
512 518 });
513 519 that.element.focusin(function (event) {
514 520 if (that.selected === false) {
515 521 nb.select(nb.find_cell_index(that));
516 522 };
517 523 });
518 524 };
519 525
520 526
521 527 // Subclasses must implement create_element.
522 528 Cell.prototype.create_element = function () {};
523 529
524 530
525 531 //============================================================================
526 532 // CodeCell
527 533 //============================================================================
528 534
529 535
530 536 var CodeCell = function (notebook) {
531 537 Cell.apply(this, arguments);
532 538 this.input_prompt_number = ' ';
533 539 this.output_prompt_number = ' ';
534 540 };
535 541
536 542
537 543 CodeCell.prototype = new Cell();
538 544
539 545
540 546 CodeCell.prototype.create_element = function () {
541 547 var cell = $('<div></div>').addClass('cell code_cell')
542 548 var input = $('<div></div>').addClass('input').append(
543 549 $('<div/>').addClass('prompt input_prompt')
544 550 ).append(
545 551 $('<textarea/>').addClass('input_area').
546 552 attr('rows',1).
547 553 attr('cols',80).
548 554 attr('wrap','hard').
549 555 autoGrow()
550 556 );
551 557 var output = $('<div></div>').addClass('output').append(
552 558 $('<div/>').addClass('prompt output_prompt')
553 559 ).append(
554 560 $('<div/>').addClass('output_area')
555 561 );
556 562 cell.append(input).append(output);
557 563 this.element = cell;
558 564 this.collapse()
559 565 };
560 566
561 567
562 568 CodeCell.prototype.append_stream = function (data) {
563 569 var data_list = data.split("\n");
564 570 console.log(data_list);
565 571 if (data_list.length > 0) {
566 572 for (var i=0; i<data_list.length; i++) {
567 573 console.log(i, data_list[i]);
568 574 var toinsert = fixConsole(data_list[i]);
569 575 this.element.find("div.output_area").append($("<p>").append(toinsert));
570 576 };
571 577 }
572 578 };
573 579
574 580
575 581 CodeCell.prototype.append_display_data = function (data) {
576 582 if (data["image/svg+xml"] !== undefined) {
577 583 this.append_svg(data["image/svg+xml"]);
578 584 } else if (data["text/plain"] !== undefined) {
579 585 console.log(data["text/plain"]);
580 586 this.append_stream(data["text/plain"]);
581 587 };
582 588 };
583 589
584 590 CodeCell.prototype.append_svg = function (svg) {
585 591 this.element.find("div.output_area").append(svg);
586 592 };
587 593
588 594
589 595 CodeCell.prototype.clear_output = function () {
590 596 this.element.find("div.output_area").html("");
591 597 };
592 598
593 599
594 600 CodeCell.prototype.collapse = function () {
595 601 this.element.find('div.output').hide();
596 602 };
597 603
598 604
599 605 CodeCell.prototype.expand = function () {
600 606 this.element.find('div.output').show();
601 607 };
602 608
603 609
604 610 CodeCell.prototype.set_prompt = function (number) {
605 611 this.set_input_prompt(number);
606 612 this.set_output_prompt(number);
607 613 };
608 614
609 615 CodeCell.prototype.set_input_prompt = function (number) {
610 616 var n = number || ' ';
611 617 this.input_prompt_number = n
612 618 this.element.find('div.input_prompt').html('In&nbsp;[' + n + ']:');
613 619 };
614 620
615 621
616 622 CodeCell.prototype.set_output_prompt = function (number) {
617 623 var n = number || ' ';
618 624 this.output_prompt_number = n
619 625 this.element.find('div.output_prompt').html('Out[' + n + ']:');
620 626 };
621 627
622 628
623 629 CodeCell.prototype.get_code = function () {
624 630 return this.element.find("textarea.input_area").val();
625 631 };
626 632
627 633 //============================================================================
628 634 // TextCell
629 635 //============================================================================
630 636
631 637
632 638 var TextCell = function (notebook) {
633 639 Cell.apply(this, arguments);
634 640 this.placeholder = "Type <strong>HTML</strong> and LaTeX: $\\alpha^2$"
635 641 };
636 642
637 643
638 644 TextCell.prototype = new Cell();
639 645
640 646
641 647 TextCell.prototype.create_element = function () {
642 648 var cell = $("<div>").addClass('cell text_cell').
643 649 append(
644 650 $("<textarea>" + this.placeholder + "</textarea>").
645 651 addClass('text_cell_input').
646 652 attr('rows',1).
647 653 attr('cols',80).
648 654 autoGrow()
649 655 ).append(
650 656 $('<div></div>').addClass('text_cell_render')
651 657 )
652 658 this.element = cell;
653 659 };
654 660
655 661
656 662 TextCell.prototype.select = function () {
657 663 this.edit();
658 664 Cell.prototype.select.apply(this);
659 665 };
660 666
661 667
662 668 TextCell.prototype.edit = function () {
663 669 var text_cell = this.element;
664 670 var input = text_cell.find("textarea.text_cell_input");
665 671 var output = text_cell.find("div.text_cell_render");
666 672 output.hide();
667 673 input.show().trigger('focus');
668 674 };
669 675
670 676
671 677 TextCell.prototype.render = function () {
672 678 var text_cell = this.element;
673 679 var input = text_cell.find("textarea.text_cell_input");
674 680 var output = text_cell.find("div.text_cell_render");
675 681 var text = input.val();
676 682 if (text === "") {
677 683 text = this.placeholder;
678 684 input.val(text);
679 685 };
680 686 output.html(text)
681 687 input.html(text);
682 688 MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
683 689 input.hide();
684 690 output.show();
685 691 };
686 692
687 693
688 694 TextCell.prototype.config_mathjax = function () {
689 695 var text_cell = this.element;
690 696 var that = this;
691 697 text_cell.click(function () {
692 698 that.edit();
693 699 }).focusout(function () {
694 700 that.render();
695 701 });
696 702
697 703 text_cell.trigger("focusout");
698 704 };
699 705
700 706
701 707 //============================================================================
702 708 // On document ready
703 709 //============================================================================
704 710
705 711
706 712 var Kernel = function () {
707 713 this.kernel_id = null;
708 714 this.base_url = "/kernels";
709 715 this.kernel_url = null;
710 716 };
711 717
712 718
713 719 Kernel.prototype.get_msg = function (msg_type, content) {
714 720 var msg = {
715 721 header : {
716 722 msg_id : uuid(),
717 723 username : "bgranger",
718 724 session: this.session_id
719 725 },
720 726 msg_type : msg_type,
721 727 content : content,
722 728 parent_header : {}
723 729 };
724 730 return msg;
725 731 }
726 732
727 733 Kernel.prototype.start_kernel = function (callback, context) {
728 734 var that = this;
729 735 $.post(this.base_url,
730 736 function (kernel_id) {
731 737 that._handle_start_kernel(kernel_id, callback, context);
732 738 },
733 739 'json'
734 740 );
735 741 };
736 742
737 743
738 744 Kernel.prototype._handle_start_kernel = function (kernel_id, callback, context) {
739 745 this.kernel_id = kernel_id;
740 746 this.kernel_url = this.base_url + "/" + this.kernel_id;
741 747 this._start_channels();
742 748 callback.call(context);
743 749 };
744 750
745 751
746 752 Kernel.prototype._start_channels = function () {
747 753 var ws_url = "ws://127.0.0.1:8888" + this.kernel_url;
748 754 this.shell_channel = new WebSocket(ws_url + "/shell");
749 755 this.iopub_channel = new WebSocket(ws_url + "/iopub");
750 756 }
751 757
752 758
753 759 Kernel.prototype.execute = function (code) {
754 760 var content = {
755 761 code : code,
756 762 silent : false,
757 763 user_variables : [],
758 764 user_expressions : {}
759 765 };
760 766 var msg = this.get_msg("execute_request", content);
761 767 this.shell_channel.send(JSON.stringify(msg));
762 768 return msg.header.msg_id;
763 769 }
764 770
765 771
766 772 Kernel.prototype.interrupt = function () {
767 773 $.post(this.kernel_url + "/interrupt");
768 774 };
769 775
770 776
771 777 Kernel.prototype.restart = function () {
778 this.status_restarting();
772 779 url = this.kernel_url + "/restart"
773 780 var that = this;
774 781 $.post(url, function (kernel_id) {
775 782 console.log("Kernel restarted: " + kernel_id);
776 783 that.kernel_id = kernel_id;
777 784 that.kernel_url = that.base_url + "/" + that.kernel_id;
785 that.status_idle();
778 786 }, 'json');
779 787 };
780 788
781 789
790 Kernel.prototype.status_busy = function () {
791 $("#kernel_status").removeClass("status_idle");
792 $("#kernel_status").removeClass("status_restarting");
793 $("#kernel_status").addClass("status_busy");
794 $("#kernel_status").text("Busy");
795 };
796
797
798 Kernel.prototype.status_idle = function () {
799 $("#kernel_status").removeClass("status_busy");
800 $("#kernel_status").removeClass("status_restarting");
801 $("#kernel_status").addClass("status_idle");
802 $("#kernel_status").text("Idle");
803 };
804
805 Kernel.prototype.status_restarting = function () {
806 $("#kernel_status").removeClass("status_busy");
807 $("#kernel_status").removeClass("status_idle");
808 $("#kernel_status").addClass("status_restarting");
809 $("#kernel_status").text("Restarting");
810 };
811
782 812 //============================================================================
783 813 // On document ready
784 814 //============================================================================
785 815
786 816
787 817 $(document).ready(function () {
788 818
789 819 MathJax.Hub.Config({
790 820 tex2jax: {
791 821 inlineMath: [ ['$','$'], ["\\(","\\)"] ],
792 822 displayMath: [ ['$$','$$'], ["\\[","\\]"] ],
793 823 }
794 824 });
795 825
796 826 IPYTHON.notebook = new Notebook('div.notebook');
797 827 IPYTHON.notebook.insert_code_cell_after();
798 828
799 829 $("#menu_tabs").tabs();
800 830
801 831 $("#help_toolbar").buttonset();
802 832
803 833 $("#kernel_toolbar").buttonset();
804 834 $("#interrupt_kernel").click(function () {IPYTHON.notebook.kernel.interrupt();});
805 835 $("#restart_kernel").click(function () {IPYTHON.notebook.kernel.restart();});
836 $("#kernel_status").addClass("status_idle");
806 837
807 838 $("#move_cell").buttonset();
808 839 $("#move_up").button("option", "icons", {primary:"ui-icon-arrowthick-1-n"});
809 840 $("#move_up").button("option", "text", false);
810 841 $("#move_up").click(function () {IPYTHON.notebook.move_cell_up();});
811 842 $("#move_down").button("option", "icons", {primary:"ui-icon-arrowthick-1-s"});
812 843 $("#move_down").button("option", "text", false);
813 844 $("#move_down").click(function () {IPYTHON.notebook.move_cell_down();});
814 845
815 846 $("#insert_delete").buttonset();
816 847 $("#insert_cell_before").click(function () {IPYTHON.notebook.insert_code_cell_before();});
817 848 $("#insert_cell_after").click(function () {IPYTHON.notebook.insert_code_cell_after();});
818 849 $("#delete_cell").button("option", "icons", {primary:"ui-icon-closethick"});
819 850 $("#delete_cell").button("option", "text", false);
820 851 $("#delete_cell").click(function () {IPYTHON.notebook.delete_cell();});
821 852
822 853 $("#cell_type").buttonset();
823 854 $("#to_code").click(function () {IPYTHON.notebook.text_to_code();});
824 855 $("#to_text").click(function () {IPYTHON.notebook.code_to_text();});
825 856
826 857 $("#sort").buttonset();
827 858 $("#sort_cells").click(function () {IPYTHON.notebook.sort_cells();});
828 859
829 860 $("#toggle").buttonset();
830 861 $("#collapse").click(function () {IPYTHON.notebook.collapse();});
831 862 $("#expand").click(function () {IPYTHON.notebook.expand();});
832 863
833 864 }); No newline at end of file
@@ -1,87 +1,88 b''
1 1 <!DOCTYPE HTML>
2 2 <html>
3 3
4 4 <head>
5 5 <meta charset="utf-8">
6 6
7 7 <title>IPython Notebook</title>
8 8
9 9 <link rel="stylesheet" href="static/css/notebook.css" type="text/css" />
10 10
11 11 <link rel="stylesheet" href="static/jquery/css/themes/aristo/jquery-wijmo.css" type="text/css" />
12 12 <!-- <link rel="stylesheet" href="static/jquery/css/themes/rocket/jquery-wijmo.css" type="text/css" /> -->
13 13 <!-- <link rel="stylesheet" href="static/jquery/css/themes/smoothness/jquery-ui-1.8.11.custom.css" type="text/css" /> -->
14 14
15 15 <script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML" charset="utf-8"></script>
16 16
17 17 </head>
18 18
19 19 <body>
20 20
21 21 <div id="header">
22 22 <span id="ipython_notebook"><h1>IPython Notebook</h1></span>
23 23 </div>
24 24
25 25
26 26 <div id="tools">
27 27
28 28 <div id="menu_tabs">
29 <span id="kernel_status">Idle</span>
29 30 <ul>
30 31 <li><a href="#cell_tab">Cell</a></li>
31 32 <li><a href="#kernel_tab">Kernel</a></li>
32 33 <li><a href="#help_tab">Help</a></li>
33 34 </ul>
34 35 <div id="cell_tab">
35 36 <span id="cell_toolbar">
36 37 <span id="move_cell">
37 38 <button id="move_up">Move up</button>
38 39 <button id="move_down">Move down</button>
39 40 </span>
40 41 <span id="insert_delete">
41 42 <button id="insert_cell_before">Before</button>
42 43 <button id="insert_cell_after">After</button>
43 44 <button id="delete_cell">Delete</button>
44 45 </span>
45 46 <span id="cell_type">
46 47 <button id="to_code">Code</button>
47 48 <button id="to_text">Text</button>
48 49 </span>
49 50 <span id="sort">
50 51 <button id="sort_cells">Sort</button>
51 52 </span>
52 53 <span id="toggle">
53 54 <button id="collapse">Collapse</button>
54 55 <button id="expand">Expand</button>
55 56 </span>
56 57 </span>
57 58 </div>
58 59 <div id="kernel_tab">
59 60 <span id="kernel_toolbar">
60 61 <button id="interrupt_kernel">Interrupt</button>
61 62 <button id="restart_kernel">Restart</button>
62 63 </span>
63 64 </div>
64 65 <div id="help_tab">
65 66 <span id="help_toolbar">
66 67 <button><a href="http://docs.python.org" target="_blank">Python</a></button>
67 68 <button><a href="http://ipython.github.com/ipython-doc/dev/index.html" target="_blank">IPython</a></button>
68 69 <button><a href="http://matplotlib.sourceforge.net/" target="_blank">Matplotlib</a></button>
69 70 <button><a href="http://docs.scipy.org/doc/numpy/reference/" target="_blank">NumPy</a></button>
70 71 <button><a href="http://docs.scipy.org/doc/scipy/reference/" target="_blank">SciPy</a></button>
71 72 <button><a href="http://docs.sympy.org/dev/index.html" target="_blank">SymPy</a></button>
72 73 </span>
73 74 </div>
74 75 </div>
75 76
76 77 </div>
77 78
78 79 <div class="notebook"></div>
79 80
80 81 <script src="static/jquery/js/jquery-1.5.1.min.js" type="text/javascript" charset="utf-8"></script>
81 82 <script src="static/jquery/js/jquery-ui-1.8.11.custom.min.js" type="text/javascript" charset="utf-8"></script>
82 83 <script src="static/jquery/js/jquery.autogrow.js" type="text/javascript" charset="utf-8"></script>
83 84 <script src="static/js/notebook.js" type="text/javascript" charset="utf-8"></script>
84 85
85 86 </body>
86 87
87 88 </html> No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now