##// END OF EJS Templates
Make pager resizable, and remember size......
Matthias BUSSONNIER -
Show More
@@ -1,59 +1,62 b''
1 1 //----------------------------------------------------------------------------
2 2 // Copyright (C) 2008-2011 The IPython Development Team
3 3 //
4 4 // Distributed under the terms of the BSD License. The full license is in
5 5 // the file COPYING, distributed as part of this software.
6 6 //----------------------------------------------------------------------------
7 7
8 8 //============================================================================
9 9 // Layout
10 10 //============================================================================
11 11
12 12 var IPython = (function (IPython) {
13 13
14 14 var LayoutManager = function () {
15 15 this.bind_events();
16 16 };
17 17
18 18
19 19 LayoutManager.prototype.bind_events = function () {
20 20 $(window).resize($.proxy(this.do_resize,this));
21 21 };
22 22
23
24 LayoutManager.prototype.do_resize = function () {
23 LayoutManager.prototype.app_height = function() {
25 24 var win = $(window);
26 25 var w = win.width();
27 26 var h = win.height();
28 27 var header_height;
29 28 if ($('div#header').css('display') === 'none') {
30 29 header_height = 0;
31 30 } else {
32 31 header_height = $('div#header').outerHeight(true);
33 32 }
34 33 var menubar_height = $('div#menubar').outerHeight(true);
35 34 var toolbar_height;
36 35 if ($('div#toolbar').css('display') === 'none') {
37 36 toolbar_height = 0;
38 37 } else {
39 38 toolbar_height = $('div#toolbar').outerHeight(true);
40 39 }
41 var app_height = h-header_height-menubar_height-toolbar_height; // content height
40 return h-header_height-menubar_height-toolbar_height; // content height
41 }
42
43 LayoutManager.prototype.do_resize = function () {
44 var app_height = this.app_height() // content height
42 45
43 46 $('div#main_app').height(app_height); // content+padding+border height
44 47
45 48 var pager_height = IPython.pager.percentage_height*app_height;
46 49 var pager_splitter_height = $('div#pager_splitter').outerHeight(true);
47 50 $('div#pager').height(pager_height);
48 51 if (IPython.pager.expanded) {
49 52 $('div#notebook').height(app_height-pager_height-pager_splitter_height);
50 53 } else {
51 54 $('div#notebook').height(app_height-pager_splitter_height);
52 55 }
53 56 };
54 57
55 58 IPython.LayoutManager = LayoutManager;
56 59
57 60 return IPython;
58 61
59 62 }(IPython));
@@ -1,1351 +1,1361 b''
1 1 //----------------------------------------------------------------------------
2 2 // Copyright (C) 2008-2011 The IPython Development Team
3 3 //
4 4 // Distributed under the terms of the BSD License. The full license is in
5 5 // the file COPYING, distributed as part of this software.
6 6 //----------------------------------------------------------------------------
7 7
8 8 //============================================================================
9 9 // Notebook
10 10 //============================================================================
11 11
12 12 var IPython = (function (IPython) {
13 13
14 14 var utils = IPython.utils;
15 15
16 16 var Notebook = function (selector) {
17 17 this.read_only = IPython.read_only;
18 18 this.element = $(selector);
19 19 this.element.scroll();
20 20 this.element.data("notebook", this);
21 21 this.next_prompt_number = 1;
22 22 this.kernel = null;
23 23 this.clipboard = null;
24 24 this.paste_enabled = false;
25 25 this.dirty = false;
26 26 this.msg_cell_map = {};
27 27 this.metadata = {};
28 28 this.control_key_active = false;
29 29 this.notebook_id = null;
30 30 this.notebook_name = null;
31 31 this.notebook_name_blacklist_re = /[\/\\]/;
32 32 this.nbformat = 3 // Increment this when changing the nbformat
33 33 this.style();
34 34 this.create_elements();
35 35 this.bind_events();
36 36 this.set_tooltipontab(true);
37 37 this.set_smartcompleter(true);
38 38 this.set_timebeforetooltip(1200);
39 39 };
40 40
41 41
42 42 Notebook.prototype.style = function () {
43 43 $('div#notebook').addClass('border-box-sizing');
44 44 };
45 45
46 46
47 47 Notebook.prototype.create_elements = function () {
48 48 // We add this end_space div to the end of the notebook div to:
49 49 // i) provide a margin between the last cell and the end of the notebook
50 50 // ii) to prevent the div from scrolling up when the last cell is being
51 51 // edited, but is too low on the page, which browsers will do automatically.
52 52 var that = this;
53 53 var end_space = $('<div/>').addClass('end_space').height("30%");
54 54 end_space.dblclick(function (e) {
55 55 if (that.read_only) return;
56 56 var ncells = that.ncells();
57 57 that.insert_cell_below('code',ncells-1);
58 58 });
59 59 this.element.append(end_space);
60 60 $('div#notebook').addClass('border-box-sizing');
61 61 };
62 62
63 63
64 64 Notebook.prototype.bind_events = function () {
65 65 var that = this;
66 66 $(document).keydown(function (event) {
67 67 // console.log(event);
68 68 if (that.read_only) return true;
69 69
70 70 // Save (CTRL+S) or (AppleKey+S)
71 71 //metaKey = applekey on mac
72 72 if ((event.ctrlKey || event.metaKey) && event.keyCode==83) {
73 73 that.save_notebook();
74 74 event.preventDefault();
75 75 return false;
76 76 } else if (event.which === 27) {
77 77 // Intercept escape at highest level to avoid closing
78 78 // websocket connection with firefox
79 79 event.preventDefault();
80 80 }
81 81 if (event.which === 38 && !event.shiftKey) {
82 82 var cell = that.get_selected_cell();
83 83 if (cell.at_top()) {
84 84 event.preventDefault();
85 85 that.select_prev();
86 86 };
87 87 } else if (event.which === 40 && !event.shiftKey) {
88 88 var cell = that.get_selected_cell();
89 89 if (cell.at_bottom()) {
90 90 event.preventDefault();
91 91 that.select_next();
92 92 };
93 93 } else if (event.which === 13 && event.shiftKey) {
94 94 that.execute_selected_cell();
95 95 return false;
96 96 } else if (event.which === 13 && event.ctrlKey) {
97 97 that.execute_selected_cell({terminal:true});
98 98 return false;
99 99 } else if (event.which === 77 && event.ctrlKey && that.control_key_active == false) {
100 100 that.control_key_active = true;
101 101 return false;
102 102 } else if (event.which === 88 && that.control_key_active) {
103 103 // Cut selected cell = x
104 104 that.cut_cell();
105 105 that.control_key_active = false;
106 106 return false;
107 107 } else if (event.which === 67 && that.control_key_active) {
108 108 // Copy selected cell = c
109 109 that.copy_cell();
110 110 that.control_key_active = false;
111 111 return false;
112 112 } else if (event.which === 86 && that.control_key_active) {
113 113 // Paste selected cell = v
114 114 that.paste_cell();
115 115 that.control_key_active = false;
116 116 return false;
117 117 } else if (event.which === 68 && that.control_key_active) {
118 118 // Delete selected cell = d
119 119 that.delete_cell();
120 120 that.control_key_active = false;
121 121 return false;
122 122 } else if (event.which === 65 && that.control_key_active) {
123 123 // Insert code cell above selected = a
124 124 that.insert_cell_above('code');
125 125 that.control_key_active = false;
126 126 return false;
127 127 } else if (event.which === 66 && that.control_key_active) {
128 128 // Insert code cell below selected = b
129 129 that.insert_cell_below('code');
130 130 that.control_key_active = false;
131 131 return false;
132 132 } else if (event.which === 89 && that.control_key_active) {
133 133 // To code = y
134 134 that.to_code();
135 135 that.control_key_active = false;
136 136 return false;
137 137 } else if (event.which === 77 && that.control_key_active) {
138 138 // To markdown = m
139 139 that.to_markdown();
140 140 that.control_key_active = false;
141 141 return false;
142 142 } else if (event.which === 84 && that.control_key_active) {
143 143 // To Raw = t
144 144 that.to_raw();
145 145 that.control_key_active = false;
146 146 return false;
147 147 } else if (event.which === 49 && that.control_key_active) {
148 148 // To Heading 1 = 1
149 149 that.to_heading(undefined, 1);
150 150 that.control_key_active = false;
151 151 return false;
152 152 } else if (event.which === 50 && that.control_key_active) {
153 153 // To Heading 2 = 2
154 154 that.to_heading(undefined, 2);
155 155 that.control_key_active = false;
156 156 return false;
157 157 } else if (event.which === 51 && that.control_key_active) {
158 158 // To Heading 3 = 3
159 159 that.to_heading(undefined, 3);
160 160 that.control_key_active = false;
161 161 return false;
162 162 } else if (event.which === 52 && that.control_key_active) {
163 163 // To Heading 4 = 4
164 164 that.to_heading(undefined, 4);
165 165 that.control_key_active = false;
166 166 return false;
167 167 } else if (event.which === 53 && that.control_key_active) {
168 168 // To Heading 5 = 5
169 169 that.to_heading(undefined, 5);
170 170 that.control_key_active = false;
171 171 return false;
172 172 } else if (event.which === 54 && that.control_key_active) {
173 173 // To Heading 6 = 6
174 174 that.to_heading(undefined, 6);
175 175 that.control_key_active = false;
176 176 return false;
177 177 } else if (event.which === 79 && that.control_key_active) {
178 178 // Toggle output = o
179 179 that.toggle_output();
180 180 that.control_key_active = false;
181 181 return false;
182 182 } else if (event.which === 83 && that.control_key_active) {
183 183 // Save notebook = s
184 184 that.save_notebook();
185 185 that.control_key_active = false;
186 186 return false;
187 187 } else if (event.which === 74 && that.control_key_active) {
188 188 // Move cell down = j
189 189 that.move_cell_down();
190 190 that.control_key_active = false;
191 191 return false;
192 192 } else if (event.which === 75 && that.control_key_active) {
193 193 // Move cell up = k
194 194 that.move_cell_up();
195 195 that.control_key_active = false;
196 196 return false;
197 197 } else if (event.which === 80 && that.control_key_active) {
198 198 // Select previous = p
199 199 that.select_prev();
200 200 that.control_key_active = false;
201 201 return false;
202 202 } else if (event.which === 78 && that.control_key_active) {
203 203 // Select next = n
204 204 that.select_next();
205 205 that.control_key_active = false;
206 206 return false;
207 207 } else if (event.which === 76 && that.control_key_active) {
208 208 // Toggle line numbers = l
209 209 that.cell_toggle_line_numbers();
210 210 that.control_key_active = false;
211 211 return false;
212 212 } else if (event.which === 73 && that.control_key_active) {
213 213 // Interrupt kernel = i
214 214 that.kernel.interrupt();
215 215 that.control_key_active = false;
216 216 return false;
217 217 } else if (event.which === 190 && that.control_key_active) {
218 218 // Restart kernel = . # matches qt console
219 219 that.restart_kernel();
220 220 that.control_key_active = false;
221 221 return false;
222 222 } else if (event.which === 72 && that.control_key_active) {
223 223 // Show keyboard shortcuts = h
224 224 IPython.quick_help.show_keyboard_shortcuts();
225 225 that.control_key_active = false;
226 226 return false;
227 227 } else if (that.control_key_active) {
228 228 that.control_key_active = false;
229 229 return true;
230 230 };
231 231 return true;
232 232 });
233 233
234 this.element.bind('collapse_pager', function () {
234 var collapse_time = function(time){
235 235 var app_height = $('div#main_app').height(); // content height
236 236 var splitter_height = $('div#pager_splitter').outerHeight(true);
237 237 var new_height = app_height - splitter_height;
238 that.element.animate({height : new_height + 'px'}, 'fast');
238 that.element.animate({height : new_height + 'px'}, time);
239 }
240
241 this.element.bind('collapse_pager', function (event,extrap) {
242 time = (extrap != undefined) ? ((extrap.duration != undefined ) ? extrap.duration : 'fast') : 'fast';
243 collapse_time(time);
239 244 });
240 245
241 this.element.bind('expand_pager', function () {
246 var expand_time = function(time) {
242 247 var app_height = $('div#main_app').height(); // content height
243 248 var splitter_height = $('div#pager_splitter').outerHeight(true);
244 249 var pager_height = $('div#pager').outerHeight(true);
245 250 var new_height = app_height - pager_height - splitter_height;
246 that.element.animate({height : new_height + 'px'}, 'fast');
251 that.element.animate({height : new_height + 'px'}, time);
252 }
253
254 this.element.bind('expand_pager', function (event, extrap) {
255 time = (extrap != undefined) ? ((extrap.duration != undefined ) ? extrap.duration : 'fast') : 'fast';
256 expand_time(time);
247 257 });
248 258
249 259 $(window).bind('beforeunload', function () {
250 260 // TODO: Make killing the kernel configurable.
251 261 var kill_kernel = false;
252 262 if (kill_kernel) {
253 263 that.kernel.kill();
254 264 }
255 265 if (that.dirty && ! that.read_only) {
256 266 return "You have unsaved changes that will be lost if you leave this page.";
257 267 };
258 268 // Null is the *only* return value that will make the browser not
259 269 // pop up the "don't leave" dialog.
260 270 return null;
261 271 });
262 272 };
263 273
264 274
265 275 Notebook.prototype.scroll_to_bottom = function () {
266 276 this.element.animate({scrollTop:this.element.get(0).scrollHeight}, 0);
267 277 };
268 278
269 279
270 280 Notebook.prototype.scroll_to_top = function () {
271 281 this.element.animate({scrollTop:0}, 0);
272 282 };
273 283
274 284
275 285 // Cell indexing, retrieval, etc.
276 286
277 287 Notebook.prototype.get_cell_elements = function () {
278 288 return this.element.children("div.cell");
279 289 };
280 290
281 291
282 292 Notebook.prototype.get_cell_element = function (index) {
283 293 var result = null;
284 294 var e = this.get_cell_elements().eq(index);
285 295 if (e.length !== 0) {
286 296 result = e;
287 297 }
288 298 return result;
289 299 };
290 300
291 301
292 302 Notebook.prototype.ncells = function (cell) {
293 303 return this.get_cell_elements().length;
294 304 };
295 305
296 306
297 307 // TODO: we are often calling cells as cells()[i], which we should optimize
298 308 // to cells(i) or a new method.
299 309 Notebook.prototype.get_cells = function () {
300 310 return this.get_cell_elements().toArray().map(function (e) {
301 311 return $(e).data("cell");
302 312 });
303 313 };
304 314
305 315
306 316 Notebook.prototype.get_cell = function (index) {
307 317 var result = null;
308 318 var ce = this.get_cell_element(index);
309 319 if (ce !== null) {
310 320 result = ce.data('cell');
311 321 }
312 322 return result;
313 323 }
314 324
315 325
316 326 Notebook.prototype.get_next_cell = function (cell) {
317 327 var result = null;
318 328 var index = this.find_cell_index(cell);
319 329 if (index !== null && index < this.ncells()) {
320 330 result = this.get_cell(index+1);
321 331 }
322 332 return result;
323 333 }
324 334
325 335
326 336 Notebook.prototype.get_prev_cell = function (cell) {
327 337 var result = null;
328 338 var index = this.find_cell_index(cell);
329 339 if (index !== null && index > 1) {
330 340 result = this.get_cell(index-1);
331 341 }
332 342 return result;
333 343 }
334 344
335 345 Notebook.prototype.find_cell_index = function (cell) {
336 346 var result = null;
337 347 this.get_cell_elements().filter(function (index) {
338 348 if ($(this).data("cell") === cell) {
339 349 result = index;
340 350 };
341 351 });
342 352 return result;
343 353 };
344 354
345 355
346 356 Notebook.prototype.index_or_selected = function (index) {
347 357 var i;
348 358 if (index === undefined || index === null) {
349 359 i = this.get_selected_index();
350 360 if (i === null) {
351 361 i = 0;
352 362 }
353 363 } else {
354 364 i = index;
355 365 }
356 366 return i;
357 367 };
358 368
359 369
360 370 Notebook.prototype.get_selected_cell = function () {
361 371 var index = this.get_selected_index();
362 372 return this.get_cell(index);
363 373 };
364 374
365 375
366 376 Notebook.prototype.is_valid_cell_index = function (index) {
367 377 if (index !== null && index >= 0 && index < this.ncells()) {
368 378 return true;
369 379 } else {
370 380 return false;
371 381 };
372 382 }
373 383
374 384 Notebook.prototype.get_selected_index = function () {
375 385 var result = null;
376 386 this.get_cell_elements().filter(function (index) {
377 387 if ($(this).data("cell").selected === true) {
378 388 result = index;
379 389 };
380 390 });
381 391 return result;
382 392 };
383 393
384 394
385 395 Notebook.prototype.cell_for_msg = function (msg_id) {
386 396 var cell_id = this.msg_cell_map[msg_id];
387 397 var result = null;
388 398 this.get_cell_elements().filter(function (index) {
389 399 cell = $(this).data("cell");
390 400 if (cell.cell_id === cell_id) {
391 401 result = cell;
392 402 };
393 403 });
394 404 return result;
395 405 };
396 406
397 407
398 408 // Cell selection.
399 409
400 410 Notebook.prototype.select = function (index) {
401 411 if (index !== undefined && index >= 0 && index < this.ncells()) {
402 412 sindex = this.get_selected_index()
403 413 if (sindex !== null && index !== sindex) {
404 414 this.get_cell(sindex).unselect();
405 415 };
406 416 var cell = this.get_cell(index)
407 417 cell.select();
408 418 if (cell.cell_type === 'heading') {
409 419 $([IPython.events]).trigger('selected_cell_type_changed.Notebook',
410 420 {'cell_type':cell.cell_type,level:cell.level}
411 421 );
412 422 } else {
413 423 $([IPython.events]).trigger('selected_cell_type_changed.Notebook',
414 424 {'cell_type':cell.cell_type}
415 425 );
416 426 };
417 427 };
418 428 return this;
419 429 };
420 430
421 431
422 432 Notebook.prototype.select_next = function () {
423 433 var index = this.get_selected_index();
424 434 if (index !== null && index >= 0 && (index+1) < this.ncells()) {
425 435 this.select(index+1);
426 436 };
427 437 return this;
428 438 };
429 439
430 440
431 441 Notebook.prototype.select_prev = function () {
432 442 var index = this.get_selected_index();
433 443 if (index !== null && index >= 0 && (index-1) < this.ncells()) {
434 444 this.select(index-1);
435 445 };
436 446 return this;
437 447 };
438 448
439 449
440 450 // Cell movement
441 451
442 452 Notebook.prototype.move_cell_up = function (index) {
443 453 var i = this.index_or_selected();
444 454 if (i !== null && i < this.ncells() && i > 0) {
445 455 var pivot = this.get_cell_element(i-1);
446 456 var tomove = this.get_cell_element(i);
447 457 if (pivot !== null && tomove !== null) {
448 458 tomove.detach();
449 459 pivot.before(tomove);
450 460 this.select(i-1);
451 461 };
452 462 };
453 463 this.dirty = true;
454 464 return this;
455 465 };
456 466
457 467
458 468 Notebook.prototype.move_cell_down = function (index) {
459 469 var i = this.index_or_selected();
460 470 if (i !== null && i < (this.ncells()-1) && i >= 0) {
461 471 var pivot = this.get_cell_element(i+1);
462 472 var tomove = this.get_cell_element(i);
463 473 if (pivot !== null && tomove !== null) {
464 474 tomove.detach();
465 475 pivot.after(tomove);
466 476 this.select(i+1);
467 477 };
468 478 };
469 479 this.dirty = true;
470 480 return this;
471 481 };
472 482
473 483
474 484 Notebook.prototype.sort_cells = function () {
475 485 // This is not working right now. Calling this will actually crash
476 486 // the browser. I think there is an infinite loop in here...
477 487 var ncells = this.ncells();
478 488 var sindex = this.get_selected_index();
479 489 var swapped;
480 490 do {
481 491 swapped = false;
482 492 for (var i=1; i<ncells; i++) {
483 493 current = this.get_cell(i);
484 494 previous = this.get_cell(i-1);
485 495 if (previous.input_prompt_number > current.input_prompt_number) {
486 496 this.move_cell_up(i);
487 497 swapped = true;
488 498 };
489 499 };
490 500 } while (swapped);
491 501 this.select(sindex);
492 502 return this;
493 503 };
494 504
495 505 // Insertion, deletion.
496 506
497 507 Notebook.prototype.delete_cell = function (index) {
498 508 var i = this.index_or_selected(index);
499 509 if (this.is_valid_cell_index(i)) {
500 510 var ce = this.get_cell_element(i);
501 511 ce.remove();
502 512 if (i === (this.ncells())) {
503 513 this.select(i-1);
504 514 } else {
505 515 this.select(i);
506 516 };
507 517 this.dirty = true;
508 518 };
509 519 return this;
510 520 };
511 521
512 522
513 523 Notebook.prototype.insert_cell_below = function (type, index) {
514 524 // type = ('code','html','markdown')
515 525 // index = cell index or undefined to insert below selected
516 526 index = this.index_or_selected(index);
517 527 var cell = null;
518 528 if (this.ncells() === 0 || this.is_valid_cell_index(index)) {
519 529 if (type === 'code') {
520 530 cell = new IPython.CodeCell(this);
521 531 cell.set_input_prompt();
522 532 } else if (type === 'markdown') {
523 533 cell = new IPython.MarkdownCell(this);
524 534 } else if (type === 'html') {
525 535 cell = new IPython.HTMLCell(this);
526 536 } else if (type === 'raw') {
527 537 cell = new IPython.RawCell(this);
528 538 } else if (type === 'heading') {
529 539 cell = new IPython.HeadingCell(this);
530 540 };
531 541 if (cell !== null) {
532 542 if (this.ncells() === 0) {
533 543 this.element.find('div.end_space').before(cell.element);
534 544 } else if (this.is_valid_cell_index(index)) {
535 545 this.get_cell_element(index).after(cell.element);
536 546 };
537 547 cell.render();
538 548 this.select(this.find_cell_index(cell));
539 549 this.dirty = true;
540 550 return cell;
541 551 };
542 552 };
543 553 return cell;
544 554 };
545 555
546 556
547 557 Notebook.prototype.insert_cell_above = function (type, index) {
548 558 // type = ('code','html','markdown')
549 559 // index = cell index or undefined to insert above selected
550 560 index = this.index_or_selected(index);
551 561 var cell = null;
552 562 if (this.ncells() === 0 || this.is_valid_cell_index(index)) {
553 563 if (type === 'code') {
554 564 cell = new IPython.CodeCell(this);
555 565 cell.set_input_prompt();
556 566 } else if (type === 'markdown') {
557 567 cell = new IPython.MarkdownCell(this);
558 568 } else if (type === 'html') {
559 569 cell = new IPython.HTMLCell(this);
560 570 } else if (type === 'raw') {
561 571 cell = new IPython.RawCell(this);
562 572 } else if (type === 'heading') {
563 573 cell = new IPython.HeadingCell(this);
564 574 };
565 575 if (cell !== null) {
566 576 if (this.ncells() === 0) {
567 577 this.element.find('div.end_space').before(cell.element);
568 578 } else if (this.is_valid_cell_index(index)) {
569 579 this.get_cell_element(index).before(cell.element);
570 580 };
571 581 cell.render();
572 582 this.select(this.find_cell_index(cell));
573 583 this.dirty = true;
574 584 return cell;
575 585 };
576 586 };
577 587 return cell;
578 588 };
579 589
580 590
581 591 Notebook.prototype.to_code = function (index) {
582 592 var i = this.index_or_selected(index);
583 593 if (this.is_valid_cell_index(i)) {
584 594 var source_element = this.get_cell_element(i);
585 595 var source_cell = source_element.data("cell");
586 596 if (!(source_cell instanceof IPython.CodeCell)) {
587 597 target_cell = this.insert_cell_below('code',i);
588 598 var text = source_cell.get_text();
589 599 if (text === source_cell.placeholder) {
590 600 text = '';
591 601 }
592 602 target_cell.set_text(text);
593 603 source_element.remove();
594 604 this.dirty = true;
595 605 };
596 606 };
597 607 };
598 608
599 609
600 610 Notebook.prototype.to_markdown = function (index) {
601 611 var i = this.index_or_selected(index);
602 612 if (this.is_valid_cell_index(i)) {
603 613 var source_element = this.get_cell_element(i);
604 614 var source_cell = source_element.data("cell");
605 615 if (!(source_cell instanceof IPython.MarkdownCell)) {
606 616 target_cell = this.insert_cell_below('markdown',i);
607 617 var text = source_cell.get_text();
608 618 if (text === source_cell.placeholder) {
609 619 text = '';
610 620 };
611 621 // The edit must come before the set_text.
612 622 target_cell.edit();
613 623 target_cell.set_text(text);
614 624 source_element.remove();
615 625 this.dirty = true;
616 626 };
617 627 };
618 628 };
619 629
620 630
621 631 Notebook.prototype.to_html = function (index) {
622 632 var i = this.index_or_selected(index);
623 633 if (this.is_valid_cell_index(i)) {
624 634 var source_element = this.get_cell_element(i);
625 635 var source_cell = source_element.data("cell");
626 636 var target_cell = null;
627 637 if (!(source_cell instanceof IPython.HTMLCell)) {
628 638 target_cell = this.insert_cell_below('html',i);
629 639 var text = source_cell.get_text();
630 640 if (text === source_cell.placeholder) {
631 641 text = '';
632 642 };
633 643 // The edit must come before the set_text.
634 644 target_cell.edit();
635 645 target_cell.set_text(text);
636 646 source_element.remove();
637 647 this.dirty = true;
638 648 };
639 649 };
640 650 };
641 651
642 652
643 653 Notebook.prototype.to_raw = function (index) {
644 654 var i = this.index_or_selected(index);
645 655 if (this.is_valid_cell_index(i)) {
646 656 var source_element = this.get_cell_element(i);
647 657 var source_cell = source_element.data("cell");
648 658 var target_cell = null;
649 659 if (!(source_cell instanceof IPython.RawCell)) {
650 660 target_cell = this.insert_cell_below('raw',i);
651 661 var text = source_cell.get_text();
652 662 if (text === source_cell.placeholder) {
653 663 text = '';
654 664 };
655 665 // The edit must come before the set_text.
656 666 target_cell.edit();
657 667 target_cell.set_text(text);
658 668 source_element.remove();
659 669 this.dirty = true;
660 670 };
661 671 };
662 672 };
663 673
664 674
665 675 Notebook.prototype.to_heading = function (index, level) {
666 676 level = level || 1;
667 677 var i = this.index_or_selected(index);
668 678 if (this.is_valid_cell_index(i)) {
669 679 var source_element = this.get_cell_element(i);
670 680 var source_cell = source_element.data("cell");
671 681 var target_cell = null;
672 682 if (source_cell instanceof IPython.HeadingCell) {
673 683 source_cell.set_level(level);
674 684 } else {
675 685 target_cell = this.insert_cell_below('heading',i);
676 686 var text = source_cell.get_text();
677 687 if (text === source_cell.placeholder) {
678 688 text = '';
679 689 };
680 690 // The edit must come before the set_text.
681 691 target_cell.set_level(level);
682 692 target_cell.edit();
683 693 target_cell.set_text(text);
684 694 source_element.remove();
685 695 this.dirty = true;
686 696 };
687 697 $([IPython.events]).trigger('selected_cell_type_changed.Notebook',
688 698 {'cell_type':'heading',level:level}
689 699 );
690 700 };
691 701 };
692 702
693 703
694 704 // Cut/Copy/Paste
695 705
696 706 Notebook.prototype.enable_paste = function () {
697 707 var that = this;
698 708 if (!this.paste_enabled) {
699 709 $('#paste_cell').removeClass('ui-state-disabled')
700 710 .on('click', function () {that.paste_cell();});
701 711 $('#paste_cell_above').removeClass('ui-state-disabled')
702 712 .on('click', function () {that.paste_cell_above();});
703 713 $('#paste_cell_below').removeClass('ui-state-disabled')
704 714 .on('click', function () {that.paste_cell_below();});
705 715 this.paste_enabled = true;
706 716 };
707 717 };
708 718
709 719
710 720 Notebook.prototype.disable_paste = function () {
711 721 if (this.paste_enabled) {
712 722 $('#paste_cell').addClass('ui-state-disabled').off('click');
713 723 $('#paste_cell_above').addClass('ui-state-disabled').off('click');
714 724 $('#paste_cell_below').addClass('ui-state-disabled').off('click');
715 725 this.paste_enabled = false;
716 726 };
717 727 };
718 728
719 729
720 730 Notebook.prototype.cut_cell = function () {
721 731 this.copy_cell();
722 732 this.delete_cell();
723 733 }
724 734
725 735 Notebook.prototype.copy_cell = function () {
726 736 var cell = this.get_selected_cell();
727 737 this.clipboard = cell.toJSON();
728 738 this.enable_paste();
729 739 };
730 740
731 741
732 742 Notebook.prototype.paste_cell = function () {
733 743 if (this.clipboard !== null && this.paste_enabled) {
734 744 var cell_data = this.clipboard;
735 745 var new_cell = this.insert_cell_above(cell_data.cell_type);
736 746 new_cell.fromJSON(cell_data);
737 747 old_cell = this.get_next_cell(new_cell);
738 748 this.delete_cell(this.find_cell_index(old_cell));
739 749 this.select(this.find_cell_index(new_cell));
740 750 };
741 751 };
742 752
743 753
744 754 Notebook.prototype.paste_cell_above = function () {
745 755 if (this.clipboard !== null && this.paste_enabled) {
746 756 var cell_data = this.clipboard;
747 757 var new_cell = this.insert_cell_above(cell_data.cell_type);
748 758 new_cell.fromJSON(cell_data);
749 759 };
750 760 };
751 761
752 762
753 763 Notebook.prototype.paste_cell_below = function () {
754 764 if (this.clipboard !== null && this.paste_enabled) {
755 765 var cell_data = this.clipboard;
756 766 var new_cell = this.insert_cell_below(cell_data.cell_type);
757 767 new_cell.fromJSON(cell_data);
758 768 };
759 769 };
760 770
761 771
762 772 // Split/merge
763 773
764 774 Notebook.prototype.split_cell = function () {
765 775 // Todo: implement spliting for other cell types.
766 776 var cell = this.get_selected_cell();
767 777 if (cell.is_splittable()) {
768 778 texta = cell.get_pre_cursor();
769 779 textb = cell.get_post_cursor();
770 780 if (cell instanceof IPython.CodeCell) {
771 781 cell.set_text(texta);
772 782 var new_cell = this.insert_cell_below('code');
773 783 new_cell.set_text(textb);
774 784 } else if (cell instanceof IPython.MarkdownCell) {
775 785 cell.set_text(texta);
776 786 cell.render();
777 787 var new_cell = this.insert_cell_below('markdown');
778 788 new_cell.edit(); // editor must be visible to call set_text
779 789 new_cell.set_text(textb);
780 790 new_cell.render();
781 791 } else if (cell instanceof IPython.HTMLCell) {
782 792 cell.set_text(texta);
783 793 cell.render();
784 794 var new_cell = this.insert_cell_below('html');
785 795 new_cell.edit(); // editor must be visible to call set_text
786 796 new_cell.set_text(textb);
787 797 new_cell.render();
788 798 };
789 799 };
790 800 };
791 801
792 802
793 803 Notebook.prototype.merge_cell_above = function () {
794 804 var index = this.get_selected_index();
795 805 var cell = this.get_cell(index);
796 806 if (index > 0) {
797 807 upper_cell = this.get_cell(index-1);
798 808 upper_text = upper_cell.get_text();
799 809 text = cell.get_text();
800 810 if (cell instanceof IPython.CodeCell) {
801 811 cell.set_text(upper_text+'\n'+text);
802 812 } else if (cell instanceof IPython.MarkdownCell || cell instanceof IPython.HTMLCell) {
803 813 cell.edit();
804 814 cell.set_text(upper_text+'\n'+text);
805 815 cell.render();
806 816 };
807 817 this.delete_cell(index-1);
808 818 this.select(this.find_cell_index(cell));
809 819 };
810 820 };
811 821
812 822
813 823 Notebook.prototype.merge_cell_below = function () {
814 824 var index = this.get_selected_index();
815 825 var cell = this.get_cell(index);
816 826 if (index < this.ncells()-1) {
817 827 lower_cell = this.get_cell(index+1);
818 828 lower_text = lower_cell.get_text();
819 829 text = cell.get_text();
820 830 if (cell instanceof IPython.CodeCell) {
821 831 cell.set_text(text+'\n'+lower_text);
822 832 } else if (cell instanceof IPython.MarkdownCell || cell instanceof IPython.HTMLCell) {
823 833 cell.edit();
824 834 cell.set_text(text+'\n'+lower_text);
825 835 cell.render();
826 836 };
827 837 this.delete_cell(index+1);
828 838 this.select(this.find_cell_index(cell));
829 839 };
830 840 };
831 841
832 842
833 843 // Cell collapsing and output clearing
834 844
835 845 Notebook.prototype.collapse = function (index) {
836 846 var i = this.index_or_selected(index);
837 847 this.get_cell(i).collapse();
838 848 this.dirty = true;
839 849 };
840 850
841 851
842 852 Notebook.prototype.expand = function (index) {
843 853 var i = this.index_or_selected(index);
844 854 this.get_cell(i).expand();
845 855 this.dirty = true;
846 856 };
847 857
848 858
849 859 Notebook.prototype.toggle_output = function (index) {
850 860 var i = this.index_or_selected(index);
851 861 this.get_cell(i).toggle_output();
852 862 this.dirty = true;
853 863 };
854 864
855 865
856 866 Notebook.prototype.set_timebeforetooltip = function (time) {
857 867 this.time_before_tooltip = time;
858 868 };
859 869
860 870
861 871 Notebook.prototype.set_tooltipontab = function (state) {
862 872 this.tooltip_on_tab = state;
863 873 };
864 874
865 875
866 876 Notebook.prototype.set_smartcompleter = function (state) {
867 877 this.smart_completer = state;
868 878 };
869 879
870 880
871 881 Notebook.prototype.clear_all_output = function () {
872 882 var ncells = this.ncells();
873 883 var cells = this.get_cells();
874 884 for (var i=0; i<ncells; i++) {
875 885 if (cells[i] instanceof IPython.CodeCell) {
876 886 cells[i].clear_output(true,true,true);
877 887 // Make all In[] prompts blank, as well
878 888 // TODO: make this configurable (via checkbox?)
879 889 cells[i].set_input_prompt();
880 890 }
881 891 };
882 892 this.dirty = true;
883 893 };
884 894
885 895
886 896 // Other cell functions: line numbers, ...
887 897
888 898 Notebook.prototype.cell_toggle_line_numbers = function() {
889 899 this.get_selected_cell().toggle_line_numbers();
890 900 };
891 901
892 902 // Kernel related things
893 903
894 904 Notebook.prototype.start_kernel = function () {
895 905 this.kernel = new IPython.Kernel();
896 906 this.kernel.start(this.notebook_id, $.proxy(this.kernel_started, this));
897 907 };
898 908
899 909
900 910 Notebook.prototype.restart_kernel = function () {
901 911 var that = this;
902 912 var dialog = $('<div/>');
903 913 dialog.html('Do you want to restart the current kernel? You will lose all variables defined in it.');
904 914 $(document).append(dialog);
905 915 dialog.dialog({
906 916 resizable: false,
907 917 modal: true,
908 918 title: "Restart kernel or continue running?",
909 919 closeText: '',
910 920 buttons : {
911 921 "Restart": function () {
912 922 that.kernel.restart($.proxy(that.kernel_started, that));
913 923 $(this).dialog('close');
914 924 },
915 925 "Continue running": function () {
916 926 $(this).dialog('close');
917 927 }
918 928 }
919 929 });
920 930 };
921 931
922 932
923 933 Notebook.prototype.kernel_started = function () {
924 934 console.log("Kernel started: ", this.kernel.kernel_id);
925 935 this.kernel.shell_channel.onmessage = $.proxy(this.handle_shell_reply,this);
926 936 this.kernel.iopub_channel.onmessage = $.proxy(this.handle_iopub_reply,this);
927 937 };
928 938
929 939
930 940 Notebook.prototype.handle_shell_reply = function (e) {
931 941 reply = $.parseJSON(e.data);
932 942 var header = reply.header;
933 943 var content = reply.content;
934 944 var msg_type = header.msg_type;
935 945 // console.log(reply);
936 946 var cell = this.cell_for_msg(reply.parent_header.msg_id);
937 947 if (msg_type === "execute_reply") {
938 948 cell.set_input_prompt(content.execution_count);
939 949 cell.element.removeClass("running");
940 950 this.dirty = true;
941 951 } else if (msg_type === "complete_reply") {
942 952 cell.finish_completing(content.matched_text, content.matches);
943 953 } else if (msg_type === "object_info_reply"){
944 954 //console.log('back from object_info_request : ')
945 955 rep = reply.content;
946 956 if(rep.found)
947 957 {
948 958 cell.finish_tooltip(rep);
949 959 }
950 960 } else {
951 961 //console.log("unknown reply:"+msg_type);
952 962 }
953 963 // when having a rely from object_info_reply,
954 964 // no payload so no nned to handle it
955 965 if(typeof(content.payload)!='undefined') {
956 966 var payload = content.payload || [];
957 967 this.handle_payload(cell, payload);
958 968 }
959 969 };
960 970
961 971
962 972 Notebook.prototype.handle_payload = function (cell, payload) {
963 973 var l = payload.length;
964 974 for (var i=0; i<l; i++) {
965 975 if (payload[i].source === 'IPython.zmq.page.page') {
966 976 if (payload[i].text.trim() !== '') {
967 977 IPython.pager.clear();
968 978 IPython.pager.expand();
969 979 IPython.pager.append_text(payload[i].text);
970 980 }
971 981 } else if (payload[i].source === 'IPython.zmq.zmqshell.ZMQInteractiveShell.set_next_input') {
972 982 var index = this.find_cell_index(cell);
973 983 var new_cell = this.insert_cell_below('code',index);
974 984 new_cell.set_text(payload[i].text);
975 985 this.dirty = true;
976 986 }
977 987 };
978 988 };
979 989
980 990
981 991 Notebook.prototype.handle_iopub_reply = function (e) {
982 992 reply = $.parseJSON(e.data);
983 993 var content = reply.content;
984 994 // console.log(reply);
985 995 var msg_type = reply.header.msg_type;
986 996 var cell = this.cell_for_msg(reply.parent_header.msg_id);
987 997 if (msg_type !== 'status' && !cell){
988 998 // message not from this notebook, but should be attached to a cell
989 999 // console.log("Received IOPub message not caused by one of my cells");
990 1000 // console.log(reply);
991 1001 return;
992 1002 }
993 1003 var output_types = ['stream','display_data','pyout','pyerr'];
994 1004 if (output_types.indexOf(msg_type) >= 0) {
995 1005 this.handle_output(cell, msg_type, content);
996 1006 } else if (msg_type === 'status') {
997 1007 if (content.execution_state === 'busy') {
998 1008 $([IPython.events]).trigger('status_busy.Kernel');
999 1009 } else if (content.execution_state === 'idle') {
1000 1010 $([IPython.events]).trigger('status_idle.Kernel');
1001 1011 } else if (content.execution_state === 'dead') {
1002 1012 this.handle_status_dead();
1003 1013 };
1004 1014 } else if (msg_type === 'clear_output') {
1005 1015 cell.clear_output(content.stdout, content.stderr, content.other);
1006 1016 };
1007 1017 };
1008 1018
1009 1019
1010 1020 Notebook.prototype.handle_status_dead = function () {
1011 1021 var that = this;
1012 1022 this.kernel.stop_channels();
1013 1023 var dialog = $('<div/>');
1014 1024 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.');
1015 1025 $(document).append(dialog);
1016 1026 dialog.dialog({
1017 1027 resizable: false,
1018 1028 modal: true,
1019 1029 title: "Dead kernel",
1020 1030 buttons : {
1021 1031 "Restart": function () {
1022 1032 that.start_kernel();
1023 1033 $(this).dialog('close');
1024 1034 },
1025 1035 "Continue running": function () {
1026 1036 $(this).dialog('close');
1027 1037 }
1028 1038 }
1029 1039 });
1030 1040 };
1031 1041
1032 1042
1033 1043 Notebook.prototype.handle_output = function (cell, msg_type, content) {
1034 1044 var json = {};
1035 1045 json.output_type = msg_type;
1036 1046 if (msg_type === "stream") {
1037 1047 json.text = content.data;
1038 1048 json.stream = content.name;
1039 1049 } else if (msg_type === "display_data") {
1040 1050 json = this.convert_mime_types(json, content.data);
1041 1051 } else if (msg_type === "pyout") {
1042 1052 json.prompt_number = content.execution_count;
1043 1053 json = this.convert_mime_types(json, content.data);
1044 1054 } else if (msg_type === "pyerr") {
1045 1055 json.ename = content.ename;
1046 1056 json.evalue = content.evalue;
1047 1057 json.traceback = content.traceback;
1048 1058 };
1049 1059 // append with dynamic=true
1050 1060 cell.append_output(json, true);
1051 1061 this.dirty = true;
1052 1062 };
1053 1063
1054 1064
1055 1065 Notebook.prototype.convert_mime_types = function (json, data) {
1056 1066 if (data['text/plain'] !== undefined) {
1057 1067 json.text = data['text/plain'];
1058 1068 };
1059 1069 if (data['text/html'] !== undefined) {
1060 1070 json.html = data['text/html'];
1061 1071 };
1062 1072 if (data['image/svg+xml'] !== undefined) {
1063 1073 json.svg = data['image/svg+xml'];
1064 1074 };
1065 1075 if (data['image/png'] !== undefined) {
1066 1076 json.png = data['image/png'];
1067 1077 };
1068 1078 if (data['image/jpeg'] !== undefined) {
1069 1079 json.jpeg = data['image/jpeg'];
1070 1080 };
1071 1081 if (data['text/latex'] !== undefined) {
1072 1082 json.latex = data['text/latex'];
1073 1083 };
1074 1084 if (data['application/json'] !== undefined) {
1075 1085 json.json = data['application/json'];
1076 1086 };
1077 1087 if (data['application/javascript'] !== undefined) {
1078 1088 json.javascript = data['application/javascript'];
1079 1089 }
1080 1090 return json;
1081 1091 };
1082 1092
1083 1093
1084 1094 Notebook.prototype.execute_selected_cell = function (options) {
1085 1095 // add_new: should a new cell be added if we are at the end of the nb
1086 1096 // terminal: execute in terminal mode, which stays in the current cell
1087 1097 default_options = {terminal: false, add_new: true};
1088 1098 $.extend(default_options, options);
1089 1099 var that = this;
1090 1100 var cell = that.get_selected_cell();
1091 1101 var cell_index = that.find_cell_index(cell);
1092 1102 if (cell instanceof IPython.CodeCell) {
1093 1103 cell.clear_output(true, true, true);
1094 1104 cell.set_input_prompt('*');
1095 1105 cell.element.addClass("running");
1096 1106 var code = cell.get_text();
1097 1107 var msg_id = that.kernel.execute(cell.get_text());
1098 1108 that.msg_cell_map[msg_id] = cell.cell_id;
1099 1109 } else if (cell instanceof IPython.HTMLCell) {
1100 1110 cell.render();
1101 1111 }
1102 1112 if (default_options.terminal) {
1103 1113 cell.select_all();
1104 1114 } else {
1105 1115 if ((cell_index === (that.ncells()-1)) && default_options.add_new) {
1106 1116 that.insert_cell_below('code');
1107 1117 // If we are adding a new cell at the end, scroll down to show it.
1108 1118 that.scroll_to_bottom();
1109 1119 } else {
1110 1120 that.select(cell_index+1);
1111 1121 };
1112 1122 };
1113 1123 this.dirty = true;
1114 1124 };
1115 1125
1116 1126
1117 1127 Notebook.prototype.execute_all_cells = function () {
1118 1128 var ncells = this.ncells();
1119 1129 for (var i=0; i<ncells; i++) {
1120 1130 this.select(i);
1121 1131 this.execute_selected_cell({add_new:false});
1122 1132 };
1123 1133 this.scroll_to_bottom();
1124 1134 };
1125 1135
1126 1136
1127 1137 Notebook.prototype.request_tool_tip = function (cell,func) {
1128 1138 // Feel free to shorten this logic if you are better
1129 1139 // than me in regEx
1130 1140 // basicaly you shoul be able to get xxx.xxx.xxx from
1131 1141 // something(range(10), kwarg=smth) ; xxx.xxx.xxx( firstarg, rand(234,23), kwarg1=2,
1132 1142 // remove everything between matchin bracket (need to iterate)
1133 1143 matchBracket = /\([^\(\)]+\)/g;
1134 1144 oldfunc = func;
1135 1145 func = func.replace(matchBracket,"");
1136 1146 while( oldfunc != func )
1137 1147 {
1138 1148 oldfunc = func;
1139 1149 func = func.replace(matchBracket,"");
1140 1150 }
1141 1151 // remove everythin after last open bracket
1142 1152 endBracket = /\([^\(]*$/g;
1143 1153 func = func.replace(endBracket,"");
1144 1154 var re = /[a-zA-Z._]+$/g;
1145 1155 var msg_id = this.kernel.object_info_request(re.exec(func));
1146 1156 if(typeof(msg_id)!='undefined'){
1147 1157 this.msg_cell_map[msg_id] = cell.cell_id;
1148 1158 }
1149 1159 };
1150 1160
1151 1161 Notebook.prototype.complete_cell = function (cell, line, cursor_pos) {
1152 1162 var msg_id = this.kernel.complete(line, cursor_pos);
1153 1163 this.msg_cell_map[msg_id] = cell.cell_id;
1154 1164 };
1155 1165
1156 1166
1157 1167 // Persistance and loading
1158 1168
1159 1169 Notebook.prototype.get_notebook_id = function () {
1160 1170 return this.notebook_id;
1161 1171 };
1162 1172
1163 1173
1164 1174 Notebook.prototype.get_notebook_name = function () {
1165 1175 return this.notebook_name;
1166 1176 };
1167 1177
1168 1178
1169 1179 Notebook.prototype.set_notebook_name = function (name) {
1170 1180 this.notebook_name = name;
1171 1181 };
1172 1182
1173 1183
1174 1184 Notebook.prototype.test_notebook_name = function (nbname) {
1175 1185 nbname = nbname || '';
1176 1186 if (this.notebook_name_blacklist_re.test(nbname) == false && nbname.length>0) {
1177 1187 return true;
1178 1188 } else {
1179 1189 return false;
1180 1190 };
1181 1191 };
1182 1192
1183 1193
1184 1194 Notebook.prototype.fromJSON = function (data) {
1185 1195 var ncells = this.ncells();
1186 1196 var i;
1187 1197 for (i=0; i<ncells; i++) {
1188 1198 // Always delete cell 0 as they get renumbered as they are deleted.
1189 1199 this.delete_cell(0);
1190 1200 };
1191 1201 // Save the metadata and name.
1192 1202 this.metadata = data.metadata;
1193 1203 this.notebook_name = data.metadata.name;
1194 1204 // Only handle 1 worksheet for now.
1195 1205 var worksheet = data.worksheets[0];
1196 1206 if (worksheet !== undefined) {
1197 1207 var new_cells = worksheet.cells;
1198 1208 ncells = new_cells.length;
1199 1209 var cell_data = null;
1200 1210 var new_cell = null;
1201 1211 for (i=0; i<ncells; i++) {
1202 1212 cell_data = new_cells[i];
1203 1213 // VERSIONHACK: plaintext -> raw
1204 1214 // handle never-released plaintext name for raw cells
1205 1215 if (cell_data.cell_type === 'plaintext'){
1206 1216 cell_data.cell_type = 'raw';
1207 1217 }
1208 1218
1209 1219 new_cell = this.insert_cell_below(cell_data.cell_type);
1210 1220 new_cell.fromJSON(cell_data);
1211 1221 };
1212 1222 };
1213 1223 };
1214 1224
1215 1225
1216 1226 Notebook.prototype.toJSON = function () {
1217 1227 var cells = this.get_cells();
1218 1228 var ncells = cells.length;
1219 1229 cell_array = new Array(ncells);
1220 1230 for (var i=0; i<ncells; i++) {
1221 1231 cell_array[i] = cells[i].toJSON();
1222 1232 };
1223 1233 data = {
1224 1234 // Only handle 1 worksheet for now.
1225 1235 worksheets : [{cells:cell_array}],
1226 1236 metadata : this.metadata
1227 1237 };
1228 1238 return data;
1229 1239 };
1230 1240
1231 1241 Notebook.prototype.save_notebook = function () {
1232 1242 // We may want to move the name/id/nbformat logic inside toJSON?
1233 1243 var data = this.toJSON();
1234 1244 data.metadata.name = this.notebook_name;
1235 1245 data.nbformat = this.nbformat;
1236 1246 // We do the call with settings so we can set cache to false.
1237 1247 var settings = {
1238 1248 processData : false,
1239 1249 cache : false,
1240 1250 type : "PUT",
1241 1251 data : JSON.stringify(data),
1242 1252 headers : {'Content-Type': 'application/json'},
1243 1253 success : $.proxy(this.save_notebook_success,this),
1244 1254 error : $.proxy(this.save_notebook_error,this)
1245 1255 };
1246 1256 $([IPython.events]).trigger('notebook_saving.Notebook');
1247 1257 var url = $('body').data('baseProjectUrl') + 'notebooks/' + this.notebook_id;
1248 1258 $.ajax(url, settings);
1249 1259 };
1250 1260
1251 1261
1252 1262 Notebook.prototype.save_notebook_success = function (data, status, xhr) {
1253 1263 this.dirty = false;
1254 1264 $([IPython.events]).trigger('notebook_saved.Notebook');
1255 1265 };
1256 1266
1257 1267
1258 1268 Notebook.prototype.save_notebook_error = function (xhr, status, error_msg) {
1259 1269 $([IPython.events]).trigger('notebook_save_failed.Notebook');
1260 1270 };
1261 1271
1262 1272
1263 1273 Notebook.prototype.load_notebook = function (notebook_id) {
1264 1274 var that = this;
1265 1275 this.notebook_id = notebook_id;
1266 1276 // We do the call with settings so we can set cache to false.
1267 1277 var settings = {
1268 1278 processData : false,
1269 1279 cache : false,
1270 1280 type : "GET",
1271 1281 dataType : "json",
1272 1282 success : $.proxy(this.load_notebook_success,this),
1273 1283 error : $.proxy(this.load_notebook_error,this),
1274 1284 };
1275 1285 $([IPython.events]).trigger('notebook_loading.Notebook');
1276 1286 var url = $('body').data('baseProjectUrl') + 'notebooks/' + this.notebook_id;
1277 1287 $.ajax(url, settings);
1278 1288 };
1279 1289
1280 1290
1281 1291 Notebook.prototype.load_notebook_success = function (data, status, xhr) {
1282 1292 this.fromJSON(data);
1283 1293 if (this.ncells() === 0) {
1284 1294 this.insert_cell_below('code');
1285 1295 };
1286 1296 this.dirty = false;
1287 1297 if (! this.read_only) {
1288 1298 this.start_kernel();
1289 1299 }
1290 1300 this.select(0);
1291 1301 this.scroll_to_top();
1292 1302 if (data.orig_nbformat !== undefined && data.nbformat !== data.orig_nbformat) {
1293 1303 msg = "This notebook has been converted from an older " +
1294 1304 "notebook format (v"+data.orig_nbformat+") to the current notebook " +
1295 1305 "format (v"+data.nbformat+"). The next time you save this notebook, the " +
1296 1306 "newer notebook format will be used and older verions of IPython " +
1297 1307 "may not be able to read it. To keep the older version, close the " +
1298 1308 "notebook without saving it.";
1299 1309 var dialog = $('<div/>');
1300 1310 dialog.html(msg);
1301 1311 this.element.append(dialog);
1302 1312 dialog.dialog({
1303 1313 resizable: false,
1304 1314 modal: true,
1305 1315 title: "Notebook converted",
1306 1316 closeText: "",
1307 1317 close: function(event, ui) {$(this).dialog('destroy').remove();},
1308 1318 buttons : {
1309 1319 "OK": function () {
1310 1320 $(this).dialog('close');
1311 1321 }
1312 1322 },
1313 1323 width: 400
1314 1324 });
1315 1325 }
1316 1326 $([IPython.events]).trigger('notebook_loaded.Notebook');
1317 1327 };
1318 1328
1319 1329
1320 1330 Notebook.prototype.load_notebook_error = function (xhr, textStatus, errorThrow) {
1321 1331 if (xhr.status === 500) {
1322 1332 msg = "An error occurred while loading this notebook. Most likely " +
1323 1333 "this notebook is in a newer format than is supported by this " +
1324 1334 "version of IPython. This version can load notebook formats " +
1325 1335 "v"+this.nbformat+" or earlier.";
1326 1336 var dialog = $('<div/>');
1327 1337 dialog.html(msg);
1328 1338 this.element.append(dialog);
1329 1339 dialog.dialog({
1330 1340 resizable: false,
1331 1341 modal: true,
1332 1342 title: "Error loading notebook",
1333 1343 closeText: "",
1334 1344 close: function(event, ui) {$(this).dialog('destroy').remove();},
1335 1345 buttons : {
1336 1346 "OK": function () {
1337 1347 $(this).dialog('close');
1338 1348 }
1339 1349 },
1340 1350 width: 400
1341 1351 });
1342 1352 }
1343 1353 }
1344 1354
1345 1355 IPython.Notebook = Notebook;
1346 1356
1347 1357
1348 1358 return IPython;
1349 1359
1350 1360 }(IPython));
1351 1361
@@ -1,102 +1,123 b''
1 1 //----------------------------------------------------------------------------
2 2 // Copyright (C) 2008-2011 The IPython Development Team
3 3 //
4 4 // Distributed under the terms of the BSD License. The full license is in
5 5 // the file COPYING, distributed as part of this software.
6 6 //----------------------------------------------------------------------------
7 7
8 8 //============================================================================
9 9 // Pager
10 10 //============================================================================
11 11
12 12 var IPython = (function (IPython) {
13 13
14 14 var utils = IPython.utils;
15 15
16 16 var Pager = function (pager_selector, pager_splitter_selector) {
17 17 this.pager_element = $(pager_selector);
18 this.pager_splitter_element = $(pager_splitter_selector);
19 this.expanded = false;
18 var that = this;
20 19 this.percentage_height = 0.40;
20 this.pager_splitter_element = $(pager_splitter_selector)
21 .draggable({
22 containment: 'window',
23 axis:'y',
24 helper: null ,
25 drag: function(event,ui){
26 // recalculate the amount of space the pager should take
27 var pheight =(document.height-event.clientY-4);
28 var downprct = pheight/IPython.layout_manager.app_height();
29 downprct = Math.min(0.9,downprct);
30 if(downprct < 0.1) {
31 that.percentage_height = 0.1;
32 that.collapse({'duration':0});
33 } else if(downprct > 0.2) {
34 that.percentage_height = downprct;
35 that.expand({'duration':0});
36 }
37 IPython.layout_manager.do_resize();
38 }
39 });
40 this.expanded = false;
21 41 this.style();
22 42 this.bind_events();
23 43 };
24 44
25
26 45 Pager.prototype.style = function () {
27 46 this.pager_splitter_element.addClass('border-box-sizing ui-widget ui-state-default');
28 47 this.pager_element.addClass('border-box-sizing ui-widget');
29 this.pager_splitter_element.attr('title', 'Click to Show/Hide pager area');
48 this.pager_splitter_element.attr('title', 'Click to Show/Hide pager area, drag to Resize');
30 49 };
31 50
32 51
33 52 Pager.prototype.bind_events = function () {
34 53 var that = this;
35 54
36 this.pager_element.bind('collapse_pager', function () {
37 that.pager_element.hide('fast');
55 this.pager_element.bind('collapse_pager', function (event,extrap) {
56 time = (extrap != undefined) ? ((extrap.duration != undefined ) ? extrap.duration : 'fast') : 'fast';
57 that.pager_element.hide(time);
38 58 });
39 59
40 this.pager_element.bind('expand_pager', function () {
41 that.pager_element.show('fast');
60 this.pager_element.bind('expand_pager', function (event,extrap) {
61 time = (extrap != undefined) ? ((extrap.duration != undefined ) ? extrap.duration : 'fast') : 'fast';
62 that.pager_element.show(time);
42 63 });
43 64
44 65 this.pager_splitter_element.hover(
45 66 function () {
46 67 that.pager_splitter_element.addClass('ui-state-hover');
47 68 },
48 69 function () {
49 70 that.pager_splitter_element.removeClass('ui-state-hover');
50 71 }
51 72 );
52 73
53 74 this.pager_splitter_element.click(function () {
54 75 that.toggle();
55 76 });
56 77
57 78 };
58 79
59 80
60 Pager.prototype.collapse = function () {
81 Pager.prototype.collapse = function (extrap) {
61 82 if (this.expanded === true) {
62 this.pager_element.add($('div#notebook')).trigger('collapse_pager');
63 83 this.expanded = false;
84 this.pager_element.add($('div#notebook')).trigger('collapse_pager',extrap);
64 85 };
65 86 };
66 87
67 88
68 Pager.prototype.expand = function () {
89 Pager.prototype.expand = function (extrap) {
69 90 if (this.expanded !== true) {
70 this.pager_element.add($('div#notebook')).trigger('expand_pager');
71 91 this.expanded = true;
92 this.pager_element.add($('div#notebook')).trigger('expand_pager',extrap);
72 93 };
73 94 };
74 95
75 96
76 97 Pager.prototype.toggle = function () {
77 98 if (this.expanded === true) {
78 99 this.collapse();
79 100 } else {
80 101 this.expand();
81 102 };
82 103 };
83 104
84 105
85 106 Pager.prototype.clear = function (text) {
86 107 this.pager_element.empty();
87 108 };
88 109
89 110
90 111 Pager.prototype.append_text = function (text) {
91 112 var toinsert = $("<div/>").addClass("output_area output_stream");
92 113 toinsert.append($('<pre/>').html(utils.fixConsole(text)));
93 114 this.pager_element.append(toinsert);
94 115 };
95 116
96 117
97 118 IPython.Pager = Pager;
98 119
99 120 return IPython;
100 121
101 122 }(IPython));
102 123
General Comments 0
You need to be logged in to leave comments. Login now