##// END OF EJS Templates
Hacks to prevent FLOUC (flash of unformatted content).
Brian E. Granger -
Show More
@@ -1,371 +1,375
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
62 62 /**
63 63 * Font normalization inspired by YUI Library's fonts.css: developer.yahoo.com/yui/
64 64 */
65 65
66 66 body { font:13px/1.231 sans-serif; *font-size:small; } /* Hack retained to preserve specificity */
67 67 select, input, textarea, button { font:99% sans-serif; }
68 68
69 69 /* Normalize monospace sizing:
70 70 en.wikipedia.org/wiki/MediaWiki_talk:Common.css/Archive_11#Teletype_style_fix_for_Chrome */
71 71 pre, code, kbd, samp { font-family: monospace, sans-serif; }
72 72
73 73
74 74 /**
75 75 * Primary styles
76 76 *
77 77 * Author: IPython Development Team
78 78 */
79 79
80 80
81 81 body {
82 82 background-color: white;
83 83 /* This makes sure that the body covers the entire window and needs to
84 84 be in a different element than the display: box in wrapper below */
85 85 position: absolute;
86 86 left: 0px;
87 87 right: 0px;
88 88 top: 0px;
89 89 bottom: 0px;
90 90 overflow: hidden;
91 91 }
92 92
93 93
94 94 div#header {
95 /* Initially hidden to prevent FLOUC */
96 display: none;
95 97 position: relative;
96 98 height: 45px;
97 99 padding: 5px;
98 100 margin: 0px;
99 width: 100%
101 width: 100%;
100 102 }
101 103
102 104 span#ipython_notebook {
103 105 position: absolute;
104 106 padding: 2px;
105 107 }
106 108
107 109 span#ipython_notebook h1 {
108 110 font-family: Verdana, "Helvetica Neue", Arial, Helvetica, Geneva, sans-serif;
109 111 font-size: 197%;
110 112 display: inline;
111 113 }
112 114
113 115 span#save_widget {
114 116 position: absolute;
115 117 left: 0px;
116 118 padding: 5px 0px;
117 119 margin: 0px 0px 0px 0px;
118 120 }
119 121
120 122 input#notebook_name {
121 123 height: 1em;
122 124 line-height: 1em;
123 125 padding: 5px;
124 126 }
125 127
126 128 span#kernel_status {
127 129 position: absolute;
128 130 padding: 8px 5px 5px 5px;
129 131 right: 10px;
130 132 font-weight: bold;
131 133 }
132 134
133 135 .status_idle {
134 136 color: gray;
135 137 }
136 138
137 139 .status_busy {
138 140 color: red;
139 141 }
140 142
141 143 .status_restarting {
142 144 color: black;
143 145 }
144 146
145 147 div#notebook_app {
148 /* Initially hidden to prevent FLOUC */
149 display: none;
146 150 width: 100%;
147 151 position: relative;
148 152 }
149 153
150 154 div#left_panel {
151 155 overflow-y: auto;
152 156 top: 0px;
153 157 left: 0px;
154 158 margin: 0px;
155 159 padding: 0px;
156 160 position: absolute;
157 161 }
158 162
159 163 h3.section_header {
160 164 padding: 5px;
161 165 }
162 166
163 167 div.section_content {
164 168 padding: 5px;
165 169 }
166 170
167 171
168 172 span.section_row_buttons > button {
169 173 width: 60px;
170 174 }
171 175
172 176 .section_row {
173 177 margin: 5px 0px;
174 178 }
175 179
176 180 .section_row_buttons {
177 181 float: right;
178 182 }
179 183
180 184 .section_row_header {
181 185 float: left;
182 186 font-size: 85%;
183 187 padding: 0.2em 0em;
184 188 font-weight: bold;
185 189 }
186 190
187 191 span.button_label {
188 192 padding: 0.2em 1em;
189 193 font-size: 77%;
190 194 float: right;
191 195 }
192 196
193 197 /* This is needed because FF was adding a 2px margin top and bottom. */
194 198 .section_row .ui-button {
195 199 margin-top: 0px;
196 200 margin-bottom: 0px;
197 201 }
198 202
199 203
200 204 .ui-button .ui-button-text {
201 205 padding: 0.2em 0.8em;
202 206 font-size: 77%;
203 207 }
204 208
205 209 div#left_panel_splitter {
206 210 width: 8px;
207 211 top: 0px;
208 212 left: 202px;
209 213 margin: 0px;
210 214 padding: 0px;
211 215 position: absolute;
212 216 }
213 217
214 218 div#notebook_panel {
215 219 /* The L margin will be set in the Javascript code*/
216 220 margin: 0px 0px 0px 0px;
217 221 padding: 0px;
218 222 }
219 223
220 224 div#notebook {
221 225 overflow-y: scroll;
222 226 overflow-x: auto;
223 227 width: 100%;
224 228 padding: 0px 15px 0px 15px;
225 229 margin: 0px
226 230 background-color: white;
227 231 }
228 232
229 233 div#pager_splitter {
230 234 height: 8px;
231 235 }
232 236
233 237 div#pager {
234 238 padding: 15px;
235 239 overflow: auto;
236 240 }
237 241
238 242 div.cell {
239 243 width: 100%;
240 244 padding: 5px;
241 245 /* This acts as a spacer between cells, that is outside the border */
242 246 margin: 15px 0px 15px 0px;
243 247 }
244 248
245 249 div.code_cell {
246 250 background-color: white;
247 251 }
248 252
249 253 div.prompt {
250 254 width: 80px;
251 255 padding: 0.4em;
252 256 margin: 0px;
253 257 font-family: monospace;
254 258 }
255 259
256 260 div.input_prompt {
257 261 color: navy;
258 262 }
259 263
260 264 div.output {
261 265 /* This is a spacer between the input and output of each cell */
262 266 margin-top: 15px;
263 267 }
264 268
265 269 div.output_prompt {
266 270 color: darkred;
267 271 }
268 272
269 273 div.output_area {
270 274 text-align: left;
271 275 color: black;
272 276 font-family: monospace;
273 277 }
274 278
275 279 div.output_stream {
276 280 padding: 0.4em;
277 281 }
278 282
279 283 div.output_latex {
280 284 /* Slightly bigger than the rest of the notebook */
281 285 font-size: 116%;
282 286 }
283 287
284 288 div.output_png {
285 289 }
286 290
287 291 div.text_cell {
288 292 background-color: white;
289 293 }
290 294
291 295 textarea.text_cell_input {
292 296 /* Slightly bigger than the rest of the notebook */
293 297 font-size: 116%;
294 298 font-family: monospace;
295 299 outline: none;
296 300 resize: none;
297 301 width: inherit;
298 302 border-style: none;
299 303 padding: 0px;
300 304 margin: 0px;
301 305 color: black;
302 306 }
303 307
304 308 div.text_cell_render {
305 309 font-family: "Helvetica Neue", Arial, Helvetica, Geneva, sans-serif;
306 310 /* Slightly bigger than the rest of the notebook */
307 311 font-size: 116%;
308 312 outline: none;
309 313 resize: none;
310 314 width: inherit;
311 315 border-style: none;
312 316 padding: 5px;
313 317 color: black;
314 318 }
315 319
316 320 div.text_cell_render em {font-style: italic;}
317 321 div.text_cell_render strong {font-weight: bold;}
318 322 div.text_cell_render u {text-decoration: underline;}
319 323 div.text_cell_render :link { text-decoration: underline }
320 324 div.text_cell_render :visited { text-decoration: underline }
321 325 div.text_cell_render h1 {font-size: 197%; margin: .67em 0; font-weight: bold;}
322 326 div.text_cell_render h2 {font-size: 153.9%; margin: .75em 0; font-weight: bold;}
323 327 div.text_cell_render h3 {font-size: 116%; margin: .83em 0; font-weight: bold;}
324 328 div.text_cell_render h4 {margin: 1.12em 0; font-weight: bold;}
325 329 div.text_cell_render h5 {font-size: 85%.; margin: 1.5em 0; font-weight: bold;}
326 330 div.text_cell_render h6 {font-size: 77%; margin: 1.67em 0; font-weight: bold;}
327 331 div.text_cell_render ul {list-style:disc; margin-left: 40px;}
328 332 div.text_cell_render ul ul {list-style:square; margin-left: 40px;}
329 333 div.text_cell_render ul ul ul {list-style:circle; margin-left: 40px;}
330 334 div.text_cell_render ol {list-style:upper-roman; margin-left: 40px;}
331 335 div.text_cell_render ol ol {list-style:upper-alpha;}
332 336 div.text_cell_render ol ol ol {list-style:decimal;}
333 337 div.text_cell_render ol ol ol ol {list-style:lower-alpha;}
334 338 div.text_cell_render ol ol ol ol ol {list-style:lower-roman;}
335 339
336 340
337 341 .CodeMirror {
338 342 overflow: hidden; /* Changed from auto to remove scrollbar */
339 343 height: auto; /* Changed to auto to autogrow */
340 344 line-height: 1.231; /* Changed from 1em to our global default */
341 345 }
342 346
343 347 /* CSS font colors for translated ANSI colors. */
344 348
345 349
346 350 .ansiblack {color: black;}
347 351 .ansired {color: darkred;}
348 352 .ansigreen {color: darkgreen;}
349 353 .ansiyellow {color: brown;}
350 354 .ansiblue {color: darkblue;}
351 355 .ansipurple {color: darkviolet;}
352 356 .ansicyan {color: steelblue;}
353 357 .ansigrey {color: grey;}
354 358 .ansibold {font-weight: bold;}
355 359
356 360 .completions {
357 361 position: absolute;
358 362 z-index: 10;
359 363 overflow: auto;
360 364 border: 1px solid black;
361 365 }
362 366
363 367 .completions select {
364 368 background: white;
365 369 outline: none;
366 370 border: none;
367 371 padding: 0px;
368 372 margin: 0px;
369 373 font-family: monospace;
370 374 }
371 375
@@ -1,624 +1,624
1 1
2 2 //============================================================================
3 3 // Notebook
4 4 //============================================================================
5 5
6 6 var IPython = (function (IPython) {
7 7
8 8 var utils = IPython.utils;
9 9
10 10 var Notebook = function (selector) {
11 11 this.element = $(selector);
12 12 this.element.scroll();
13 13 this.element.data("notebook", this);
14 14 this.next_prompt_number = 1;
15 15 this.kernel = null;
16 16 this.msg_cell_map = {};
17 17 this.filename = null;
18 18 this.notebook_load_re = /%notebook load/
19 19 this.notebook_save_re = /%notebook save/
20 20 this.notebook_filename_re = /(\w)+.ipynb/
21 21 this.style();
22 22 this.create_elements();
23 23 this.bind_events();
24 24 this.start_kernel();
25 25 };
26 26
27 27
28 28 Notebook.prototype.style = function () {
29 29 $('div#notebook').addClass('border-box-sizing');
30 30 };
31 31
32 32
33 33 Notebook.prototype.create_elements = function () {
34 34 // We add this end_space div to the end of the notebook div to:
35 35 // i) provide a margin between the last cell and the end of the notebook
36 36 // ii) to prevent the div from scrolling up when the last cell is being
37 37 // edited, but is too low on the page, which browsers will do automatically.
38 38 this.element.append($('<div class="end_space"></div>').height(50));
39 39 $('div#notebook').addClass('border-box-sizing');
40 40 };
41 41
42 42
43 43 Notebook.prototype.bind_events = function () {
44 44 var that = this;
45 45 $(document).keydown(function (event) {
46 46 // console.log(event);
47 47 if (event.which === 38) {
48 48 var cell = that.selected_cell();
49 49 if (cell.at_top()) {
50 50 event.preventDefault();
51 51 that.select_prev();
52 52 };
53 53 } else if (event.which === 40) {
54 54 var cell = that.selected_cell();
55 55 if (cell.at_bottom()) {
56 56 event.preventDefault();
57 57 that.select_next();
58 58 };
59 59 } else if (event.which === 13 && event.shiftKey) {
60 60 that.execute_selected_cell();
61 61 return false;
62 62 } else if (event.which === 13 && event.ctrlKey) {
63 63 that.execute_selected_cell({terminal:true});
64 64 return false;
65 65 };
66 66 });
67 67
68 68 this.element.bind('collapse_pager', function () {
69 69 var app_height = $('div#notebook_app').height(); // content height
70 70 var splitter_height = $('div#pager_splitter').outerHeight(true);
71 71 var new_height = app_height - splitter_height;
72 72 that.element.animate({height : new_height + 'px'}, 'fast');
73 73 });
74 74
75 75 this.element.bind('expand_pager', function () {
76 76 var app_height = $('div#notebook_app').height(); // content height
77 77 var splitter_height = $('div#pager_splitter').outerHeight(true);
78 78 var pager_height = $('div#pager').outerHeight(true);
79 79 var new_height = app_height - pager_height - splitter_height;
80 80 that.element.animate({height : new_height + 'px'}, 'fast');
81 81 });
82 82
83 83 this.element.bind('collapse_left_panel', function () {
84 84 var splitter_width = $('div#left_panel_splitter').outerWidth(true);
85 85 var new_margin = splitter_width;
86 86 $('div#notebook_panel').animate({marginLeft : new_margin + 'px'}, 'fast');
87 87 });
88 88
89 89 this.element.bind('expand_left_panel', function () {
90 90 var splitter_width = $('div#left_panel_splitter').outerWidth(true);
91 91 var left_panel_width = IPython.left_panel.width;
92 92 var new_margin = splitter_width + left_panel_width;
93 93 $('div#notebook_panel').animate({marginLeft : new_margin + 'px'}, 'fast');
94 94 });
95 95 };
96 96
97 97
98 98 Notebook.prototype.scroll_to_bottom = function () {
99 99 this.element.animate({scrollTop:this.element.get(0).scrollHeight}, 0);
100 100 };
101 101
102 102 // Cell indexing, retrieval, etc.
103 103
104 104
105 105 Notebook.prototype.cell_elements = function () {
106 106 return this.element.children("div.cell");
107 107 }
108 108
109 109
110 110 Notebook.prototype.ncells = function (cell) {
111 111 return this.cell_elements().length;
112 112 }
113 113
114 114
115 115 // TODO: we are often calling cells as cells()[i], which we should optimize
116 116 // to cells(i) or a new method.
117 117 Notebook.prototype.cells = function () {
118 118 return this.cell_elements().toArray().map(function (e) {
119 119 return $(e).data("cell");
120 120 });
121 121 }
122 122
123 123
124 124 Notebook.prototype.find_cell_index = function (cell) {
125 125 var result = null;
126 126 this.cell_elements().filter(function (index) {
127 127 if ($(this).data("cell") === cell) {
128 128 result = index;
129 129 };
130 130 });
131 131 return result;
132 132 };
133 133
134 134
135 135 Notebook.prototype.index_or_selected = function (index) {
136 136 return index || this.selected_index() || 0;
137 137 }
138 138
139 139
140 140 Notebook.prototype.select = function (index) {
141 141 if (index !== undefined && index >= 0 && index < this.ncells()) {
142 142 if (this.selected_index() !== null) {
143 143 this.selected_cell().unselect();
144 144 };
145 145 this.cells()[index].select();
146 146 if (index === (this.ncells()-1)) {
147 147 this.scroll_to_bottom();
148 148 };
149 149 };
150 150 return this;
151 151 };
152 152
153 153
154 154 Notebook.prototype.select_next = function () {
155 155 var index = this.selected_index();
156 156 if (index !== null && index >= 0 && (index+1) < this.ncells()) {
157 157 this.select(index+1);
158 158 };
159 159 return this;
160 160 };
161 161
162 162
163 163 Notebook.prototype.select_prev = function () {
164 164 var index = this.selected_index();
165 165 if (index !== null && index >= 0 && (index-1) < this.ncells()) {
166 166 this.select(index-1);
167 167 };
168 168 return this;
169 169 };
170 170
171 171
172 172 Notebook.prototype.selected_index = function () {
173 173 var result = null;
174 174 this.cell_elements().filter(function (index) {
175 175 if ($(this).data("cell").selected === true) {
176 176 result = index;
177 177 };
178 178 });
179 179 return result;
180 180 };
181 181
182 182
183 183 Notebook.prototype.cell_for_msg = function (msg_id) {
184 184 var cell_id = this.msg_cell_map[msg_id];
185 185 var result = null;
186 186 this.cell_elements().filter(function (index) {
187 187 cell = $(this).data("cell");
188 188 if (cell.cell_id === cell_id) {
189 189 result = cell;
190 190 };
191 191 });
192 192 return result;
193 193 };
194 194
195 195
196 196 Notebook.prototype.selected_cell = function () {
197 197 return this.cell_elements().eq(this.selected_index()).data("cell");
198 198 }
199 199
200 200
201 201 // Cell insertion, deletion and moving.
202 202
203 203
204 204 Notebook.prototype.delete_cell = function (index) {
205 205 var i = index || this.selected_index();
206 206 if (i !== null && i >= 0 && i < this.ncells()) {
207 207 this.cell_elements().eq(i).remove();
208 208 if (i === (this.ncells())) {
209 209 this.select(i-1);
210 210 } else {
211 211 this.select(i);
212 212 };
213 213 };
214 214 return this;
215 215 };
216 216
217 217
218 218 Notebook.prototype.append_cell = function (cell) {
219 219 this.element.find('div.end_space').before(cell.element);
220 220 return this;
221 221 };
222 222
223 223
224 224 Notebook.prototype.insert_cell_after = function (cell, index) {
225 225 var ncells = this.ncells();
226 226 if (ncells === 0) {
227 227 this.append_cell(cell);
228 228 return this;
229 229 };
230 230 if (index >= 0 && index < ncells) {
231 231 this.cell_elements().eq(index).after(cell.element);
232 232 };
233 233 return this
234 234 };
235 235
236 236
237 237 Notebook.prototype.insert_cell_before = function (cell, index) {
238 238 var ncells = this.ncells();
239 239 if (ncells === 0) {
240 240 this.append_cell(cell);
241 241 return this;
242 242 };
243 243 if (index >= 0 && index < ncells) {
244 244 this.cell_elements().eq(index).before(cell.element);
245 245 };
246 246 return this;
247 247 };
248 248
249 249
250 250 Notebook.prototype.move_cell_up = function (index) {
251 251 var i = index || this.selected_index();
252 252 if (i !== null && i < this.ncells() && i > 0) {
253 253 var pivot = this.cell_elements().eq(i-1);
254 254 var tomove = this.cell_elements().eq(i);
255 255 if (pivot !== null && tomove !== null) {
256 256 tomove.detach();
257 257 pivot.before(tomove);
258 258 this.select(i-1);
259 259 };
260 260 };
261 261 return this;
262 262 }
263 263
264 264
265 265 Notebook.prototype.move_cell_down = function (index) {
266 266 var i = index || this.selected_index();
267 267 if (i !== null && i < (this.ncells()-1) && i >= 0) {
268 268 var pivot = this.cell_elements().eq(i+1)
269 269 var tomove = this.cell_elements().eq(i)
270 270 if (pivot !== null && tomove !== null) {
271 271 tomove.detach();
272 272 pivot.after(tomove);
273 273 this.select(i+1);
274 274 };
275 275 };
276 276 return this;
277 277 }
278 278
279 279
280 280 Notebook.prototype.sort_cells = function () {
281 281 var ncells = this.ncells();
282 282 var sindex = this.selected_index();
283 283 var swapped;
284 284 do {
285 285 swapped = false
286 286 for (var i=1; i<ncells; i++) {
287 287 current = this.cell_elements().eq(i).data("cell");
288 288 previous = this.cell_elements().eq(i-1).data("cell");
289 289 if (previous.input_prompt_number > current.input_prompt_number) {
290 290 this.move_cell_up(i);
291 291 swapped = true;
292 292 };
293 293 };
294 294 } while (swapped);
295 295 this.select(sindex);
296 296 return this;
297 297 };
298 298
299 299
300 300 Notebook.prototype.insert_code_cell_before = function (index) {
301 301 // TODO: Bounds check for i
302 302 var i = this.index_or_selected(index);
303 303 var cell = new IPython.CodeCell(this);
304 304 // cell.set_input_prompt(this.next_prompt_number);
305 305 cell.set_input_prompt();
306 306 this.next_prompt_number = this.next_prompt_number + 1;
307 307 this.insert_cell_before(cell, i);
308 308 this.select(this.find_cell_index(cell));
309 309 return this;
310 310 }
311 311
312 312
313 313 Notebook.prototype.insert_code_cell_after = function (index) {
314 314 // TODO: Bounds check for i
315 315 var i = this.index_or_selected(index);
316 316 var cell = new IPython.CodeCell(this);
317 317 // cell.set_input_prompt(this.next_prompt_number);
318 318 cell.set_input_prompt();
319 319 this.next_prompt_number = this.next_prompt_number + 1;
320 320 this.insert_cell_after(cell, i);
321 321 this.select(this.find_cell_index(cell));
322 322 return this;
323 323 }
324 324
325 325
326 326 Notebook.prototype.insert_text_cell_before = function (index) {
327 327 // TODO: Bounds check for i
328 328 var i = this.index_or_selected(index);
329 329 var cell = new IPython.TextCell(this);
330 330 cell.config_mathjax();
331 331 this.insert_cell_before(cell, i);
332 332 this.select(this.find_cell_index(cell));
333 333 return this;
334 334 }
335 335
336 336
337 337 Notebook.prototype.insert_text_cell_after = function (index) {
338 338 // TODO: Bounds check for i
339 339 var i = this.index_or_selected(index);
340 340 var cell = new IPython.TextCell(this);
341 341 cell.config_mathjax();
342 342 this.insert_cell_after(cell, i);
343 343 this.select(this.find_cell_index(cell));
344 344 return this;
345 345 }
346 346
347 347
348 348 Notebook.prototype.text_to_code = function (index) {
349 349 // TODO: Bounds check for i
350 350 var i = this.index_or_selected(index);
351 351 var source_element = this.cell_elements().eq(i);
352 352 var source_cell = source_element.data("cell");
353 353 if (source_cell instanceof IPython.TextCell) {
354 354 this.insert_code_cell_after(i);
355 355 var target_cell = this.cells()[i+1];
356 356 target_cell.set_code(source_cell.get_text());
357 357 source_element.remove();
358 358 };
359 359 };
360 360
361 361
362 362 Notebook.prototype.code_to_text = function (index) {
363 363 // TODO: Bounds check for i
364 364 var i = this.index_or_selected(index);
365 365 var source_element = this.cell_elements().eq(i);
366 366 var source_cell = source_element.data("cell");
367 367 if (source_cell instanceof IPython.CodeCell) {
368 368 this.insert_text_cell_after(i);
369 369 var target_cell = this.cells()[i+1];
370 370 var text = source_cell.get_code();
371 371 if (text === "") {text = target_cell.placeholder;};
372 372 target_cell.set_text(text);
373 373 source_element.remove();
374 374 target_cell.edit();
375 375 };
376 376 };
377 377
378 378
379 379 // Cell collapsing
380 380
381 381 Notebook.prototype.collapse = function (index) {
382 382 var i = this.index_or_selected(index);
383 383 this.cells()[i].collapse();
384 384 };
385 385
386 386
387 387 Notebook.prototype.expand = function (index) {
388 388 var i = this.index_or_selected(index);
389 389 this.cells()[i].expand();
390 390 };
391 391
392 392
393 393 // Kernel related things
394 394
395 395 Notebook.prototype.start_kernel = function () {
396 396 this.kernel = new IPython.Kernel();
397 397 this.kernel.start_kernel($.proxy(this.kernel_started, this));
398 398 };
399 399
400 400
401 401 Notebook.prototype.handle_shell_reply = function (e) {
402 402 reply = $.parseJSON(e.data);
403 403 var header = reply.header;
404 404 var content = reply.content;
405 405 var msg_type = header.msg_type;
406 406 // console.log(reply);
407 407 var cell = this.cell_for_msg(reply.parent_header.msg_id);
408 408 if (msg_type === "execute_reply") {
409 409 cell.set_input_prompt(content.execution_count);
410 410 } else if (msg_type === "complete_reply") {
411 411 cell.finish_completing(content.matched_text, content.matches);
412 412 };
413 413 var payload = content.payload || [];
414 414 this.handle_payload(payload);
415 415 };
416 416
417 417
418 418 Notebook.prototype.handle_payload = function (payload) {
419 419 var l = payload.length;
420 420 if (l > 0) {
421 421 IPython.pager.clear();
422 422 IPython.pager.expand();
423 423 };
424 424 for (var i=0; i<l; i++) {
425 425 IPython.pager.append_text(payload[i].text);
426 426 };
427 427 };
428 428
429 429
430 430 Notebook.prototype.handle_iopub_reply = function (e) {
431 431 reply = $.parseJSON(e.data);
432 432 var content = reply.content;
433 433 // console.log(reply);
434 434 var msg_type = reply.header.msg_type;
435 435 var cell = this.cell_for_msg(reply.parent_header.msg_id);
436 436 if (msg_type === "stream") {
437 437 cell.expand();
438 438 cell.append_stream(content.data + "\n");
439 439 } else if (msg_type === "display_data") {
440 440 cell.expand();
441 441 cell.append_display_data(content.data);
442 442 } else if (msg_type === "pyout") {
443 443 cell.expand();
444 444 cell.append_pyout(content.data, content.execution_count)
445 445 } else if (msg_type === "pyerr") {
446 446 cell.expand();
447 447 cell.append_pyerr(content.ename, content.evalue, content.traceback);
448 448 } else if (msg_type === "status") {
449 449 if (content.execution_state === "busy") {
450 450 IPython.kernel_status_widget.status_busy();
451 451 } else if (content.execution_state === "idle") {
452 452 IPython.kernel_status_widget.status_idle();
453 453 };
454 454 }
455 455 };
456 456
457 457
458 458 Notebook.prototype.kernel_started = function () {
459 459 console.log("Kernel started: ", this.kernel.kernel_id);
460 460 this.kernel.shell_channel.onmessage = $.proxy(this.handle_shell_reply,this);
461 461 this.kernel.iopub_channel.onmessage = $.proxy(this.handle_iopub_reply,this);
462 462 };
463 463
464 464
465 465 Notebook.prototype.execute_selected_cell = function (options) {
466 466 // add_new: should a new cell be added if we are at the end of the nb
467 467 // terminal: execute in terminal mode, which stays in the current cell
468 468 default_options = {terminal: false, add_new: true}
469 469 $.extend(default_options, options)
470 470 var that = this;
471 471 var cell = that.selected_cell();
472 472 var cell_index = that.find_cell_index(cell);
473 // TODO: the logic here needs to be moved into appropriate
474 // methods of Notebook.
475 473 if (cell instanceof IPython.CodeCell) {
476 474 cell.clear_output();
477 475 var code = cell.get_code();
478 476 if (that.notebook_load_re.test(code)) {
477 // %notebook load
479 478 var code_parts = code.split(' ');
480 479 if (code_parts.length === 3) {
481 480 that.load_notebook(code_parts[2]);
482 481 };
483 482 } else if (that.notebook_save_re.test(code)) {
483 // %notebook save
484 484 var code_parts = code.split(' ');
485 485 if (code_parts.length === 3) {
486 486 that.save_notebook(code_parts[2]);
487 487 } else {
488 488 that.save_notebook()
489 489 };
490 490 } else {
491 491 var msg_id = that.kernel.execute(cell.get_code());
492 492 that.msg_cell_map[msg_id] = cell.cell_id;
493 493 };
494 494 } else if (cell instanceof IPython.TextCell) {
495 495 cell.render();
496 496 }
497 497 if (default_options.terminal) {
498 498 cell.clear_input();
499 499 } else {
500 500 if ((cell_index === (that.ncells()-1)) && default_options.add_new) {
501 501 that.insert_code_cell_after();
502 502 // If we are adding a new cell at the end, scroll down to show it.
503 503 that.scroll_to_bottom();
504 504 } else {
505 505 that.select(cell_index+1);
506 506 };
507 507 };
508 508 };
509 509
510 510
511 511 Notebook.prototype.execute_all_cells = function () {
512 512 var ncells = this.ncells();
513 513 for (var i=0; i<ncells; i++) {
514 514 this.select(i);
515 515 this.execute_selected_cell({add_new:false});
516 516 };
517 517 this.scroll_to_bottom();
518 518 };
519 519
520 520
521 521 Notebook.prototype.complete_cell = function (cell, line, cursor_pos) {
522 522 var msg_id = this.kernel.complete(line, cursor_pos);
523 523 this.msg_cell_map[msg_id] = cell.cell_id;
524 524 };
525 525
526 526 // Persistance and loading
527 527
528 528
529 529 Notebook.prototype.fromJSON = function (data) {
530 530 var ncells = this.ncells();
531 531 for (var i=0; i<ncells; i++) {
532 532 // Always delete cell 0 as they get renumbered as they are deleted.
533 533 this.delete_cell(0);
534 534 };
535 535 var new_cells = data.cells;
536 536 ncells = new_cells.length;
537 537 var cell_data = null;
538 538 for (var i=0; i<ncells; i++) {
539 539 cell_data = new_cells[i];
540 540 if (cell_data.cell_type == 'code') {
541 541 this.insert_code_cell_after();
542 542 this.selected_cell().fromJSON(cell_data);
543 543 } else if (cell_data.cell_type === 'text') {
544 544 this.insert_text_cell_after();
545 545 this.selected_cell().fromJSON(cell_data);
546 546 };
547 547 };
548 548 };
549 549
550 550
551 551 Notebook.prototype.toJSON = function () {
552 552 var cells = this.cells();
553 553 var ncells = cells.length;
554 554 cell_array = new Array(ncells);
555 555 for (var i=0; i<ncells; i++) {
556 556 cell_array[i] = cells[i].toJSON();
557 557 };
558 558 json = {
559 559 cells : cell_array
560 560 };
561 561 return json
562 562 };
563 563
564 564
565 565 Notebook.prototype.test_filename = function (filename) {
566 566 if (this.notebook_filename_re.test(filename)) {
567 567 return true;
568 568 } else {
569 569 var bad_filename = $('<div/>');
570 570 bad_filename.html(
571 571 "The filename you entered (" + filename + ") is not valid. Notebook filenames must have the following form: foo.ipynb"
572 572 );
573 573 bad_filename.dialog({title: 'Invalid filename', modal: true});
574 574 return false;
575 575 };
576 576 };
577 577
578 578 Notebook.prototype.save_notebook = function (filename) {
579 579 this.filename = filename || this.filename || '';
580 580 if (this.filename === '') {
581 581 var no_filename = $('<div/>');
582 582 no_filename.html(
583 583 "This notebook has no filename, please specify a filename of the form: foo.ipynb"
584 584 );
585 585 no_filename.dialog({title: 'Missing filename', modal: true});
586 586 return;
587 587 }
588 588 if (!this.test_filename(this.filename)) {return;}
589 589 var thedata = this.toJSON();
590 590 var settings = {
591 591 processData : false,
592 592 cache : false,
593 593 type : "PUT",
594 594 data : JSON.stringify(thedata),
595 595 success : function (data, status, xhr) {console.log(data);}
596 596 };
597 597 $.ajax("/notebooks/" + this.filename, settings);
598 598 };
599 599
600 600
601 601 Notebook.prototype.load_notebook = function (filename) {
602 602 if (!this.test_filename(filename)) {return;}
603 603 var that = this;
604 604 // We do the call with settings so we can set cache to false.
605 605 var settings = {
606 606 processData : false,
607 607 cache : false,
608 608 type : "GET",
609 609 dataType : "json",
610 610 success : function (data, status, xhr) {
611 611 that.fromJSON(data);
612 612 that.filename = filename;
613 613 that.kernel.restart();
614 614 }
615 615 };
616 616 $.ajax("/notebooks/" + filename, settings);
617 617 }
618 618
619 619 IPython.Notebook = Notebook;
620 620
621 621 return IPython;
622 622
623 623 }(IPython));
624 624
@@ -1,38 +1,42
1 1
2 2 //============================================================================
3 3 // On document ready
4 4 //============================================================================
5 5
6 6
7 7 $(document).ready(function () {
8 8
9 9 MathJax.Hub.Config({
10 10 tex2jax: {
11 11 inlineMath: [ ['$','$'], ["\\(","\\)"] ],
12 12 displayMath: [ ['$$','$$'], ["\\[","\\]"] ],
13 13 },
14 14 displayAlign: 'left', // Change this to 'center' to center equations.
15 15 "HTML-CSS": {
16 16 styles: {'.MathJax_Display': {"margin": 0}}
17 17 }
18 18 });
19 19
20 20 $('div#header').addClass('border-box-sizing');
21 21 $('div#notebook_app').addClass('border-box-sizing ui-widget ui-widget-content');
22 22 $('div#notebook_panel').addClass('border-box-sizing ui-widget');
23 23
24 24 IPython.layout_manager = new IPython.LayoutManager();
25 25 IPython.pager = new IPython.Pager('div#pager', 'div#pager_splitter');
26 26 IPython.left_panel = new IPython.LeftPanel('div#left_panel', 'div#left_panel_splitter');
27 27 IPython.save_widget = new IPython.SaveWidget('span#save_widget');
28 28 IPython.notebook = new IPython.Notebook('div#notebook');
29 29 IPython.kernel_status_widget = new IPython.KernelStatusWidget('#kernel_status');
30 30 IPython.kernel_status_widget.status_idle();
31 31
32 32 IPython.layout_manager.do_resize();
33 33 IPython.notebook.insert_code_cell_after();
34 34 IPython.layout_manager.do_resize();
35 35 IPython.pager.collapse();
36 36 IPython.layout_manager.do_resize();
37
38 // These have display: none in the css file and are made visible here to prevent FLOUC.
39 $('div#header').css('display','block');
40 $('div#notebook_app').css('display','block');
37 41 });
38 42
General Comments 0
You need to be logged in to leave comments. Login now