##// END OF EJS Templates
Merge pull request #1361 from ellisonbg/nbissues...
Fernando Perez -
r6066:54c3e061 merge
parent child Browse files
Show More
@@ -0,0 +1,31 b''
1 //----------------------------------------------------------------------------
2 // Copyright (C) 2008-2011 The IPython Development Team
3 //
4 // Distributed under the terms of the BSD License. The full license is in
5 // the file COPYING, distributed as part of this software.
6 //----------------------------------------------------------------------------
7
8 //============================================================================
9 // Events
10 //============================================================================
11
12 // Give us an object to bind all events to. This object should be created
13 // before all other objects so it exists when others register event handlers.
14 // To trigger an event handler:
15 // $([IPython.events]).trigger('event.Namespace);
16 // To handle it:
17 // $([IPython.events]).on('event.Namespace',function () {});
18
19 var IPython = (function (IPython) {
20
21 var utils = IPython.utils;
22
23 var Events = function () {};
24
25 IPython.Events = Events;
26 IPython.events = new Events();
27
28 return IPython;
29
30 }(IPython));
31
@@ -0,0 +1,102 b''
1 //----------------------------------------------------------------------------
2 // Copyright (C) 2008-2011 The IPython Development Team
3 //
4 // Distributed under the terms of the BSD License. The full license is in
5 // the file COPYING, distributed as part of this software.
6 //----------------------------------------------------------------------------
7
8 //============================================================================
9 // Notification widget
10 //============================================================================
11
12 var IPython = (function (IPython) {
13
14 var utils = IPython.utils;
15
16
17 var NotificationWidget = function (selector) {
18 this.selector = selector;
19 this.timeout = null;
20 this.busy = false;
21 if (this.selector !== undefined) {
22 this.element = $(selector);
23 this.style();
24 this.bind_events();
25 }
26 };
27
28
29 NotificationWidget.prototype.style = function () {
30 this.element.addClass('ui-widget ui-widget-content ui-corner-all');
31 this.element.addClass('border-box-sizing');
32 };
33
34
35 NotificationWidget.prototype.bind_events = function () {
36 var that = this;
37 // Kernel events
38 $([IPython.events]).on('status_idle.Kernel',function () {
39 IPython.save_widget.update_document_title();
40 if (that.get_message() === 'Kernel busy') {
41 that.element.fadeOut(100, function () {
42 that.element.html('');
43 });
44 };
45 });
46 $([IPython.events]).on('status_busy.Kernel',function () {
47 window.document.title='(Busy) '+window.document.title;
48 that.set_message("Kernel busy");
49 });
50 $([IPython.events]).on('status_restarting.Kernel',function () {
51 that.set_message("Restarting kernel",500);
52 });
53 $([IPython.events]).on('status_interrupting.Kernel',function () {
54 that.set_message("Interrupting kernel",500);
55 });
56 // Notebook events
57 $([IPython.events]).on('notebook_loading.Notebook', function () {
58 that.set_message("Loading notebook",500);
59 });
60 $([IPython.events]).on('notebook_loaded.Notebook', function () {
61 that.set_message("Notebook loaded",500);
62 });
63 $([IPython.events]).on('notebook_saving.Notebook', function () {
64 that.set_message("Saving notebook",500);
65 });
66 $([IPython.events]).on('notebook_saved.Notebook', function () {
67 that.set_message("Notebook saved",500);
68 });
69 $([IPython.events]).on('notebook_save_failed.Notebook', function () {
70 that.set_message("Notebook save failed",500);
71 });
72 };
73
74
75 NotificationWidget.prototype.set_message = function (msg, timeout) {
76 var that = this;
77 this.element.html(msg);
78 this.element.fadeIn(100);
79 if (this.timeout !== null) {
80 clearTimeout(this.timeout);
81 this.timeout = null;
82 };
83 if (timeout !== undefined) {
84 this.timeout = setTimeout(function () {
85 that.element.fadeOut(100, function () {that.element.html('');});
86 that.timeout = null;
87 }, timeout)
88 };
89 };
90
91
92 NotificationWidget.prototype.get_message = function () {
93 return this.element.html();
94 };
95
96
97 IPython.NotificationWidget = NotificationWidget;
98
99 return IPython;
100
101 }(IPython));
102
@@ -298,6 +298,13 b' class HTML(DisplayObject):'
298 class Math(DisplayObject):
298 class Math(DisplayObject):
299
299
300 def _repr_latex_(self):
300 def _repr_latex_(self):
301 s = self.data.strip('$')
302 return "$$%s$$" % s
303
304
305 class Latex(DisplayObject):
306
307 def _repr_latex_(self):
301 return self.data
308 return self.data
302
309
303
310
@@ -524,7 +524,8 b' class LatexFormatter(BaseFormatter):'
524 this.
524 this.
525
525
526 The return value of this formatter should be a valid LaTeX equation,
526 The return value of this formatter should be a valid LaTeX equation,
527 enclosed in either ```$``` or ```$$```.
527 enclosed in either ```$```, ```$$``` or another LaTeX equation
528 environment.
528 """
529 """
529 format_type = Unicode('text/latex')
530 format_type = Unicode('text/latex')
530
531
@@ -58,9 +58,10 b' def print_png(o):'
58
58
59 def print_latex(o):
59 def print_latex(o):
60 """A function to generate the latex representation of sympy expressions."""
60 """A function to generate the latex representation of sympy expressions."""
61 s = latex(o, mode='equation', itex=True)
61 s = latex(o, mode='plain')
62 s = s.replace('\\dag','\\dagger')
62 s = s.replace('\\dag','\\dagger')
63 return s
63 s = s.strip('$')
64 return '$$%s$$' % s
64
65
65
66
66 _loaded = False
67 _loaded = False
@@ -5,7 +5,7 b''
5 We carry a mostly unmodified copy of CodeMirror. The current version we use
5 We carry a mostly unmodified copy of CodeMirror. The current version we use
6 is (*please update this information when updating versions*)::
6 is (*please update this information when updating versions*)::
7
7
8 CodeMirror 7f93a5c
8 CodeMirror c813c94
9
9
10 The only changes we've applied so far are these::
10 The only changes we've applied so far are these::
11
11
@@ -149,8 +149,10 b' var CodeMirror = (function() {'
149 else if (option == "theme") themeChanged();
149 else if (option == "theme") themeChanged();
150 else if (option == "lineWrapping" && oldVal != value) operation(wrappingChanged)();
150 else if (option == "lineWrapping" && oldVal != value) operation(wrappingChanged)();
151 else if (option == "tabSize") operation(tabsChanged)();
151 else if (option == "tabSize") operation(tabsChanged)();
152 if (option == "lineNumbers" || option == "gutter" || option == "firstLineNumber" || option == "theme")
152 if (option == "lineNumbers" || option == "gutter" || option == "firstLineNumber" || option == "theme") {
153 gutterChanged();
153 updateDisplay(true);
154 updateDisplay(true);
155 }
154 },
156 },
155 getOption: function(option) {return options[option];},
157 getOption: function(option) {return options[option];},
156 undo: operation(undo),
158 undo: operation(undo),
@@ -278,8 +280,8 b' var CodeMirror = (function() {'
278 return index;
280 return index;
279 },
281 },
280 scrollTo: function(x, y) {
282 scrollTo: function(x, y) {
281 if (x != null) scroller.scrollTop = x;
283 if (x != null) scroller.scrollLeft = x;
282 if (y != null) scroller.scrollLeft = y;
284 if (y != null) scroller.scrollTop = y;
283 updateDisplay([]);
285 updateDisplay([]);
284 },
286 },
285
287
@@ -440,10 +442,10 b' var CodeMirror = (function() {'
440 try {
442 try {
441 var text = e.dataTransfer.getData("Text");
443 var text = e.dataTransfer.getData("Text");
442 if (text) {
444 if (text) {
443 var end = replaceRange(text, pos, pos);
445 var curFrom = sel.from, curTo = sel.to;
444 var curFrom = sel.from, curTo = sel.to;
446 setSelectionUser(pos, pos);
445 setSelectionUser(pos, end);
446 if (draggingText) replaceRange("", curFrom, curTo);
447 if (draggingText) replaceRange("", curFrom, curTo);
448 replaceSelection(text);
447 focusInput();
449 focusInput();
448 }
450 }
449 }
451 }
@@ -511,9 +513,9 b' var CodeMirror = (function() {'
511 }
513 }
512 }
514 }
513 function onKeyPress(e) {
515 function onKeyPress(e) {
516 if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return;
514 var keyCode = e_prop(e, "keyCode"), charCode = e_prop(e, "charCode");
517 var keyCode = e_prop(e, "keyCode"), charCode = e_prop(e, "charCode");
515 if (window.opera && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;}
518 if (window.opera && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;}
516 if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return;
517 if (window.opera && !e.which && handleKeyBinding(e)) return;
519 if (window.opera && !e.which && handleKeyBinding(e)) return;
518 if (options.electricChars && mode.electricChars && options.smartIndent && !options.readOnly) {
520 if (options.electricChars && mode.electricChars && options.smartIndent && !options.readOnly) {
519 var ch = String.fromCharCode(charCode == null ? keyCode : charCode);
521 var ch = String.fromCharCode(charCode == null ? keyCode : charCode);
@@ -565,20 +567,22 b' var CodeMirror = (function() {'
565 }
567 }
566 updateLinesNoUndo(from, to, newText, selFrom, selTo);
568 updateLinesNoUndo(from, to, newText, selFrom, selTo);
567 }
569 }
568 function unredoHelper(from, to) {
570 function unredoHelper(from, to, dir) {
569 var change = from.pop();
571 var set = from.pop(), len = set ? set.length : 0, out = [];
570 if (change) {
572 for (var i = dir > 0 ? 0 : len - 1, e = dir > 0 ? len : -1; i != e; i += dir) {
573 var change = set[i];
571 var replaced = [], end = change.start + change.added;
574 var replaced = [], end = change.start + change.added;
572 doc.iter(change.start, end, function(line) { replaced.push(line.text); });
575 doc.iter(change.start, end, function(line) { replaced.push(line.text); });
573 to.push({start: change.start, added: change.old.length, old: replaced});
576 out.push({start: change.start, added: change.old.length, old: replaced});
574 var pos = clipPos({line: change.start + change.old.length - 1,
577 var pos = clipPos({line: change.start + change.old.length - 1,
575 ch: editEnd(replaced[replaced.length-1], change.old[change.old.length-1])});
578 ch: editEnd(replaced[replaced.length-1], change.old[change.old.length-1])});
576 updateLinesNoUndo({line: change.start, ch: 0}, {line: end - 1, ch: getLine(end-1).text.length}, change.old, pos, pos);
579 updateLinesNoUndo({line: change.start, ch: 0}, {line: end - 1, ch: getLine(end-1).text.length}, change.old, pos, pos);
577 updateInput = true;
578 }
580 }
581 updateInput = true;
582 to.push(out);
579 }
583 }
580 function undo() {unredoHelper(history.done, history.undone);}
584 function undo() {unredoHelper(history.done, history.undone, -1);}
581 function redo() {unredoHelper(history.undone, history.done);}
585 function redo() {unredoHelper(history.undone, history.done, 1);}
582
586
583 function updateLinesNoUndo(from, to, newText, selFrom, selTo) {
587 function updateLinesNoUndo(from, to, newText, selFrom, selTo) {
584 if (suppressEdits) return;
588 if (suppressEdits) return;
@@ -780,7 +784,7 b' var CodeMirror = (function() {'
780 if (!posEq(sel.from, sel.to)) {
784 if (!posEq(sel.from, sel.to)) {
781 prevInput = "";
785 prevInput = "";
782 input.value = getSelection();
786 input.value = getSelection();
783 input.select();
787 selectInput(input);
784 } else if (user) prevInput = input.value = "";
788 } else if (user) prevInput = input.value = "";
785 }
789 }
786
790
@@ -1537,7 +1541,7 b' var CodeMirror = (function() {'
1537 leaveInputAlone = true;
1541 leaveInputAlone = true;
1538 var val = input.value = getSelection();
1542 var val = input.value = getSelection();
1539 focusInput();
1543 focusInput();
1540 input.select();
1544 selectInput(input);
1541 function rehide() {
1545 function rehide() {
1542 var newVal = splitLines(input.value).join("\n");
1546 var newVal = splitLines(input.value).join("\n");
1543 if (newVal != val) operation(replaceSelection)(newVal, "end");
1547 if (newVal != val) operation(replaceSelection)(newVal, "end");
@@ -2551,11 +2555,13 b' var CodeMirror = (function() {'
2551 History.prototype = {
2555 History.prototype = {
2552 addChange: function(start, added, old) {
2556 addChange: function(start, added, old) {
2553 this.undone.length = 0;
2557 this.undone.length = 0;
2554 var time = +new Date, last = this.done[this.done.length - 1];
2558 var time = +new Date, cur = this.done[this.done.length - 1], last = cur && cur[cur.length - 1];
2555 if (time - this.time > 400 || !last ||
2559 var dtime = time - this.time;
2556 last.start > start + added || last.start + last.added < start - last.added + last.old.length)
2560 if (dtime > 400 || !last) {
2557 this.done.push({start: start, added: added, old: old});
2561 this.done.push([{start: start, added: added, old: old}]);
2558 else {
2562 } else if (last.start > start + added || last.start + last.added < start - last.added + last.old.length) {
2563 cur.push({start: start, added: added, old: old});
2564 } else {
2559 var oldoff = 0;
2565 var oldoff = 0;
2560 if (start < last.start) {
2566 if (start < last.start) {
2561 for (var i = last.start - start - 1; i >= 0; --i)
2567 for (var i = last.start - start - 1; i >= 0; --i)
@@ -15,7 +15,7 b' CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {'
15
15
16 var hrRE = /^[*-=_]/
16 var hrRE = /^[*-=_]/
17 , ulRE = /^[*-+]\s+/
17 , ulRE = /^[*-+]\s+/
18 , olRE = /^[0-9]\.\s+/
18 , olRE = /^[0-9]+\.\s+/
19 , headerRE = /^(?:\={3,}|-{3,})$/
19 , headerRE = /^(?:\={3,}|-{3,})$/
20 , codeRE = /^(k:\t|\s{4,})/
20 , codeRE = /^(k:\t|\s{4,})/
21 , textRE = /^[^\[*_\\<>`]+/;
21 , textRE = /^[^\[*_\\<>`]+/;
@@ -213,6 +213,10 b' CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {'
213
213
214 token: function(stream, state) {
214 token: function(stream, state) {
215 if (stream.sol()) {
215 if (stream.sol()) {
216 // Reset EM state
217 state.em = false;
218 // Reset STRONG state
219 state.strong = false;
216 state.f = state.block;
220 state.f = state.block;
217 var previousIndentation = state.indentation
221 var previousIndentation = state.indentation
218 , currentIndentation = 0;
222 , currentIndentation = 0;
@@ -55,6 +55,19 b' span#notebook_name {'
55 margin: 0.3em 0;
55 margin: 0.3em 0;
56 }
56 }
57
57
58 #menubar_container {
59 position: relative;
60 }
61
62 #notification {
63 position: absolute;
64 right: 3px;
65 top: 3px;
66 height: 25px;
67 padding: 3px 6px;
68 z-index: 10;
69 }
70
58 #toolbar {
71 #toolbar {
59 /* Initially hidden to prevent FLOUC */
72 /* Initially hidden to prevent FLOUC */
60 display: none;
73 display: none;
@@ -71,31 +84,6 b' span#quick_help_area {'
71 margin: 0px 0px 0px 0px;
84 margin: 0px 0px 0px 0px;
72 }
85 }
73
86
74 span#kernel_status {
75 position: absolute;
76 padding: 8px 5px 5px 5px;
77 right: 10px;
78 font-weight: bold;
79 }
80
81
82 .status_idle {
83 color: gray;
84 visibility: hidden;
85 }
86
87 .status_busy {
88 color: red;
89 }
90
91 .status_restarting {
92 color: black;
93 }
94
95 #kernel_persist {
96 float: right;
97 }
98
99 .help_string {
87 .help_string {
100 float: right;
88 float: right;
101 width: 170px;
89 width: 170px;
@@ -142,6 +142,16 b' var IPython = (function (IPython) {'
142 };
142 };
143
143
144
144
145 Cell.prototype.toggle_line_numbers = function () {
146 if (this.code_mirror.getOption('lineNumbers') == false) {
147 this.code_mirror.setOption('lineNumbers', true);
148 } else {
149 this.code_mirror.setOption('lineNumbers', false);
150 }
151 this.code_mirror.refresh();
152 };
153
154
145 IPython.Cell = Cell;
155 IPython.Cell = Cell;
146
156
147 return IPython;
157 return IPython;
@@ -79,11 +79,11 b' var IPython = (function (IPython) {'
79 var that = this;
79 var that = this;
80 // whatever key is pressed, first, cancel the tooltip request before
80 // whatever key is pressed, first, cancel the tooltip request before
81 // they are sent, and remove tooltip if any
81 // they are sent, and remove tooltip if any
82 if(event.type === 'keydown' ){
82 if(event.type === 'keydown' ) {
83 that.remove_and_cancel_tooltip();
83 that.remove_and_cancel_tooltip();
84 }
84 };
85
85
86
86
87 if (event.keyCode === 13 && (event.shiftKey || event.ctrlKey)) {
87 if (event.keyCode === 13 && (event.shiftKey || event.ctrlKey)) {
88 // Always ignore shift-enter in CodeMirror as we handle it.
88 // Always ignore shift-enter in CodeMirror as we handle it.
89 return true;
89 return true;
@@ -123,6 +123,10 b' var IPython = (function (IPython) {'
123 return false;
123 return false;
124 } else if ((pre_cursor.substr(-1) === "("|| pre_cursor.substr(-1) === " ") && tooltip_on_tab ) {
124 } else if ((pre_cursor.substr(-1) === "("|| pre_cursor.substr(-1) === " ") && tooltip_on_tab ) {
125 that.request_tooltip_after_time(pre_cursor,0);
125 that.request_tooltip_after_time(pre_cursor,0);
126 // Prevent the event from bubbling up.
127 event.stop();
128 // Prevent CodeMirror from handling the tab.
129 return true;
126 } else {
130 } else {
127 pre_cursor.trim();
131 pre_cursor.trim();
128 // Autocomplete the current line.
132 // Autocomplete the current line.
@@ -132,7 +136,7 b' var IPython = (function (IPython) {'
132 this.completion_cursor = cur;
136 this.completion_cursor = cur;
133 IPython.notebook.complete_cell(this, line, cur.ch);
137 IPython.notebook.complete_cell(this, line, cur.ch);
134 return true;
138 return true;
135 }
139 };
136 } else if (event.keyCode === 8 && event.type == 'keydown') {
140 } else if (event.keyCode === 8 && event.type == 'keydown') {
137 // If backspace and the line ends with 4 spaces, remove them.
141 // If backspace and the line ends with 4 spaces, remove them.
138 var cur = editor.getCursor();
142 var cur = editor.getCursor();
@@ -147,13 +151,8 b' var IPython = (function (IPython) {'
147 return true;
151 return true;
148 } else {
152 } else {
149 return false;
153 return false;
150 }
154 };
151 } else if (event.keyCode === 76 && event.ctrlKey && event.shiftKey
155 } else {
152 && event.type == 'keydown') {
153 // toggle line numbers with Ctrl-Shift-L
154 this.toggle_line_numbers();
155 }
156 else {
157 // keypress/keyup also trigger on TAB press, and we don't want to
156 // keypress/keyup also trigger on TAB press, and we don't want to
158 // use those to disable tab completion.
157 // use those to disable tab completion.
159 if (this.is_completing && event.keyCode !== 9) {
158 if (this.is_completing && event.keyCode !== 9) {
@@ -162,8 +161,8 b' var IPython = (function (IPython) {'
162 if (ed_cur.line !== cc_cur.line || ed_cur.ch !== cc_cur.ch) {
161 if (ed_cur.line !== cc_cur.line || ed_cur.ch !== cc_cur.ch) {
163 this.is_completing = false;
162 this.is_completing = false;
164 this.completion_cursor = null;
163 this.completion_cursor = null;
165 }
164 };
166 }
165 };
167 return false;
166 return false;
168 };
167 };
169 return false;
168 return false;
@@ -545,16 +544,6 b' var IPython = (function (IPython) {'
545 };
544 };
546
545
547
546
548 CodeCell.prototype.toggle_line_numbers = function () {
549 if (this.code_mirror.getOption('lineNumbers') == false) {
550 this.code_mirror.setOption('lineNumbers', true);
551 } else {
552 this.code_mirror.setOption('lineNumbers', false);
553 }
554 this.code_mirror.refresh();
555 };
556
557
558 CodeCell.prototype.select = function () {
547 CodeCell.prototype.select = function () {
559 IPython.Cell.prototype.select.apply(this);
548 IPython.Cell.prototype.select.apply(this);
560 this.code_mirror.refresh();
549 this.code_mirror.refresh();
@@ -62,7 +62,7 b' var IPython = (function (IPython) {'
62
62
63
63
64 Kernel.prototype.restart = function (callback) {
64 Kernel.prototype.restart = function (callback) {
65 IPython.kernel_status_widget.status_restarting();
65 $([IPython.events]).trigger('status_restarting.Kernel');
66 var url = this.kernel_url + "/restart";
66 var url = this.kernel_url + "/restart";
67 var that = this;
67 var that = this;
68 if (this.running) {
68 if (this.running) {
@@ -84,20 +84,19 b' var IPython = (function (IPython) {'
84 this.kernel_url = this.base_url + "/" + this.kernel_id;
84 this.kernel_url = this.base_url + "/" + this.kernel_id;
85 this.start_channels();
85 this.start_channels();
86 callback();
86 callback();
87 IPython.kernel_status_widget.status_idle();
88 };
87 };
89
88
90 Kernel.prototype._websocket_closed = function(ws_url, early){
89 Kernel.prototype._websocket_closed = function(ws_url, early){
91 var msg;
90 var msg;
92 var parent_item = $('body');
91 var parent_item = $('body');
93 if (early) {
92 if (early) {
94 msg = "Websocket connection to " + ws_url + " could not be established.<br/>" +
93 msg = "Websocket connection to " + ws_url + " could not be established." +
95 " You will NOT be able to run code.<br/>" +
94 " You will NOT be able to run code." +
96 " Your browser may not be compatible with the websocket version in the server," +
95 " Your browser may not be compatible with the websocket version in the server," +
97 " or if the url does not look right, there could be an error in the" +
96 " or if the url does not look right, there could be an error in the" +
98 " server's configuration.";
97 " server's configuration.";
99 } else {
98 } else {
100 msg = "Websocket connection closed unexpectedly.<br/>" +
99 msg = "Websocket connection closed unexpectedly." +
101 " The kernel will no longer be responsive.";
100 " The kernel will no longer be responsive.";
102 }
101 }
103 var dialog = $('<div/>');
102 var dialog = $('<div/>');
@@ -107,8 +106,10 b' var IPython = (function (IPython) {'
107 resizable: false,
106 resizable: false,
108 modal: true,
107 modal: true,
109 title: "Websocket closed",
108 title: "Websocket closed",
109 closeText: "",
110 close: function(event, ui) {$(this).dialog('destroy').remove();},
110 buttons : {
111 buttons : {
111 "Okay": function () {
112 "OK": function () {
112 $(this).dialog('close');
113 $(this).dialog('close');
113 }
114 }
114 }
115 }
@@ -211,6 +212,7 b' var IPython = (function (IPython) {'
211
212
212 Kernel.prototype.interrupt = function () {
213 Kernel.prototype.interrupt = function () {
213 if (this.running) {
214 if (this.running) {
215 $([IPython.events]).trigger('status_interrupting.Kernel');
214 $.post(this.kernel_url + "/interrupt");
216 $.post(this.kernel_url + "/interrupt");
215 };
217 };
216 };
218 };
@@ -45,21 +45,21 b' var IPython = (function (IPython) {'
45 IPython.save_widget.rename_notebook();
45 IPython.save_widget.rename_notebook();
46 });
46 });
47 this.element.find('#copy_notebook').click(function () {
47 this.element.find('#copy_notebook').click(function () {
48 var notebook_id = IPython.save_widget.get_notebook_id();
48 var notebook_id = IPython.notebook.get_notebook_id();
49 var url = $('body').data('baseProjectUrl') + notebook_id + '/copy';
49 var url = $('body').data('baseProjectUrl') + notebook_id + '/copy';
50 window.open(url,'_newtab');
50 window.open(url,'_newtab');
51 });
51 });
52 this.element.find('#save_notebook').click(function () {
52 this.element.find('#save_notebook').click(function () {
53 IPython.save_widget.save_notebook();
53 IPython.notebook.save_notebook();
54 });
54 });
55 this.element.find('#download_ipynb').click(function () {
55 this.element.find('#download_ipynb').click(function () {
56 var notebook_id = IPython.save_widget.get_notebook_id();
56 var notebook_id = IPython.notebook.get_notebook_id();
57 var url = $('body').data('baseProjectUrl') + 'notebooks/' +
57 var url = $('body').data('baseProjectUrl') + 'notebooks/' +
58 notebook_id + '?format=json';
58 notebook_id + '?format=json';
59 window.open(url,'_newtab');
59 window.open(url,'_newtab');
60 });
60 });
61 this.element.find('#download_py').click(function () {
61 this.element.find('#download_py').click(function () {
62 var notebook_id = IPython.save_widget.get_notebook_id();
62 var notebook_id = IPython.notebook.get_notebook_id();
63 var url = $('body').data('baseProjectUrl') + 'notebooks/' +
63 var url = $('body').data('baseProjectUrl') + 'notebooks/' +
64 notebook_id + '?format=py';
64 notebook_id + '?format=py';
65 window.open(url,'_newtab');
65 window.open(url,'_newtab');
@@ -26,6 +26,10 b' var IPython = (function (IPython) {'
26 this.msg_cell_map = {};
26 this.msg_cell_map = {};
27 this.metadata = {};
27 this.metadata = {};
28 this.control_key_active = false;
28 this.control_key_active = false;
29 this.notebook_id = null;
30 this.notebook_name = null;
31 this.notebook_name_blacklist_re = /[\/\\]/;
32 this.nbformat = 3 // Increment this when changing the nbformat
29 this.style();
33 this.style();
30 this.create_elements();
34 this.create_elements();
31 this.bind_events();
35 this.bind_events();
@@ -66,7 +70,7 b' var IPython = (function (IPython) {'
66 // Save (CTRL+S) or (AppleKey+S)
70 // Save (CTRL+S) or (AppleKey+S)
67 //metaKey = applekey on mac
71 //metaKey = applekey on mac
68 if ((event.ctrlKey || event.metaKey) && event.keyCode==83) {
72 if ((event.ctrlKey || event.metaKey) && event.keyCode==83) {
69 IPython.save_widget.save_notebook();
73 that.save_notebook();
70 event.preventDefault();
74 event.preventDefault();
71 return false;
75 return false;
72 } else if (event.which === 27) {
76 } else if (event.which === 27) {
@@ -92,7 +96,7 b' var IPython = (function (IPython) {'
92 } else if (event.which === 13 && event.ctrlKey) {
96 } else if (event.which === 13 && event.ctrlKey) {
93 that.execute_selected_cell({terminal:true});
97 that.execute_selected_cell({terminal:true});
94 return false;
98 return false;
95 } else if (event.which === 77 && event.ctrlKey) {
99 } else if (event.which === 77 && event.ctrlKey && that.control_key_active == false) {
96 that.control_key_active = true;
100 that.control_key_active = true;
97 return false;
101 return false;
98 } else if (event.which === 88 && that.control_key_active) {
102 } else if (event.which === 88 && that.control_key_active) {
@@ -177,7 +181,7 b' var IPython = (function (IPython) {'
177 return false;
181 return false;
178 } else if (event.which === 83 && that.control_key_active) {
182 } else if (event.which === 83 && that.control_key_active) {
179 // Save notebook = s
183 // Save notebook = s
180 IPython.save_widget.save_notebook();
184 that.save_notebook();
181 that.control_key_active = false;
185 that.control_key_active = false;
182 return false;
186 return false;
183 } else if (event.which === 74 && that.control_key_active) {
187 } else if (event.which === 74 && that.control_key_active) {
@@ -207,12 +211,12 b' var IPython = (function (IPython) {'
207 return false;
211 return false;
208 } else if (event.which === 73 && that.control_key_active) {
212 } else if (event.which === 73 && that.control_key_active) {
209 // Interrupt kernel = i
213 // Interrupt kernel = i
210 IPython.notebook.kernel.interrupt();
214 that.kernel.interrupt();
211 that.control_key_active = false;
215 that.control_key_active = false;
212 return false;
216 return false;
213 } else if (event.which === 190 && that.control_key_active) {
217 } else if (event.which === 190 && that.control_key_active) {
214 // Restart kernel = . # matches qt console
218 // Restart kernel = . # matches qt console
215 IPython.notebook.restart_kernel();
219 that.restart_kernel();
216 that.control_key_active = false;
220 that.control_key_active = false;
217 return false;
221 return false;
218 } else if (event.which === 72 && that.control_key_active) {
222 } else if (event.which === 72 && that.control_key_active) {
@@ -402,10 +406,14 b' var IPython = (function (IPython) {'
402 var cell = this.get_cell(index)
406 var cell = this.get_cell(index)
403 cell.select();
407 cell.select();
404 if (cell.cell_type === 'heading') {
408 if (cell.cell_type === 'heading') {
405 IPython.toolbar.set_cell_type(cell.cell_type+cell.level);
409 $([IPython.events]).trigger('selected_cell_type_changed.Notebook',
410 {'cell_type':cell.cell_type,level:cell.level}
411 );
406 } else {
412 } else {
407 IPython.toolbar.set_cell_type(cell.cell_type)
413 $([IPython.events]).trigger('selected_cell_type_changed.Notebook',
408 }
414 {'cell_type':cell.cell_type}
415 );
416 };
409 };
417 };
410 return this;
418 return this;
411 };
419 };
@@ -676,7 +684,9 b' var IPython = (function (IPython) {'
676 source_element.remove();
684 source_element.remove();
677 this.dirty = true;
685 this.dirty = true;
678 };
686 };
679 IPython.toolbar.set_cell_type("heading"+level);
687 $([IPython.events]).trigger('selected_cell_type_changed.Notebook',
688 {'cell_type':'heading',level:level}
689 );
680 };
690 };
681 };
691 };
682
692
@@ -880,15 +890,12 b' var IPython = (function (IPython) {'
880
890
881 Notebook.prototype.start_kernel = function () {
891 Notebook.prototype.start_kernel = function () {
882 this.kernel = new IPython.Kernel();
892 this.kernel = new IPython.Kernel();
883 var notebook_id = IPython.save_widget.get_notebook_id();
893 this.kernel.start(this.notebook_id, $.proxy(this.kernel_started, this));
884 this.kernel.start(notebook_id, $.proxy(this.kernel_started, this));
885 };
894 };
886
895
887
896
888 Notebook.prototype.restart_kernel = function () {
897 Notebook.prototype.restart_kernel = function () {
889 var that = this;
898 var that = this;
890 var notebook_id = IPython.save_widget.get_notebook_id();
891
892 var dialog = $('<div/>');
899 var dialog = $('<div/>');
893 dialog.html('Do you want to restart the current kernel? You will lose all variables defined in it.');
900 dialog.html('Do you want to restart the current kernel? You will lose all variables defined in it.');
894 $(document).append(dialog);
901 $(document).append(dialog);
@@ -976,8 +983,8 b' var IPython = (function (IPython) {'
976 var cell = this.cell_for_msg(reply.parent_header.msg_id);
983 var cell = this.cell_for_msg(reply.parent_header.msg_id);
977 if (msg_type !== 'status' && !cell){
984 if (msg_type !== 'status' && !cell){
978 // message not from this notebook, but should be attached to a cell
985 // message not from this notebook, but should be attached to a cell
979 console.log("Received IOPub message not caused by one of my cells");
986 // console.log("Received IOPub message not caused by one of my cells");
980 console.log(reply);
987 // console.log(reply);
981 return;
988 return;
982 }
989 }
983 var output_types = ['stream','display_data','pyout','pyerr'];
990 var output_types = ['stream','display_data','pyout','pyerr'];
@@ -985,9 +992,10 b' var IPython = (function (IPython) {'
985 this.handle_output(cell, msg_type, content);
992 this.handle_output(cell, msg_type, content);
986 } else if (msg_type === 'status') {
993 } else if (msg_type === 'status') {
987 if (content.execution_state === 'busy') {
994 if (content.execution_state === 'busy') {
995 $([IPython.events]).trigger('status_busy.Kernel');
988 IPython.kernel_status_widget.status_busy();
996 IPython.kernel_status_widget.status_busy();
989 } else if (content.execution_state === 'idle') {
997 } else if (content.execution_state === 'idle') {
990 IPython.kernel_status_widget.status_idle();
998 $([IPython.events]).trigger('status_idle.Kernel');
991 } else if (content.execution_state === 'dead') {
999 } else if (content.execution_state === 'dead') {
992 this.handle_status_dead();
1000 this.handle_status_dead();
993 };
1001 };
@@ -1142,8 +1150,33 b' var IPython = (function (IPython) {'
1142 this.msg_cell_map[msg_id] = cell.cell_id;
1150 this.msg_cell_map[msg_id] = cell.cell_id;
1143 };
1151 };
1144
1152
1153
1145 // Persistance and loading
1154 // Persistance and loading
1146
1155
1156 Notebook.prototype.get_notebook_id = function () {
1157 return this.notebook_id;
1158 };
1159
1160
1161 Notebook.prototype.get_notebook_name = function () {
1162 return this.notebook_name;
1163 };
1164
1165
1166 Notebook.prototype.set_notebook_name = function (name) {
1167 this.notebook_name = name;
1168 };
1169
1170
1171 Notebook.prototype.test_notebook_name = function (nbname) {
1172 nbname = nbname || '';
1173 if (this.notebook_name_blacklist_re.test(nbname) == false && nbname.length>0) {
1174 return true;
1175 } else {
1176 return false;
1177 };
1178 };
1179
1147
1180
1148 Notebook.prototype.fromJSON = function (data) {
1181 Notebook.prototype.fromJSON = function (data) {
1149 var ncells = this.ncells();
1182 var ncells = this.ncells();
@@ -1152,8 +1185,9 b' var IPython = (function (IPython) {'
1152 // Always delete cell 0 as they get renumbered as they are deleted.
1185 // Always delete cell 0 as they get renumbered as they are deleted.
1153 this.delete_cell(0);
1186 this.delete_cell(0);
1154 };
1187 };
1155 // Save the metadata
1188 // Save the metadata and name.
1156 this.metadata = data.metadata;
1189 this.metadata = data.metadata;
1190 this.notebook_name = data.metadata.name;
1157 // Only handle 1 worksheet for now.
1191 // Only handle 1 worksheet for now.
1158 var worksheet = data.worksheets[0];
1192 var worksheet = data.worksheets[0];
1159 if (worksheet !== undefined) {
1193 if (worksheet !== undefined) {
@@ -1186,12 +1220,10 b' var IPython = (function (IPython) {'
1186 };
1220 };
1187
1221
1188 Notebook.prototype.save_notebook = function () {
1222 Notebook.prototype.save_notebook = function () {
1189 var notebook_id = IPython.save_widget.get_notebook_id();
1190 var nbname = IPython.save_widget.get_notebook_name();
1191 // We may want to move the name/id/nbformat logic inside toJSON?
1223 // We may want to move the name/id/nbformat logic inside toJSON?
1192 var data = this.toJSON();
1224 var data = this.toJSON();
1193 data.metadata.name = nbname;
1225 data.metadata.name = this.notebook_name;
1194 data.nbformat = 3;
1226 data.nbformat = this.nbformat;
1195 // We do the call with settings so we can set cache to false.
1227 // We do the call with settings so we can set cache to false.
1196 var settings = {
1228 var settings = {
1197 processData : false,
1229 processData : false,
@@ -1199,63 +1231,108 b' var IPython = (function (IPython) {'
1199 type : "PUT",
1231 type : "PUT",
1200 data : JSON.stringify(data),
1232 data : JSON.stringify(data),
1201 headers : {'Content-Type': 'application/json'},
1233 headers : {'Content-Type': 'application/json'},
1202 success : $.proxy(this.notebook_saved,this),
1234 success : $.proxy(this.save_notebook_success,this),
1203 error : $.proxy(this.notebook_save_failed,this)
1235 error : $.proxy(this.save_notebook_error,this)
1204 };
1236 };
1205 IPython.save_widget.status_saving();
1237 $([IPython.events]).trigger('notebook_saving.Notebook');
1206 var url = $('body').data('baseProjectUrl') + 'notebooks/' + notebook_id;
1238 var url = $('body').data('baseProjectUrl') + 'notebooks/' + this.notebook_id;
1207 $.ajax(url, settings);
1239 $.ajax(url, settings);
1208 };
1240 };
1209
1241
1210
1242
1211 Notebook.prototype.notebook_saved = function (data, status, xhr) {
1243 Notebook.prototype.save_notebook_success = function (data, status, xhr) {
1212 this.dirty = false;
1244 this.dirty = false;
1213 IPython.save_widget.notebook_saved();
1245 $([IPython.events]).trigger('notebook_saved.Notebook');
1214 IPython.save_widget.status_last_saved();
1215 };
1246 };
1216
1247
1217
1248
1218 Notebook.prototype.notebook_save_failed = function (xhr, status, error_msg) {
1249 Notebook.prototype.save_notebook_error = function (xhr, status, error_msg) {
1219 IPython.save_widget.status_save_failed();
1250 $([IPython.events]).trigger('notebook_save_failed.Notebook');
1220 };
1251 };
1221
1252
1222
1253
1223 Notebook.prototype.load_notebook = function () {
1254 Notebook.prototype.load_notebook = function (notebook_id) {
1224 var that = this;
1255 var that = this;
1225 var notebook_id = IPython.save_widget.get_notebook_id();
1256 this.notebook_id = notebook_id;
1226 // We do the call with settings so we can set cache to false.
1257 // We do the call with settings so we can set cache to false.
1227 var settings = {
1258 var settings = {
1228 processData : false,
1259 processData : false,
1229 cache : false,
1260 cache : false,
1230 type : "GET",
1261 type : "GET",
1231 dataType : "json",
1262 dataType : "json",
1232 success : function (data, status, xhr) {
1263 success : $.proxy(this.load_notebook_success,this),
1233 that.notebook_loaded(data, status, xhr);
1264 error : $.proxy(this.load_notebook_error,this),
1234 }
1235 };
1265 };
1236 IPython.save_widget.status_loading();
1266 $([IPython.events]).trigger('notebook_loading.Notebook');
1237 var url = $('body').data('baseProjectUrl') + 'notebooks/' + notebook_id;
1267 var url = $('body').data('baseProjectUrl') + 'notebooks/' + this.notebook_id;
1238 $.ajax(url, settings);
1268 $.ajax(url, settings);
1239 };
1269 };
1240
1270
1241
1271
1242 Notebook.prototype.notebook_loaded = function (data, status, xhr) {
1272 Notebook.prototype.load_notebook_success = function (data, status, xhr) {
1243 this.fromJSON(data);
1273 this.fromJSON(data);
1244 if (this.ncells() === 0) {
1274 if (this.ncells() === 0) {
1245 this.insert_cell_below('code');
1275 this.insert_cell_below('code');
1246 };
1276 };
1247 IPython.save_widget.status_last_saved();
1248 IPython.save_widget.set_notebook_name(data.metadata.name);
1249 this.dirty = false;
1277 this.dirty = false;
1250 if (! this.read_only) {
1278 if (! this.read_only) {
1251 this.start_kernel();
1279 this.start_kernel();
1252 }
1280 }
1253 this.select(0);
1281 this.select(0);
1254 this.scroll_to_top();
1282 this.scroll_to_top();
1255 IPython.save_widget.update_url();
1283 if (data.orig_nbformat !== undefined && data.nbformat !== data.orig_nbformat) {
1256 IPython.layout_manager.do_resize();
1284 msg = "This notebook has been converted from an older " +
1257 };
1285 "notebook format (v"+data.orig_nbformat+") to the current notebook " +
1258
1286 "format (v"+data.nbformat+"). The next time you save this notebook, the " +
1287 "newer notebook format will be used and older verions of IPython " +
1288 "may not be able to read it. To keep the older version, close the " +
1289 "notebook without saving it.";
1290 var dialog = $('<div/>');
1291 dialog.html(msg);
1292 this.element.append(dialog);
1293 dialog.dialog({
1294 resizable: false,
1295 modal: true,
1296 title: "Notebook converted",
1297 closeText: "",
1298 close: function(event, ui) {$(this).dialog('destroy').remove();},
1299 buttons : {
1300 "OK": function () {
1301 $(this).dialog('close');
1302 }
1303 },
1304 width: 400
1305 });
1306 }
1307 $([IPython.events]).trigger('notebook_loaded.Notebook');
1308 };
1309
1310
1311 Notebook.prototype.load_notebook_error = function (xhr, textStatus, errorThrow) {
1312 if (xhr.status === 500) {
1313 msg = "An error occurred while loading this notebook. Most likely " +
1314 "this notebook is in a newer format than is supported by this " +
1315 "version of IPython. This version can load notebook formats " +
1316 "v"+this.nbformat+" or earlier.";
1317 var dialog = $('<div/>');
1318 dialog.html(msg);
1319 this.element.append(dialog);
1320 dialog.dialog({
1321 resizable: false,
1322 modal: true,
1323 title: "Error loading notebook",
1324 closeText: "",
1325 close: function(event, ui) {$(this).dialog('destroy').remove();},
1326 buttons : {
1327 "OK": function () {
1328 $(this).dialog('close');
1329 }
1330 },
1331 width: 400
1332 });
1333 }
1334 }
1335
1259 IPython.Notebook = Notebook;
1336 IPython.Notebook = Notebook;
1260
1337
1261
1338
@@ -82,14 +82,13 b' $(document).ready(function () {'
82
82
83 IPython.layout_manager = new IPython.LayoutManager();
83 IPython.layout_manager = new IPython.LayoutManager();
84 IPython.pager = new IPython.Pager('div#pager', 'div#pager_splitter');
84 IPython.pager = new IPython.Pager('div#pager', 'div#pager_splitter');
85 IPython.save_widget = new IPython.SaveWidget('span#save_widget');
86 IPython.quick_help = new IPython.QuickHelp('span#quick_help_area');
85 IPython.quick_help = new IPython.QuickHelp('span#quick_help_area');
87 IPython.login_widget = new IPython.LoginWidget('span#login_widget');
86 IPython.login_widget = new IPython.LoginWidget('span#login_widget');
88 IPython.notebook = new IPython.Notebook('div#notebook');
87 IPython.notebook = new IPython.Notebook('div#notebook');
89 IPython.kernel_status_widget = new IPython.KernelStatusWidget('#kernel_status');
88 IPython.save_widget = new IPython.SaveWidget('span#save_widget');
90 IPython.menubar = new IPython.MenuBar('#menubar')
89 IPython.menubar = new IPython.MenuBar('#menubar')
91 IPython.toolbar = new IPython.ToolBar('#toolbar')
90 IPython.toolbar = new IPython.ToolBar('#toolbar')
92 IPython.kernel_status_widget.status_idle();
91 IPython.notification_widget = new IPython.NotificationWidget('#notification')
93
92
94 IPython.layout_manager.do_resize();
93 IPython.layout_manager.do_resize();
95
94
@@ -111,7 +110,11 b' $(document).ready(function () {'
111 $('div#main_app').css('display','block');
110 $('div#main_app').css('display','block');
112
111
113 IPython.layout_manager.do_resize();
112 IPython.layout_manager.do_resize();
114 IPython.notebook.load_notebook();
113 $([IPython.events]).on('notebook_loaded.Notebook', function () {
114 IPython.layout_manager.do_resize();
115 IPython.save_widget.update_url();
116 })
117 IPython.notebook.load_notebook($('body').data('notebookId'));
115
118
116 });
119 });
117
120
@@ -79,16 +79,15 b' $(document).ready(function () {'
79 $('div#main_app').addClass('border-box-sizing ui-widget ui-widget-content');
79 $('div#main_app').addClass('border-box-sizing ui-widget ui-widget-content');
80 $('div#notebook_panel').addClass('border-box-sizing ui-widget');
80 $('div#notebook_panel').addClass('border-box-sizing ui-widget');
81
81
82 IPython.save_widget = new IPython.SaveWidget('span#save_widget');
83 IPython.login_widget = new IPython.LoginWidget('span#login_widget');
82 IPython.login_widget = new IPython.LoginWidget('span#login_widget');
84 IPython.notebook = new IPython.Notebook('div#notebook');
83 IPython.notebook = new IPython.Notebook('div#notebook');
84 IPython.save_widget = new IPython.SaveWidget('span#save_widget');
85
85
86 // These have display: none in the css file and are made visible here to prevent FLOUC.
86 // These have display: none in the css file and are made visible here to prevent FLOUC.
87 $('div#header').css('display','block');
87 $('div#header').css('display','block');
88 $('div#main_app').css('display','block');
88 $('div#main_app').css('display','block');
89
89
90 // Perform these actions after the notebook has been loaded.
90 IPython.notebook.load_notebook($('body').data('notebookId'));
91 IPython.notebook.load_notebook(function () {});
92
91
93 });
92 });
94
93
@@ -15,8 +15,6 b' var IPython = (function (IPython) {'
15
15
16 var SaveWidget = function (selector) {
16 var SaveWidget = function (selector) {
17 this.selector = selector;
17 this.selector = selector;
18 this.notebook_name_blacklist_re = /[\/\\]/;
19 this.last_saved_name = '';
20 if (this.selector !== undefined) {
18 if (this.selector !== undefined) {
21 this.element = $(selector);
19 this.element = $(selector);
22 this.style();
20 this.style();
@@ -43,11 +41,19 b' var IPython = (function (IPython) {'
43 }, function () {
41 }, function () {
44 $(this).removeClass("ui-state-hover");
42 $(this).removeClass("ui-state-hover");
45 });
43 });
46 };
44 $([IPython.events]).on('notebook_loaded.Notebook', function () {
47
45 that.set_last_saved();
48
46 that.update_notebook_name();
49 SaveWidget.prototype.save_notebook = function () {
47 that.update_document_title();
50 IPython.notebook.save_notebook();
48 });
49 $([IPython.events]).on('notebook_saved.Notebook', function () {
50 that.set_last_saved();
51 that.update_notebook_name();
52 that.update_document_title();
53 });
54 $([IPython.events]).on('notebook_save_failed.Notebook', function () {
55 that.set_save_status('');
56 });
51 };
57 };
52
58
53
59
@@ -61,7 +67,7 b' var IPython = (function (IPython) {'
61 dialog.append(
67 dialog.append(
62 $('<input/>').attr('type','text').attr('size','25')
68 $('<input/>').attr('type','text').attr('size','25')
63 .addClass('ui-widget ui-widget-content')
69 .addClass('ui-widget ui-widget-content')
64 .attr('value',that.get_notebook_name())
70 .attr('value',IPython.notebook.get_notebook_name())
65 );
71 );
66 // $(document).append(dialog);
72 // $(document).append(dialog);
67 dialog.dialog({
73 dialog.dialog({
@@ -73,15 +79,15 b' var IPython = (function (IPython) {'
73 buttons : {
79 buttons : {
74 "OK": function () {
80 "OK": function () {
75 var new_name = $(this).find('input').attr('value');
81 var new_name = $(this).find('input').attr('value');
76 if (!that.test_notebook_name(new_name)) {
82 if (!IPython.notebook.test_notebook_name(new_name)) {
77 $(this).find('h3').html(
83 $(this).find('h3').html(
78 "Invalid notebook name. Notebook names must "+
84 "Invalid notebook name. Notebook names must "+
79 "have 1 or more characters and can contain any characters " +
85 "have 1 or more characters and can contain any characters " +
80 "except / and \\. Please enter a new notebook name:"
86 "except / and \\. Please enter a new notebook name:"
81 );
87 );
82 } else {
88 } else {
83 that.set_notebook_name(new_name);
89 IPython.notebook.set_notebook_name(new_name);
84 that.save_notebook();
90 IPython.notebook.save_notebook();
85 $(this).dialog('close');
91 $(this).dialog('close');
86 }
92 }
87 },
93 },
@@ -92,82 +98,36 b' var IPython = (function (IPython) {'
92 });
98 });
93 }
99 }
94
100
95 SaveWidget.prototype.notebook_saved = function () {
96 this.set_document_title();
97 this.last_saved_name = this.get_notebook_name();
98 };
99
100
101
101 SaveWidget.prototype.get_notebook_name = function () {
102 SaveWidget.prototype.update_notebook_name = function () {
102 return this.element.find('span#notebook_name').html();
103 var nbname = IPython.notebook.get_notebook_name();
103 };
104
105
106 SaveWidget.prototype.set_notebook_name = function (nbname) {
107 this.element.find('span#notebook_name').html(nbname);
104 this.element.find('span#notebook_name').html(nbname);
108 this.set_document_title();
109 this.last_saved_name = nbname;
110 };
105 };
111
106
112
107
113 SaveWidget.prototype.set_document_title = function () {
108 SaveWidget.prototype.update_document_title = function () {
114 nbname = this.get_notebook_name();
109 var nbname = IPython.notebook.get_notebook_name();
115 document.title = nbname;
110 document.title = nbname;
116 };
111 };
117
118
119 SaveWidget.prototype.get_notebook_id = function () {
120 return $('body').data('notebookId');
121 };
122
112
123
113
124 SaveWidget.prototype.update_url = function () {
114 SaveWidget.prototype.update_url = function () {
125 var notebook_id = this.get_notebook_id();
115 var notebook_id = IPython.notebook.get_notebook_id();
126 if (notebook_id !== '') {
116 if (notebook_id !== null) {
127 var new_url = $('body').data('baseProjectUrl') + notebook_id;
117 var new_url = $('body').data('baseProjectUrl') + notebook_id;
128 window.history.replaceState({}, '', new_url);
118 window.history.replaceState({}, '', new_url);
129 };
119 };
130 };
120 };
131
121
132
122
133 SaveWidget.prototype.test_notebook_name = function (nbname) {
123 SaveWidget.prototype.set_save_status = function (msg) {
134 nbname = nbname || '';
124 this.element.find('span#save_status').html(msg);
135 if (this.notebook_name_blacklist_re.test(nbname) == false && nbname.length>0) {
125 }
136 return true;
137 } else {
138 return false;
139 };
140 };
141
126
142
127
143 SaveWidget.prototype.set_last_saved = function () {
128 SaveWidget.prototype.set_last_saved = function () {
144 var d = new Date();
129 var d = new Date();
145 $('#save_status').html('Last saved: '+d.format('mmm dd h:MM TT'));
130 this.set_save_status('Last saved: '+d.format('mmm dd h:MM TT'));
146
147 };
148
149 SaveWidget.prototype.reset_status = function () {
150 this.element.find('span#save_status').html('');
151 };
152
153
154 SaveWidget.prototype.status_last_saved = function () {
155 this.set_last_saved();
156 };
157
158
159 SaveWidget.prototype.status_saving = function () {
160 this.element.find('span#save_status').html('Saving...');
161 };
162
163
164 SaveWidget.prototype.status_save_failed = function () {
165 this.element.find('span#save_status').html('Save failed');
166 };
167
168
169 SaveWidget.prototype.status_loading = function () {
170 this.element.find('span#save_status').html('Loading...');
171 };
131 };
172
132
173
133
@@ -49,7 +49,7 b' var IPython = (function (IPython) {'
49 IPython.Cell.prototype.bind_events.apply(this);
49 IPython.Cell.prototype.bind_events.apply(this);
50 var that = this;
50 var that = this;
51 this.element.keydown(function (event) {
51 this.element.keydown(function (event) {
52 if (event.which === 13) {
52 if (event.which === 13 && !event.shiftKey) {
53 if (that.rendered) {
53 if (that.rendered) {
54 that.edit();
54 that.edit();
55 return false;
55 return false;
@@ -72,8 +72,9 b' var IPython = (function (IPython) {'
72
72
73
73
74 ToolBar.prototype.bind_events = function () {
74 ToolBar.prototype.bind_events = function () {
75 var that = this;
75 this.element.find('#save_b').click(function () {
76 this.element.find('#save_b').click(function () {
76 IPython.save_widget.save_notebook();
77 IPython.notebook.save_notebook();
77 });
78 });
78 this.element.find('#cut_b').click(function () {
79 this.element.find('#cut_b').click(function () {
79 IPython.notebook.cut_cell();
80 IPython.notebook.cut_cell();
@@ -124,12 +125,13 b' var IPython = (function (IPython) {'
124 IPython.notebook.to_heading(undefined, 6);
125 IPython.notebook.to_heading(undefined, 6);
125 };
126 };
126 });
127 });
127
128 $([IPython.events]).on('selected_cell_type_changed', function (event, data) {
128 };
129 if (data.cell_type === 'heading') {
129
130 that.element.find('#cell_type').val(data.cell_type+data.level);
130
131 } else {
131 ToolBar.prototype.set_cell_type = function (cell_type) {
132 that.element.find('#cell_type').val(data.cell_type);
132 this.element.find('#cell_type').val(cell_type);
133 }
134 });
133 };
135 };
134
136
135
137
@@ -54,10 +54,9 b''
54 <button id="login">Login</button>
54 <button id="login">Login</button>
55 {% end %}
55 {% end %}
56 </span>
56 </span>
57
58 <span id="kernel_status">Idle</span>
59 </div>
57 </div>
60
58
59 <div id="menubar_container">
61 <div id="menubar">
60 <div id="menubar">
62 <ul id="menus">
61 <ul id="menus">
63 <li><a href="#">File</a>
62 <li><a href="#">File</a>
@@ -153,6 +152,9 b''
153 </ul>
152 </ul>
154
153
155 </div>
154 </div>
155 <div id="notification"></div>
156 </div>
157
156
158
157 <div id="toolbar">
159 <div id="toolbar">
158
160
@@ -220,12 +222,12 b''
220 <script src="{{ static_url("dateformat/date.format.js") }}" charset="utf-8"></script>
222 <script src="{{ static_url("dateformat/date.format.js") }}" charset="utf-8"></script>
221
223
222 <script src="{{ static_url("js/namespace.js") }}" type="text/javascript" charset="utf-8"></script>
224 <script src="{{ static_url("js/namespace.js") }}" type="text/javascript" charset="utf-8"></script>
225 <script src="{{ static_url("js/events.js") }}" type="text/javascript" charset="utf-8"></script>
223 <script src="{{ static_url("js/utils.js") }}" type="text/javascript" charset="utf-8"></script>
226 <script src="{{ static_url("js/utils.js") }}" type="text/javascript" charset="utf-8"></script>
224 <script src="{{ static_url("js/cell.js") }}" type="text/javascript" charset="utf-8"></script>
227 <script src="{{ static_url("js/cell.js") }}" type="text/javascript" charset="utf-8"></script>
225 <script src="{{ static_url("js/codecell.js") }}" type="text/javascript" charset="utf-8"></script>
228 <script src="{{ static_url("js/codecell.js") }}" type="text/javascript" charset="utf-8"></script>
226 <script src="{{ static_url("js/textcell.js") }}" type="text/javascript" charset="utf-8"></script>
229 <script src="{{ static_url("js/textcell.js") }}" type="text/javascript" charset="utf-8"></script>
227 <script src="{{ static_url("js/kernel.js") }}" type="text/javascript" charset="utf-8"></script>
230 <script src="{{ static_url("js/kernel.js") }}" type="text/javascript" charset="utf-8"></script>
228 <script src="{{ static_url("js/kernelstatus.js") }}" type="text/javascript" charset="utf-8"></script>
229 <script src="{{ static_url("js/layout.js") }}" type="text/javascript" charset="utf-8"></script>
231 <script src="{{ static_url("js/layout.js") }}" type="text/javascript" charset="utf-8"></script>
230 <script src="{{ static_url("js/savewidget.js") }}" type="text/javascript" charset="utf-8"></script>
232 <script src="{{ static_url("js/savewidget.js") }}" type="text/javascript" charset="utf-8"></script>
231 <script src="{{ static_url("js/quickhelp.js") }}" type="text/javascript" charset="utf-8"></script>
233 <script src="{{ static_url("js/quickhelp.js") }}" type="text/javascript" charset="utf-8"></script>
@@ -234,6 +236,7 b''
234 <script src="{{ static_url("js/menubar.js") }}" type="text/javascript" charset="utf-8"></script>
236 <script src="{{ static_url("js/menubar.js") }}" type="text/javascript" charset="utf-8"></script>
235 <script src="{{ static_url("js/toolbar.js") }}" type="text/javascript" charset="utf-8"></script>
237 <script src="{{ static_url("js/toolbar.js") }}" type="text/javascript" charset="utf-8"></script>
236 <script src="{{ static_url("js/notebook.js") }}" type="text/javascript" charset="utf-8"></script>
238 <script src="{{ static_url("js/notebook.js") }}" type="text/javascript" charset="utf-8"></script>
239 <script src="{{ static_url("js/notificationwidget.js") }}" type="text/javascript" charset="utf-8"></script>
237 <script src="{{ static_url("js/notebookmain.js") }}" type="text/javascript" charset="utf-8"></script>
240 <script src="{{ static_url("js/notebookmain.js") }}" type="text/javascript" charset="utf-8"></script>
238
241
239 </body>
242 </body>
@@ -17,10 +17,7 b''
17
17
18 <link rel="stylesheet" href="{{ static_url("jquery/css/themes/base/jquery-ui.min.css") }}" type="text/css" />
18 <link rel="stylesheet" href="{{ static_url("jquery/css/themes/base/jquery-ui.min.css") }}" type="text/css" />
19 <link rel="stylesheet" href="{{ static_url("codemirror/lib/codemirror.css") }}">
19 <link rel="stylesheet" href="{{ static_url("codemirror/lib/codemirror.css") }}">
20 <link rel="stylesheet" href="{{ static_url("codemirror/mode/markdown/markdown.css") }}">
21 <link rel="stylesheet" href="{{ static_url("codemirror/mode/rst/rst.css") }}">
22 <link rel="stylesheet" href="{{ static_url("codemirror/theme/ipython.css") }}">
20 <link rel="stylesheet" href="{{ static_url("codemirror/theme/ipython.css") }}">
23 <link rel="stylesheet" href="{{ static_url("codemirror/theme/default.css") }}">
24
21
25 <link rel="stylesheet" href="{{ static_url("prettify/prettify.css") }}"/>
22 <link rel="stylesheet" href="{{ static_url("prettify/prettify.css") }}"/>
26
23
@@ -88,6 +85,7 b''
88 <script src="{{ static_url("dateformat/date.format.js") }}" charset="utf-8"></script>
85 <script src="{{ static_url("dateformat/date.format.js") }}" charset="utf-8"></script>
89
86
90 <script src="{{ static_url("js/namespace.js") }}" type="text/javascript" charset="utf-8"></script>
87 <script src="{{ static_url("js/namespace.js") }}" type="text/javascript" charset="utf-8"></script>
88 <script src="{{ static_url("js/events.js") }}" type="text/javascript" charset="utf-8"></script>
91 <script src="{{ static_url("js/utils.js") }}" type="text/javascript" charset="utf-8"></script>
89 <script src="{{ static_url("js/utils.js") }}" type="text/javascript" charset="utf-8"></script>
92 <script src="{{ static_url("js/cell.js") }}" type="text/javascript" charset="utf-8"></script>
90 <script src="{{ static_url("js/cell.js") }}" type="text/javascript" charset="utf-8"></script>
93 <script src="{{ static_url("js/codecell.js") }}" type="text/javascript" charset="utf-8"></script>
91 <script src="{{ static_url("js/codecell.js") }}" type="text/javascript" charset="utf-8"></script>
@@ -28,14 +28,14 b' from IPython.nbformat import v1'
28 from IPython.nbformat.v3 import (
28 from IPython.nbformat.v3 import (
29 NotebookNode,
29 NotebookNode,
30 new_code_cell, new_text_cell, new_notebook, new_output, new_worksheet,
30 new_code_cell, new_text_cell, new_notebook, new_output, new_worksheet,
31 parse_filename, new_metadata, new_author, new_heading_cell
31 parse_filename, new_metadata, new_author, new_heading_cell, nbformat
32 )
32 )
33
33
34 #-----------------------------------------------------------------------------
34 #-----------------------------------------------------------------------------
35 # Code
35 # Code
36 #-----------------------------------------------------------------------------
36 #-----------------------------------------------------------------------------
37
37
38 current_nbformat = 3
38 current_nbformat = nbformat
39
39
40
40
41 class NBFormatError(Exception):
41 class NBFormatError(Exception):
@@ -45,8 +45,8 b' class NBFormatError(Exception):'
45 def parse_json(s, **kwargs):
45 def parse_json(s, **kwargs):
46 """Parse a string into a (nbformat, dict) tuple."""
46 """Parse a string into a (nbformat, dict) tuple."""
47 d = json.loads(s, **kwargs)
47 d = json.loads(s, **kwargs)
48 nbformat = d.get('nbformat',1)
48 nbf = d.get('nbformat',1)
49 return nbformat, d
49 return nbf, d
50
50
51
51
52 def parse_py(s, **kwargs):
52 def parse_py(s, **kwargs):
@@ -54,25 +54,25 b' def parse_py(s, **kwargs):'
54 pattern = r'# <nbformat>(?P<nbformat>\d+)</nbformat>'
54 pattern = r'# <nbformat>(?P<nbformat>\d+)</nbformat>'
55 m = re.search(pattern,s)
55 m = re.search(pattern,s)
56 if m is not None:
56 if m is not None:
57 nbformat = int(m.group('nbformat'))
57 nbf = int(m.group('nbformat'))
58 else:
58 else:
59 nbformat = 3
59 nbf = current_nbformat
60 return nbformat, s
60 return nbf, s
61
61
62
62
63 def reads_json(s, **kwargs):
63 def reads_json(s, **kwargs):
64 """Read a JSON notebook from a string and return the NotebookNode object."""
64 """Read a JSON notebook from a string and return the NotebookNode object."""
65 nbformat, d = parse_json(s, **kwargs)
65 nbf, d = parse_json(s, **kwargs)
66 if nbformat == 1:
66 if nbf == 1:
67 nb = v1.to_notebook_json(d, **kwargs)
67 nb = v1.to_notebook_json(d, **kwargs)
68 nb = v3.convert_to_this_nbformat(nb, orig_version=1)
68 nb = v3.convert_to_this_nbformat(nb, orig_version=1)
69 elif nbformat == 2:
69 elif nbf == 2:
70 nb = v2.to_notebook_json(d, **kwargs)
70 nb = v2.to_notebook_json(d, **kwargs)
71 nb = v3.convert_to_this_nbformat(nb, orig_version=2)
71 nb = v3.convert_to_this_nbformat(nb, orig_version=2)
72 elif nbformat == 3:
72 elif nbf == 3:
73 nb = v3.to_notebook_json(d, **kwargs)
73 nb = v3.to_notebook_json(d, **kwargs)
74 else:
74 else:
75 raise NBFormatError('Unsupported JSON nbformat version: %i' % nbformat)
75 raise NBFormatError('Unsupported JSON nbformat version: %i' % nbf)
76 return nb
76 return nb
77
77
78
78
@@ -82,13 +82,13 b' def writes_json(nb, **kwargs):'
82
82
83 def reads_py(s, **kwargs):
83 def reads_py(s, **kwargs):
84 """Read a .py notebook from a string and return the NotebookNode object."""
84 """Read a .py notebook from a string and return the NotebookNode object."""
85 nbformat, s = parse_py(s, **kwargs)
85 nbf, s = parse_py(s, **kwargs)
86 if nbformat == 2:
86 if nbf == 2:
87 nb = v2.to_notebook_py(s, **kwargs)
87 nb = v2.to_notebook_py(s, **kwargs)
88 elif nbformat == 3:
88 elif nbf == 3:
89 nb = v3.to_notebook_py(s, **kwargs)
89 nb = v3.to_notebook_py(s, **kwargs)
90 else:
90 else:
91 raise NBFormatError('Unsupported PY nbformat version: %i' % nbformat)
91 raise NBFormatError('Unsupported PY nbformat version: %i' % nbf)
92 return nb
92 return nb
93
93
94
94
@@ -1,4 +1,4 b''
1 """The main API for the v2 notebook format.
1 """The main API for the v3 notebook format.
2
2
3 Authors:
3 Authors:
4
4
@@ -19,7 +19,7 b' Authors:'
19 from .nbbase import (
19 from .nbbase import (
20 NotebookNode,
20 NotebookNode,
21 new_code_cell, new_text_cell, new_notebook, new_output, new_worksheet,
21 new_code_cell, new_text_cell, new_notebook, new_output, new_worksheet,
22 new_metadata, new_author, new_heading_cell
22 new_metadata, new_author, new_heading_cell, nbformat
23 )
23 )
24
24
25 from .nbjson import reads as reads_json, writes as writes_json
25 from .nbjson import reads as reads_json, writes as writes_json
@@ -27,7 +27,7 b' from IPython.nbformat import v2'
27 #-----------------------------------------------------------------------------
27 #-----------------------------------------------------------------------------
28
28
29 def convert_to_this_nbformat(nb, orig_version=2):
29 def convert_to_this_nbformat(nb, orig_version=2):
30 """Convert a notebook to the v2 format.
30 """Convert a notebook to the v3 format.
31
31
32 Parameters
32 Parameters
33 ----------
33 ----------
@@ -40,6 +40,9 b' def convert_to_this_nbformat(nb, orig_version=2):'
40 nb = v2.convert_to_this_nbformat(nb)
40 nb = v2.convert_to_this_nbformat(nb)
41 orig_version = 2
41 orig_version = 2
42 if orig_version == 2:
42 if orig_version == 2:
43 # Mark the original nbformat so consumers know it has been converted.
44 nb.nbformat = 3
45 nb.orig_nbformat = 2
43 return nb
46 return nb
44 elif orig_version == 3:
47 elif orig_version == 3:
45 return nb
48 return nb
@@ -30,6 +30,9 b' from IPython.utils.ipstruct import Struct'
30 # Code
30 # Code
31 #-----------------------------------------------------------------------------
31 #-----------------------------------------------------------------------------
32
32
33 # Change this when incrementing the nbformat version
34 nbformat = 3
35
33 class NotebookNode(Struct):
36 class NotebookNode(Struct):
34 pass
37 pass
35
38
@@ -146,7 +149,7 b' def new_worksheet(name=None, cells=None):'
146 def new_notebook(metadata=None, worksheets=None):
149 def new_notebook(metadata=None, worksheets=None):
147 """Create a notebook by name, id and a list of worksheets."""
150 """Create a notebook by name, id and a list of worksheets."""
148 nb = NotebookNode()
151 nb = NotebookNode()
149 nb.nbformat = 3
152 nb.nbformat = nbformat
150 if worksheets is None:
153 if worksheets is None:
151 nb.worksheets = []
154 nb.worksheets = []
152 else:
155 else:
@@ -20,7 +20,7 b' import re'
20 from .rwbase import NotebookReader, NotebookWriter
20 from .rwbase import NotebookReader, NotebookWriter
21 from .nbbase import (
21 from .nbbase import (
22 new_code_cell, new_text_cell, new_worksheet,
22 new_code_cell, new_text_cell, new_worksheet,
23 new_notebook, new_heading_cell
23 new_notebook, new_heading_cell, nbformat
24 )
24 )
25
25
26 #-----------------------------------------------------------------------------
26 #-----------------------------------------------------------------------------
@@ -151,7 +151,7 b' class PyWriter(NotebookWriter):'
151
151
152 def writes(self, nb, **kwargs):
152 def writes(self, nb, **kwargs):
153 lines = [u'# -*- coding: utf-8 -*-']
153 lines = [u'# -*- coding: utf-8 -*-']
154 lines.extend([u'# <nbformat>2</nbformat>',''])
154 lines.extend([u'# <nbformat>%i</nbformat>' % nbformat,''])
155 for ws in nb.worksheets:
155 for ws in nb.worksheets:
156 for cell in ws.cells:
156 for cell in ws.cells:
157 if cell.cell_type == u'code':
157 if cell.cell_type == u'code':
@@ -4,7 +4,7 b' from base64 import encodestring'
4 from ..nbbase import (
4 from ..nbbase import (
5 NotebookNode,
5 NotebookNode,
6 new_code_cell, new_text_cell, new_worksheet, new_notebook, new_output,
6 new_code_cell, new_text_cell, new_worksheet, new_notebook, new_output,
7 new_metadata, new_author, new_heading_cell
7 new_metadata, new_author, new_heading_cell, nbformat
8 )
8 )
9
9
10 # some random base64-encoded *bytes*
10 # some random base64-encoded *bytes*
@@ -92,7 +92,7 b' nb0 = new_notebook('
92 )
92 )
93
93
94 nb0_py = """# -*- coding: utf-8 -*-
94 nb0_py = """# -*- coding: utf-8 -*-
95 # <nbformat>2</nbformat>
95 # <nbformat>%i</nbformat>
96
96
97 # <htmlcell>
97 # <htmlcell>
98
98
@@ -122,6 +122,6 b' a = numpy.random.rand(100)'
122
122
123 print a
123 print a
124
124
125 """
125 """ % nbformat
126
126
127
127
@@ -3,7 +3,7 b' from unittest import TestCase'
3 from ..nbbase import (
3 from ..nbbase import (
4 NotebookNode,
4 NotebookNode,
5 new_code_cell, new_text_cell, new_worksheet, new_notebook, new_output,
5 new_code_cell, new_text_cell, new_worksheet, new_notebook, new_output,
6 new_author, new_metadata, new_heading_cell
6 new_author, new_metadata, new_heading_cell, nbformat
7 )
7 )
8
8
9 class TestCell(TestCase):
9 class TestCell(TestCase):
@@ -102,7 +102,7 b' class TestNotebook(TestCase):'
102 nb = new_notebook()
102 nb = new_notebook()
103 self.assertEquals(nb.worksheets, [])
103 self.assertEquals(nb.worksheets, [])
104 self.assertEquals(nb.metadata, NotebookNode())
104 self.assertEquals(nb.metadata, NotebookNode())
105 self.assertEquals(nb.nbformat,2)
105 self.assertEquals(nb.nbformat,nbformat)
106
106
107 def test_notebook(self):
107 def test_notebook(self):
108 worksheets = [new_worksheet(),new_worksheet()]
108 worksheets = [new_worksheet(),new_worksheet()]
@@ -110,7 +110,7 b' class TestNotebook(TestCase):'
110 nb = new_notebook(metadata=metadata,worksheets=worksheets)
110 nb = new_notebook(metadata=metadata,worksheets=worksheets)
111 self.assertEquals(nb.metadata.name,u'foo')
111 self.assertEquals(nb.metadata.name,u'foo')
112 self.assertEquals(nb.worksheets,worksheets)
112 self.assertEquals(nb.worksheets,worksheets)
113 self.assertEquals(nb.nbformat,2)
113 self.assertEquals(nb.nbformat,nbformat)
114
114
115 class TestMetadata(TestCase):
115 class TestMetadata(TestCase):
116
116
@@ -855,7 +855,7 b''
855 "Note that this is *different* from the above examples. Above we were typing mathematical expressions",
855 "Note that this is *different* from the above examples. Above we were typing mathematical expressions",
856 "in Markdown cells (along with normal text) and letting the browser render them; now we are displaying",
856 "in Markdown cells (along with normal text) and letting the browser render them; now we are displaying",
857 "the output of a Python computation as a LaTeX expression wrapped by the `Math()` object so the browser",
857 "the output of a Python computation as a LaTeX expression wrapped by the `Math()` object so the browser",
858 "renders it:"
858 "renders it. The `Math` object will add the needed LaTeX delimiters (`$$`) if they are not provided:"
859 ]
859 ]
860 },
860 },
861 {
861 {
@@ -863,22 +863,59 b''
863 "collapsed": false,
863 "collapsed": false,
864 "input": [
864 "input": [
865 "from IPython.core.display import Math",
865 "from IPython.core.display import Math",
866 "Math(r'$F(k) = \\int_{-\\infty}^{\\infty} f(x) e^{2\\pi i k} dx$')"
866 "Math(r'F(k) = \\int_{-\\infty}^{\\infty} f(x) e^{2\\pi i k} dx')"
867 ],
867 ],
868 "language": "python",
868 "language": "python",
869 "outputs": [
869 "outputs": [
870 {
870 {
871 "latex": [
871 "latex": [
872 "$F(k) = \\int_{-\\infty}^{\\infty} f(x) e^{2\\pi i k} dx$"
872 "$$F(k) = \\int_{-\\infty}^{\\infty} f(x) e^{2\\pi i k} dx$$"
873 ],
873 ],
874 "output_type": "pyout",
874 "output_type": "pyout",
875 "prompt_number": 8,
875 "prompt_number": 1,
876 "text": [
876 "text": [
877 "&lt;IPython.core.display.Math at 0x45840d0&gt;"
877 "<IPython.core.display.Math object at 0x10ad35e90>"
878 ]
878 ]
879 }
879 }
880 ],
880 ],
881 "prompt_number": 8
881 "prompt_number": 1
882 },
883 {
884 "cell_type": "markdown",
885 "source": [
886 "With the `Latex` class, you have to include the delimiters yourself. This allows you to use other LaTeX modes such as `eqnarray`:"
887 ]
888 },
889 {
890 "cell_type": "code",
891 "collapsed": false,
892 "input": [
893 "from IPython.core.display import Latex",
894 "Latex(r\"\"\"\\begin{eqnarray}",
895 "\\nabla \\times \\vec{\\mathbf{B}} -\\, \\frac1c\\, \\frac{\\partial\\vec{\\mathbf{E}}}{\\partial t} & = \\frac{4\\pi}{c}\\vec{\\mathbf{j}} \\\\",
896 "\\nabla \\cdot \\vec{\\mathbf{E}} & = 4 \\pi \\rho \\\\",
897 "\\nabla \\times \\vec{\\mathbf{E}}\\, +\\, \\frac1c\\, \\frac{\\partial\\vec{\\mathbf{B}}}{\\partial t} & = \\vec{\\mathbf{0}} \\\\",
898 "\\nabla \\cdot \\vec{\\mathbf{B}} & = 0 ",
899 "\\end{eqnarray}\"\"\")"
900 ],
901 "language": "python",
902 "outputs": [
903 {
904 "latex": [
905 "\\begin{eqnarray}",
906 "\\nabla \\times \\vec{\\mathbf{B}} -\\, \\frac1c\\, \\frac{\\partial\\vec{\\mathbf{E}}}{\\partial t} & = \\frac{4\\pi}{c}\\vec{\\mathbf{j}} \\\\ \\nabla \\cdot \\vec{\\mathbf{E}} & = 4 \\pi \\rho \\\\",
907 "\\nabla \\times \\vec{\\mathbf{E}}\\, +\\, \\frac1c\\, \\frac{\\partial\\vec{\\mathbf{B}}}{\\partial t} & = \\vec{\\mathbf{0}} \\\\",
908 "\\nabla \\cdot \\vec{\\mathbf{B}} & = 0 ",
909 "\\end{eqnarray}"
910 ],
911 "output_type": "pyout",
912 "prompt_number": 5,
913 "text": [
914 "<IPython.core.display.Latex object at 0x109a38790>"
915 ]
916 }
917 ],
918 "prompt_number": 5
882 },
919 },
883 {
920 {
884 "cell_type": "markdown",
921 "cell_type": "markdown",
1 NO CONTENT: file was removed
NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now