##// END OF EJS Templates
Splitting notebook.js into muliple files for development ease.
Brian E. Granger -
Show More
@@ -0,0 +1,72 b''
1
2 //============================================================================
3 // Cell
4 //============================================================================
5
6
7 var Cell = function (notebook) {
8 this.notebook = notebook;
9 this.selected = false;
10 this.element;
11 this.create_element();
12 if (this.element !== undefined) {
13 this.element.data("cell", this);
14 this.bind_events();
15 }
16 this.cell_id = uuid();
17 };
18
19
20 Cell.prototype.grow = function(element) {
21 // Grow the cell by hand. This is used upon reloading from JSON, when the
22 // autogrow handler is not called.
23 var dom = element.get(0);
24 var lines_count = 0;
25 // modified split rule from
26 // http://stackoverflow.com/questions/2035910/how-to-get-the-number-of-lines-in-a-textarea/2036424#2036424
27 var lines = dom.value.split(/\r|\r\n|\n/);
28 lines_count = lines.length;
29 if (lines_count >= 1) {
30 dom.rows = lines_count;
31 } else {
32 dom.rows = 1;
33 }
34 };
35
36
37 Cell.prototype.select = function () {
38 this.element.addClass('ui-widget-content ui-corner-all');
39 this.selected = true;
40 // TODO: we need t test across browsers to see if both of these are needed.
41 // In the meantime, there should not be any harm in having them both.
42 this.element.find('textarea').trigger('focusin');
43 this.element.find('textarea').trigger('focus');
44 };
45
46
47 Cell.prototype.unselect = function () {
48 this.element.removeClass('ui-widget-content ui-corner-all');
49 this.selected = false;
50 };
51
52
53 Cell.prototype.bind_events = function () {
54 var that = this;
55 var nb = that.notebook
56 that.element.click(function (event) {
57 if (that.selected === false) {
58 nb.select(nb.find_cell_index(that));
59 };
60 });
61 that.element.focusin(function (event) {
62 if (that.selected === false) {
63 nb.select(nb.find_cell_index(that));
64 };
65 });
66 };
67
68
69 // Subclasses must implement create_element.
70 Cell.prototype.create_element = function () {};
71
72
@@ -0,0 +1,195 b''
1
2 //============================================================================
3 // CodeCell
4 //============================================================================
5
6
7 var CodeCell = function (notebook) {
8 this.code_mirror = null;
9 this.input_prompt_number = ' ';
10 Cell.apply(this, arguments);
11 };
12
13
14 CodeCell.prototype = new Cell();
15
16
17 CodeCell.prototype.create_element = function () {
18 var cell = $('<div></div>').addClass('cell code_cell vbox border-box-sizing');
19 var input = $('<div></div>').addClass('input hbox border-box-sizing');
20 input.append($('<div/>').addClass('prompt input_prompt monospace-font'));
21 var input_area = $('<div/>').addClass('input_area box-flex1 border-box-sizing');
22 this.code_mirror = CodeMirror(input_area.get(0), {
23 indentUnit : 4,
24 enterMode : 'flat',
25 tabMode: 'shift'
26 });
27 input.append(input_area);
28 var output = $('<div></div>').addClass('output vbox border-box-sizing');
29 cell.append(input).append(output);
30 this.element = cell;
31 this.collapse()
32 };
33
34
35 CodeCell.prototype.select = function () {
36 Cell.prototype.select.apply(this);
37 this.code_mirror.focus();
38 };
39
40
41 CodeCell.prototype.append_pyout = function (data, n) {
42 var toinsert = $("<div/>").addClass("output_area output_pyout hbox monospace-font");
43 toinsert.append($('<div/>').
44 addClass('prompt output_prompt').
45 html('Out[' + n + ']:')
46 );
47 this.append_display_data(data, toinsert);
48 toinsert.children().last().addClass("box_flex1");
49 this.element.find("div.output").append(toinsert);
50 // If we just output latex, typeset it.
51 if (data["text/latex"] !== undefined) {
52 MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
53 };
54 };
55
56
57 CodeCell.prototype.append_pyerr = function (ename, evalue, tb) {
58 var s = '';
59 var len = tb.length;
60 for (var i=0; i<len; i++) {
61 s = s + tb[i] + '\n';
62 }
63 s = s + '\n';
64 this.append_stream(s);
65 };
66
67
68 CodeCell.prototype.append_display_data = function (data, element) {
69 console.log(data);
70 if (data["text/latex"] !== undefined) {
71 this.append_latex(data["text/latex"], element);
72 // If it is undefined, then we just appended to div.output, which
73 // makes the latex visible and we can typeset it. The typesetting
74 // has to be done after the latex is on the page.
75 if (element === undefined) {
76 MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
77 };
78 } else if (data["image/svg+xml"] !== undefined) {
79 this.append_svg(data["image/svg+xml"], element);
80 } else if (data["image/png"] !== undefined) {
81 this.append_png(data["image/png"], element);
82 } else if (data["text/plain"] !== undefined) {
83 this.append_stream(data["text/plain"], element);
84 };
85 return element;
86 };
87
88
89 CodeCell.prototype.append_stream = function (data, element) {
90 element = element || this.element.find("div.output");
91 var toinsert = $("<div/>").addClass("output_area output_stream monospace-font");
92 toinsert.append($("<pre/>").addClass("monospace-font").html(fixConsole(data)));
93 element.append(toinsert);
94 return element;
95 };
96
97
98 CodeCell.prototype.append_svg = function (svg, element) {
99 element = element || this.element.find("div.output");
100 var toinsert = $("<div/>").addClass("output_area output_svg");
101 toinsert.append(svg);
102 element.append(toinsert);
103 return element;
104 };
105
106
107 CodeCell.prototype.append_png = function (png, element) {
108 element = element || this.element.find("div.output");
109 var toinsert = $("<div/>").addClass("output_area output_png");
110 toinsert.append($("<img/>").attr('src','data:image/png;base64,'+png));
111 element.append(toinsert);
112 return element;
113 };
114
115
116 CodeCell.prototype.append_latex = function (latex, element) {
117 // This method cannot do the typesetting because the latex first has to
118 // be on the page.
119 element = element || this.element.find("div.output");
120 var toinsert = $("<div/>").addClass("output_area output_latex monospace-font");
121 toinsert.append(latex);
122 element.append(toinsert);
123 return element;
124 }
125
126
127 CodeCell.prototype.clear_output = function () {
128 this.element.find("div.output").html("");
129 };
130
131
132 CodeCell.prototype.collapse = function () {
133 this.element.find('div.output').hide();
134 };
135
136
137 CodeCell.prototype.expand = function () {
138 this.element.find('div.output').show();
139 };
140
141
142 CodeCell.prototype.set_input_prompt = function (number) {
143 var n = number || ' ';
144 this.input_prompt_number = n
145 this.element.find('div.input_prompt').html('In&nbsp;[' + n + ']:');
146 };
147
148
149 CodeCell.prototype.get_code = function () {
150 return this.code_mirror.getValue();
151 };
152
153
154 CodeCell.prototype.set_code = function (code) {
155 return this.code_mirror.setValue(code);
156 };
157
158
159 CodeCell.prototype.at_top = function () {
160 var cursor = this.code_mirror.getCursor();
161 if (cursor.line === 0) {
162 return true;
163 } else {
164 return false;
165 }
166 };
167
168
169 CodeCell.prototype.at_bottom = function () {
170 var cursor = this.code_mirror.getCursor();
171 if (cursor.line === (this.code_mirror.lineCount()-1)) {
172 return true;
173 } else {
174 return false;
175 }
176 };
177
178
179 CodeCell.prototype.fromJSON = function (data) {
180 if (data.cell_type === 'code') {
181 this.set_code(data.code);
182 this.set_input_prompt(data.prompt_number);
183 };
184 };
185
186
187 CodeCell.prototype.toJSON = function () {
188 return {
189 code : this.get_code(),
190 cell_type : 'code',
191 prompt_number : this.input_prompt_number
192 };
193 };
194
195
@@ -0,0 +1,107 b''
1
2 //============================================================================
3 // Kernel
4 //============================================================================
5
6
7 var Kernel = function () {
8 this.kernel_id = null;
9 this.base_url = "/kernels";
10 this.kernel_url = null;
11 };
12
13
14 Kernel.prototype.get_msg = function (msg_type, content) {
15 var msg = {
16 header : {
17 msg_id : uuid(),
18 username : "bgranger",
19 session: this.session_id,
20 msg_type : msg_type
21 },
22 content : content,
23 parent_header : {}
24 };
25 return msg;
26 }
27
28 Kernel.prototype.start_kernel = function (callback, context) {
29 var that = this;
30 $.post(this.base_url,
31 function (kernel_id) {
32 that._handle_start_kernel(kernel_id, callback, context);
33 },
34 'json'
35 );
36 };
37
38
39 Kernel.prototype._handle_start_kernel = function (kernel_id, callback, context) {
40 this.kernel_id = kernel_id;
41 this.kernel_url = this.base_url + "/" + this.kernel_id;
42 this._start_channels();
43 callback.call(context);
44 };
45
46
47 Kernel.prototype._start_channels = function () {
48 var ws_url = "ws://127.0.0.1:8888" + this.kernel_url;
49 this.shell_channel = new WebSocket(ws_url + "/shell");
50 this.iopub_channel = new WebSocket(ws_url + "/iopub");
51 }
52
53
54 Kernel.prototype.execute = function (code) {
55 var content = {
56 code : code,
57 silent : false,
58 user_variables : [],
59 user_expressions : {}
60 };
61 var msg = this.get_msg("execute_request", content);
62 this.shell_channel.send(JSON.stringify(msg));
63 return msg.header.msg_id;
64 }
65
66
67 Kernel.prototype.interrupt = function () {
68 $.post(this.kernel_url + "/interrupt");
69 };
70
71
72 Kernel.prototype.restart = function () {
73 this.status_restarting();
74 url = this.kernel_url + "/restart"
75 var that = this;
76 $.post(url, function (kernel_id) {
77 console.log("Kernel restarted: " + kernel_id);
78 that.kernel_id = kernel_id;
79 that.kernel_url = that.base_url + "/" + that.kernel_id;
80 that.status_idle();
81 }, 'json');
82 };
83
84
85 Kernel.prototype.status_busy = function () {
86 $("#kernel_status").removeClass("status_idle");
87 $("#kernel_status").removeClass("status_restarting");
88 $("#kernel_status").addClass("status_busy");
89 $("#kernel_status").text("Busy");
90 };
91
92
93 Kernel.prototype.status_idle = function () {
94 $("#kernel_status").removeClass("status_busy");
95 $("#kernel_status").removeClass("status_restarting");
96 $("#kernel_status").addClass("status_idle");
97 $("#kernel_status").text("Idle");
98 };
99
100 Kernel.prototype.status_restarting = function () {
101 $("#kernel_status").removeClass("status_busy");
102 $("#kernel_status").removeClass("status_idle");
103 $("#kernel_status").addClass("status_restarting");
104 $("#kernel_status").text("Restarting");
105 };
106
107
@@ -0,0 +1,4 b''
1 var IPYTHON = {};
2
3
4
@@ -0,0 +1,62 b''
1
2 //============================================================================
3 // On document ready
4 //============================================================================
5
6
7 $(document).ready(function () {
8
9 $('div#wrapper').addClass('vbox border-box-sizing')
10 $('div.notebook').addClass('box-flex1 border-box-sizing')
11
12 MathJax.Hub.Config({
13 tex2jax: {
14 inlineMath: [ ['$','$'], ["\\(","\\)"] ],
15 displayMath: [ ['$$','$$'], ["\\[","\\]"] ],
16 },
17 displayAlign: 'left', // Change this to 'center' to center equations.
18 "HTML-CSS": {
19 styles: {'.MathJax_Display': {"margin": 0}}
20 }
21 });
22
23 IPYTHON.notebook = new Notebook('div.notebook');
24 IPYTHON.notebook.insert_code_cell_after();
25
26 $("#menu_tabs").tabs();
27
28 $("#help_toolbar").buttonset();
29
30 $("#kernel_toolbar").buttonset();
31 $("#interrupt_kernel").click(function () {IPYTHON.notebook.kernel.interrupt();});
32 $("#restart_kernel").click(function () {IPYTHON.notebook.kernel.restart();});
33 $("#kernel_status").addClass("status_idle");
34
35 $("#move_cell").buttonset();
36 $("#move_up").button("option", "icons", {primary:"ui-icon-arrowthick-1-n"});
37 $("#move_up").button("option", "text", false);
38 $("#move_up").click(function () {IPYTHON.notebook.move_cell_up();});
39 $("#move_down").button("option", "icons", {primary:"ui-icon-arrowthick-1-s"});
40 $("#move_down").button("option", "text", false);
41 $("#move_down").click(function () {IPYTHON.notebook.move_cell_down();});
42
43 $("#insert_delete").buttonset();
44 $("#insert_cell_before").click(function () {IPYTHON.notebook.insert_code_cell_before();});
45 $("#insert_cell_after").click(function () {IPYTHON.notebook.insert_code_cell_after();});
46 $("#delete_cell").button("option", "icons", {primary:"ui-icon-closethick"});
47 $("#delete_cell").button("option", "text", false);
48 $("#delete_cell").click(function () {IPYTHON.notebook.delete_cell();});
49
50 $("#cell_type").buttonset();
51 $("#to_code").click(function () {IPYTHON.notebook.text_to_code();});
52 $("#to_text").click(function () {IPYTHON.notebook.code_to_text();});
53
54 $("#sort").buttonset();
55 $("#sort_cells").click(function () {IPYTHON.notebook.sort_cells();});
56
57 $("#toggle").buttonset();
58 $("#collapse").click(function () {IPYTHON.notebook.collapse();});
59 $("#expand").click(function () {IPYTHON.notebook.expand();});
60
61 });
62
@@ -0,0 +1,144 b''
1
2 //============================================================================
3 // TextCell
4 //============================================================================
5
6
7 var TextCell = function (notebook) {
8 Cell.apply(this, arguments);
9 this.placeholder = "Type <strong>HTML</strong> and LaTeX: $\\alpha^2$"
10 this.rendered = false;
11 };
12
13
14 TextCell.prototype = new Cell();
15
16
17 TextCell.prototype.create_element = function () {
18 var cell = $("<div>").addClass('cell text_cell').
19 append(
20 $("<textarea>" + this.placeholder + "</textarea>").
21 addClass('text_cell_input monospace-font').
22 attr('rows',1).
23 attr('cols',80).
24 autogrow()
25 ).append(
26 // The tabindex=-1 makes this div focusable.
27 $('<div></div>').addClass('text_cell_render').attr('tabindex','-1')
28 )
29 this.element = cell;
30 };
31
32
33 TextCell.prototype.bind_events = function () {
34 Cell.prototype.bind_events.apply(this);
35 var that = this;
36 this.element.keydown(function (event) {
37 if (event.which === 13) {
38 if (that.rendered) {
39 that.edit();
40 event.preventDefault();
41 };
42 };
43 });
44 };
45
46
47 TextCell.prototype.select = function () {
48 Cell.prototype.select.apply(this);
49 var output = this.element.find("div.text_cell_render");
50 output.trigger('focus');
51 };
52
53
54 TextCell.prototype.edit = function () {
55 if (this.rendered === true) {
56 var text_cell = this.element;
57 var input = text_cell.find("textarea.text_cell_input");
58 var output = text_cell.find("div.text_cell_render");
59 output.hide();
60 input.show().trigger('focus');
61 this.rendered = false;
62 };
63 };
64
65
66 TextCell.prototype.render = function () {
67 if (this.rendered === false) {
68 var text_cell = this.element;
69 var input = text_cell.find("textarea.text_cell_input");
70 var output = text_cell.find("div.text_cell_render");
71 var text = input.val();
72 if (text === "") {
73 text = this.placeholder;
74 input.val(text);
75 };
76 output.html(text)
77 input.html(text);
78 MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
79 input.hide();
80 output.show();
81 this.rendered = true;
82 };
83 };
84
85
86 TextCell.prototype.config_mathjax = function () {
87 var text_cell = this.element;
88 var that = this;
89 text_cell.click(function () {
90 that.edit();
91 }).focusout(function () {
92 that.render();
93 });
94
95 text_cell.trigger("focusout");
96 };
97
98
99 TextCell.prototype.get_text = function() {
100 return this.element.find("textarea.text_cell_input").val();
101 };
102
103
104 TextCell.prototype.set_text = function(text) {
105 this.element.find("textarea.text_cell_input").val(text);
106 this.element.find("textarea.text_cell_input").html(text);
107 this.element.find("div.text_cell_render").html(text);
108 };
109
110
111 TextCell.prototype.at_top = function () {
112 if (this.rendered) {
113 return true;
114 } else {
115 return false;
116 }
117 };
118
119
120 TextCell.prototype.at_bottom = function () {
121 if (this.rendered) {
122 return true;
123 } else {
124 return false;
125 }
126 };
127
128
129 TextCell.prototype.fromJSON = function (data) {
130 if (data.cell_type === 'text') {
131 this.set_text(data.text);
132 this.grow(this.element.find("textarea.text_cell_input"));
133 };
134 }
135
136
137 TextCell.prototype.toJSON = function () {
138 return {
139 cell_type : 'text',
140 text : this.get_text(),
141 };
142 };
143
144
@@ -0,0 +1,62 b''
1
2 //============================================================================
3 // Utilities
4 //============================================================================
5
6
7 var uuid = function () {
8 // http://www.ietf.org/rfc/rfc4122.txt
9 var s = [];
10 var hexDigits = "0123456789ABCDEF";
11 for (var i = 0; i < 32; i++) {
12 s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
13 }
14 s[12] = "4"; // bits 12-15 of the time_hi_and_version field to 0010
15 s[16] = hexDigits.substr((s[16] & 0x3) | 0x8, 1); // bits 6-7 of the clock_seq_hi_and_reserved to 01
16
17 var uuid = s.join("");
18 return uuid;
19 };
20
21
22 //Fix raw text to parse correctly in crazy XML
23 function xmlencode(string) {
24 return string.replace(/\&/g,'&'+'amp;')
25 .replace(/</g,'&'+'lt;')
26 .replace(/>/g,'&'+'gt;')
27 .replace(/\'/g,'&'+'apos;')
28 .replace(/\"/g,'&'+'quot;')
29 .replace(/`/g,'&'+'#96;')
30 }
31
32 //Map from terminal commands to CSS classes
33 attrib = {
34 "30":"cblack", "31":"cred",
35 "32":"cgreen", "33":"cyellow",
36 "34":"cblue", "36":"ccyan",
37 "37":"cwhite", "01":"cbold"}
38
39 //Fixes escaped console commands, IE colors. Turns them into HTML
40 function fixConsole(txt) {
41 txt = xmlencode(txt)
42 var re = /\033\[([\d;]*?)m/
43 var opened = false
44 var cmds = []
45 var opener = ""
46 var closer = ""
47
48 while (re.test(txt)) {
49 var cmds = txt.match(re)[1].split(";")
50 closer = opened?"</span>":""
51 opened = cmds.length > 1 || cmds[0] != 0
52 var rep = []
53 for (var i in cmds)
54 if (typeof(attrib[cmds[i]]) != "undefined")
55 rep.push(attrib[cmds[i]])
56 opener = rep.length > 0?"<span class=\""+rep.join(" ")+"\">":""
57 txt = txt.replace(re, closer + opener)
58 }
59 if (opened) txt += "</span>"
60 return txt.trim()
61 }
62
This diff has been collapsed as it changes many lines, (637 lines changed) Show them Hide them
@@ -1,67 +1,3 b''
1 var IPYTHON = {};
2
3
4 //============================================================================
5 // Utilities
6 //============================================================================
7
8
9 var uuid = function () {
10 // http://www.ietf.org/rfc/rfc4122.txt
11 var s = [];
12 var hexDigits = "0123456789ABCDEF";
13 for (var i = 0; i < 32; i++) {
14 s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
15 }
16 s[12] = "4"; // bits 12-15 of the time_hi_and_version field to 0010
17 s[16] = hexDigits.substr((s[16] & 0x3) | 0x8, 1); // bits 6-7 of the clock_seq_hi_and_reserved to 01
18
19 var uuid = s.join("");
20 return uuid;
21 };
22
23
24 //Fix raw text to parse correctly in crazy XML
25 function xmlencode(string) {
26 return string.replace(/\&/g,'&'+'amp;')
27 .replace(/</g,'&'+'lt;')
28 .replace(/>/g,'&'+'gt;')
29 .replace(/\'/g,'&'+'apos;')
30 .replace(/\"/g,'&'+'quot;')
31 .replace(/`/g,'&'+'#96;')
32 }
33
34 //Map from terminal commands to CSS classes
35 attrib = {
36 "30":"cblack", "31":"cred",
37 "32":"cgreen", "33":"cyellow",
38 "34":"cblue", "36":"ccyan",
39 "37":"cwhite", "01":"cbold"}
40
41 //Fixes escaped console commands, IE colors. Turns them into HTML
42 function fixConsole(txt) {
43 txt = xmlencode(txt)
44 var re = /\033\[([\d;]*?)m/
45 var opened = false
46 var cmds = []
47 var opener = ""
48 var closer = ""
49
50 while (re.test(txt)) {
51 var cmds = txt.match(re)[1].split(";")
52 closer = opened?"</span>":""
53 opened = cmds.length > 1 || cmds[0] != 0
54 var rep = []
55 for (var i in cmds)
56 if (typeof(attrib[cmds[i]]) != "undefined")
57 rep.push(attrib[cmds[i]])
58 opener = rep.length > 0?"<span class=\""+rep.join(" ")+"\">":""
59 txt = txt.replace(re, closer + opener)
60 }
61 if (opened) txt += "</span>"
62 return txt.trim()
63 }
64
65
1
66 //============================================================================
2 //============================================================================
67 // Notebook
3 // Notebook
@@ -570,576 +506,3 b' Notebook.prototype.load_notebook = function (filename) {'
570 $.ajax("/notebooks/" + filename, settings);
506 $.ajax("/notebooks/" + filename, settings);
571 }
507 }
572
508
573
574 //============================================================================
575 // Cell
576 //============================================================================
577
578
579 var Cell = function (notebook) {
580 this.notebook = notebook;
581 this.selected = false;
582 this.element;
583 this.create_element();
584 if (this.element !== undefined) {
585 this.element.data("cell", this);
586 this.bind_events();
587 }
588 this.cell_id = uuid();
589 };
590
591
592 Cell.prototype.grow = function(element) {
593 // Grow the cell by hand. This is used upon reloading from JSON, when the
594 // autogrow handler is not called.
595 var dom = element.get(0);
596 var lines_count = 0;
597 // modified split rule from
598 // http://stackoverflow.com/questions/2035910/how-to-get-the-number-of-lines-in-a-textarea/2036424#2036424
599 var lines = dom.value.split(/\r|\r\n|\n/);
600 lines_count = lines.length;
601 if (lines_count >= 1) {
602 dom.rows = lines_count;
603 } else {
604 dom.rows = 1;
605 }
606 };
607
608
609 Cell.prototype.select = function () {
610 this.element.addClass('ui-widget-content ui-corner-all');
611 this.selected = true;
612 // TODO: we need t test across browsers to see if both of these are needed.
613 // In the meantime, there should not be any harm in having them both.
614 this.element.find('textarea').trigger('focusin');
615 this.element.find('textarea').trigger('focus');
616 };
617
618
619 Cell.prototype.unselect = function () {
620 this.element.removeClass('ui-widget-content ui-corner-all');
621 this.selected = false;
622 };
623
624
625 Cell.prototype.bind_events = function () {
626 var that = this;
627 var nb = that.notebook
628 that.element.click(function (event) {
629 if (that.selected === false) {
630 nb.select(nb.find_cell_index(that));
631 };
632 });
633 that.element.focusin(function (event) {
634 if (that.selected === false) {
635 nb.select(nb.find_cell_index(that));
636 };
637 });
638 };
639
640
641 // Subclasses must implement create_element.
642 Cell.prototype.create_element = function () {};
643
644
645 //============================================================================
646 // CodeCell
647 //============================================================================
648
649
650 var CodeCell = function (notebook) {
651 this.code_mirror = null;
652 this.input_prompt_number = ' ';
653 Cell.apply(this, arguments);
654 };
655
656
657 CodeCell.prototype = new Cell();
658
659
660 CodeCell.prototype.create_element = function () {
661 var cell = $('<div></div>').addClass('cell code_cell vbox border-box-sizing');
662 var input = $('<div></div>').addClass('input hbox border-box-sizing');
663 input.append($('<div/>').addClass('prompt input_prompt monospace-font'));
664 var input_area = $('<div/>').addClass('input_area box-flex1 border-box-sizing');
665 this.code_mirror = CodeMirror(input_area.get(0), {
666 indentUnit : 4,
667 enterMode : 'flat',
668 tabMode: 'shift'
669 });
670 input.append(input_area);
671 var output = $('<div></div>').addClass('output vbox border-box-sizing');
672 cell.append(input).append(output);
673 this.element = cell;
674 this.collapse()
675 };
676
677
678 CodeCell.prototype.select = function () {
679 Cell.prototype.select.apply(this);
680 this.code_mirror.focus();
681 };
682
683
684 CodeCell.prototype.append_pyout = function (data, n) {
685 var toinsert = $("<div/>").addClass("output_area output_pyout hbox monospace-font");
686 toinsert.append($('<div/>').
687 addClass('prompt output_prompt').
688 html('Out[' + n + ']:')
689 );
690 this.append_display_data(data, toinsert);
691 toinsert.children().last().addClass("box_flex1");
692 this.element.find("div.output").append(toinsert);
693 // If we just output latex, typeset it.
694 if (data["text/latex"] !== undefined) {
695 MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
696 };
697 };
698
699
700 CodeCell.prototype.append_pyerr = function (ename, evalue, tb) {
701 var s = '';
702 var len = tb.length;
703 for (var i=0; i<len; i++) {
704 s = s + tb[i] + '\n';
705 }
706 s = s + '\n';
707 this.append_stream(s);
708 };
709
710
711 CodeCell.prototype.append_display_data = function (data, element) {
712 console.log(data);
713 if (data["text/latex"] !== undefined) {
714 this.append_latex(data["text/latex"], element);
715 // If it is undefined, then we just appended to div.output, which
716 // makes the latex visible and we can typeset it. The typesetting
717 // has to be done after the latex is on the page.
718 if (element === undefined) {
719 MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
720 };
721 } else if (data["image/svg+xml"] !== undefined) {
722 this.append_svg(data["image/svg+xml"], element);
723 } else if (data["image/png"] !== undefined) {
724 this.append_png(data["image/png"], element);
725 } else if (data["text/plain"] !== undefined) {
726 this.append_stream(data["text/plain"], element);
727 };
728 return element;
729 };
730
731
732 CodeCell.prototype.append_stream = function (data, element) {
733 element = element || this.element.find("div.output");
734 var toinsert = $("<div/>").addClass("output_area output_stream monospace-font");
735 toinsert.append($("<pre/>").addClass("monospace-font").html(fixConsole(data)));
736 element.append(toinsert);
737 return element;
738 };
739
740
741 CodeCell.prototype.append_svg = function (svg, element) {
742 element = element || this.element.find("div.output");
743 var toinsert = $("<div/>").addClass("output_area output_svg");
744 toinsert.append(svg);
745 element.append(toinsert);
746 return element;
747 };
748
749
750 CodeCell.prototype.append_png = function (png, element) {
751 element = element || this.element.find("div.output");
752 var toinsert = $("<div/>").addClass("output_area output_png");
753 toinsert.append($("<img/>").attr('src','data:image/png;base64,'+png));
754 element.append(toinsert);
755 return element;
756 };
757
758
759 CodeCell.prototype.append_latex = function (latex, element) {
760 // This method cannot do the typesetting because the latex first has to
761 // be on the page.
762 element = element || this.element.find("div.output");
763 var toinsert = $("<div/>").addClass("output_area output_latex monospace-font");
764 toinsert.append(latex);
765 element.append(toinsert);
766 return element;
767 }
768
769
770 CodeCell.prototype.clear_output = function () {
771 this.element.find("div.output").html("");
772 };
773
774
775 CodeCell.prototype.collapse = function () {
776 this.element.find('div.output').hide();
777 };
778
779
780 CodeCell.prototype.expand = function () {
781 this.element.find('div.output').show();
782 };
783
784
785 CodeCell.prototype.set_input_prompt = function (number) {
786 var n = number || ' ';
787 this.input_prompt_number = n
788 this.element.find('div.input_prompt').html('In&nbsp;[' + n + ']:');
789 };
790
791
792 CodeCell.prototype.get_code = function () {
793 return this.code_mirror.getValue();
794 };
795
796
797 CodeCell.prototype.set_code = function (code) {
798 return this.code_mirror.setValue(code);
799 };
800
801
802 CodeCell.prototype.at_top = function () {
803 var cursor = this.code_mirror.getCursor();
804 if (cursor.line === 0) {
805 return true;
806 } else {
807 return false;
808 }
809 };
810
811
812 CodeCell.prototype.at_bottom = function () {
813 var cursor = this.code_mirror.getCursor();
814 if (cursor.line === (this.code_mirror.lineCount()-1)) {
815 return true;
816 } else {
817 return false;
818 }
819 };
820
821
822 CodeCell.prototype.fromJSON = function (data) {
823 if (data.cell_type === 'code') {
824 this.set_code(data.code);
825 this.set_input_prompt(data.prompt_number);
826 };
827 };
828
829
830 CodeCell.prototype.toJSON = function () {
831 return {
832 code : this.get_code(),
833 cell_type : 'code',
834 prompt_number : this.input_prompt_number
835 };
836 };
837
838 //============================================================================
839 // TextCell
840 //============================================================================
841
842
843 var TextCell = function (notebook) {
844 Cell.apply(this, arguments);
845 this.placeholder = "Type <strong>HTML</strong> and LaTeX: $\\alpha^2$"
846 this.rendered = false;
847 };
848
849
850 TextCell.prototype = new Cell();
851
852
853 TextCell.prototype.create_element = function () {
854 var cell = $("<div>").addClass('cell text_cell').
855 append(
856 $("<textarea>" + this.placeholder + "</textarea>").
857 addClass('text_cell_input monospace-font').
858 attr('rows',1).
859 attr('cols',80).
860 autogrow()
861 ).append(
862 // The tabindex=-1 makes this div focusable.
863 $('<div></div>').addClass('text_cell_render').attr('tabindex','-1')
864 )
865 this.element = cell;
866 };
867
868
869 TextCell.prototype.bind_events = function () {
870 Cell.prototype.bind_events.apply(this);
871 var that = this;
872 this.element.keydown(function (event) {
873 if (event.which === 13) {
874 if (that.rendered) {
875 that.edit();
876 event.preventDefault();
877 };
878 };
879 });
880 };
881
882
883 TextCell.prototype.select = function () {
884 Cell.prototype.select.apply(this);
885 var output = this.element.find("div.text_cell_render");
886 output.trigger('focus');
887 };
888
889
890 TextCell.prototype.edit = function () {
891 if (this.rendered === true) {
892 var text_cell = this.element;
893 var input = text_cell.find("textarea.text_cell_input");
894 var output = text_cell.find("div.text_cell_render");
895 output.hide();
896 input.show().trigger('focus');
897 this.rendered = false;
898 };
899 };
900
901
902 TextCell.prototype.render = function () {
903 if (this.rendered === false) {
904 var text_cell = this.element;
905 var input = text_cell.find("textarea.text_cell_input");
906 var output = text_cell.find("div.text_cell_render");
907 var text = input.val();
908 if (text === "") {
909 text = this.placeholder;
910 input.val(text);
911 };
912 output.html(text)
913 input.html(text);
914 MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
915 input.hide();
916 output.show();
917 this.rendered = true;
918 };
919 };
920
921
922 TextCell.prototype.config_mathjax = function () {
923 var text_cell = this.element;
924 var that = this;
925 text_cell.click(function () {
926 that.edit();
927 }).focusout(function () {
928 that.render();
929 });
930
931 text_cell.trigger("focusout");
932 };
933
934
935 TextCell.prototype.get_text = function() {
936 return this.element.find("textarea.text_cell_input").val();
937 };
938
939
940 TextCell.prototype.set_text = function(text) {
941 this.element.find("textarea.text_cell_input").val(text);
942 this.element.find("textarea.text_cell_input").html(text);
943 this.element.find("div.text_cell_render").html(text);
944 };
945
946
947 TextCell.prototype.at_top = function () {
948 if (this.rendered) {
949 return true;
950 } else {
951 return false;
952 }
953 };
954
955
956 TextCell.prototype.at_bottom = function () {
957 if (this.rendered) {
958 return true;
959 } else {
960 return false;
961 }
962 };
963
964
965 TextCell.prototype.fromJSON = function (data) {
966 if (data.cell_type === 'text') {
967 this.set_text(data.text);
968 this.grow(this.element.find("textarea.text_cell_input"));
969 };
970 }
971
972
973 TextCell.prototype.toJSON = function () {
974 return {
975 cell_type : 'text',
976 text : this.get_text(),
977 };
978 };
979
980 //============================================================================
981 // On document ready
982 //============================================================================
983
984
985 var Kernel = function () {
986 this.kernel_id = null;
987 this.base_url = "/kernels";
988 this.kernel_url = null;
989 };
990
991
992 Kernel.prototype.get_msg = function (msg_type, content) {
993 var msg = {
994 header : {
995 msg_id : uuid(),
996 username : "bgranger",
997 session: this.session_id,
998 msg_type : msg_type
999 },
1000 content : content,
1001 parent_header : {}
1002 };
1003 return msg;
1004 }
1005
1006 Kernel.prototype.start_kernel = function (callback, context) {
1007 var that = this;
1008 $.post(this.base_url,
1009 function (kernel_id) {
1010 that._handle_start_kernel(kernel_id, callback, context);
1011 },
1012 'json'
1013 );
1014 };
1015
1016
1017 Kernel.prototype._handle_start_kernel = function (kernel_id, callback, context) {
1018 this.kernel_id = kernel_id;
1019 this.kernel_url = this.base_url + "/" + this.kernel_id;
1020 this._start_channels();
1021 callback.call(context);
1022 };
1023
1024
1025 Kernel.prototype._start_channels = function () {
1026 var ws_url = "ws://127.0.0.1:8888" + this.kernel_url;
1027 this.shell_channel = new WebSocket(ws_url + "/shell");
1028 this.iopub_channel = new WebSocket(ws_url + "/iopub");
1029 }
1030
1031
1032 Kernel.prototype.execute = function (code) {
1033 var content = {
1034 code : code,
1035 silent : false,
1036 user_variables : [],
1037 user_expressions : {}
1038 };
1039 var msg = this.get_msg("execute_request", content);
1040 this.shell_channel.send(JSON.stringify(msg));
1041 return msg.header.msg_id;
1042 }
1043
1044
1045 Kernel.prototype.interrupt = function () {
1046 $.post(this.kernel_url + "/interrupt");
1047 };
1048
1049
1050 Kernel.prototype.restart = function () {
1051 this.status_restarting();
1052 url = this.kernel_url + "/restart"
1053 var that = this;
1054 $.post(url, function (kernel_id) {
1055 console.log("Kernel restarted: " + kernel_id);
1056 that.kernel_id = kernel_id;
1057 that.kernel_url = that.base_url + "/" + that.kernel_id;
1058 that.status_idle();
1059 }, 'json');
1060 };
1061
1062
1063 Kernel.prototype.status_busy = function () {
1064 $("#kernel_status").removeClass("status_idle");
1065 $("#kernel_status").removeClass("status_restarting");
1066 $("#kernel_status").addClass("status_busy");
1067 $("#kernel_status").text("Busy");
1068 };
1069
1070
1071 Kernel.prototype.status_idle = function () {
1072 $("#kernel_status").removeClass("status_busy");
1073 $("#kernel_status").removeClass("status_restarting");
1074 $("#kernel_status").addClass("status_idle");
1075 $("#kernel_status").text("Idle");
1076 };
1077
1078 Kernel.prototype.status_restarting = function () {
1079 $("#kernel_status").removeClass("status_busy");
1080 $("#kernel_status").removeClass("status_idle");
1081 $("#kernel_status").addClass("status_restarting");
1082 $("#kernel_status").text("Restarting");
1083 };
1084
1085 //============================================================================
1086 // On document ready
1087 //============================================================================
1088
1089
1090 $(document).ready(function () {
1091
1092 $('div#wrapper').addClass('vbox border-box-sizing')
1093 $('div.notebook').addClass('box-flex1 border-box-sizing')
1094
1095 MathJax.Hub.Config({
1096 tex2jax: {
1097 inlineMath: [ ['$','$'], ["\\(","\\)"] ],
1098 displayMath: [ ['$$','$$'], ["\\[","\\]"] ],
1099 },
1100 displayAlign: 'left', // Change this to 'center' to center equations.
1101 "HTML-CSS": {
1102 styles: {'.MathJax_Display': {"margin": 0}}
1103 }
1104 });
1105
1106 IPYTHON.notebook = new Notebook('div.notebook');
1107 IPYTHON.notebook.insert_code_cell_after();
1108
1109 $("#menu_tabs").tabs();
1110
1111 $("#help_toolbar").buttonset();
1112
1113 $("#kernel_toolbar").buttonset();
1114 $("#interrupt_kernel").click(function () {IPYTHON.notebook.kernel.interrupt();});
1115 $("#restart_kernel").click(function () {IPYTHON.notebook.kernel.restart();});
1116 $("#kernel_status").addClass("status_idle");
1117
1118 $("#move_cell").buttonset();
1119 $("#move_up").button("option", "icons", {primary:"ui-icon-arrowthick-1-n"});
1120 $("#move_up").button("option", "text", false);
1121 $("#move_up").click(function () {IPYTHON.notebook.move_cell_up();});
1122 $("#move_down").button("option", "icons", {primary:"ui-icon-arrowthick-1-s"});
1123 $("#move_down").button("option", "text", false);
1124 $("#move_down").click(function () {IPYTHON.notebook.move_cell_down();});
1125
1126 $("#insert_delete").buttonset();
1127 $("#insert_cell_before").click(function () {IPYTHON.notebook.insert_code_cell_before();});
1128 $("#insert_cell_after").click(function () {IPYTHON.notebook.insert_code_cell_after();});
1129 $("#delete_cell").button("option", "icons", {primary:"ui-icon-closethick"});
1130 $("#delete_cell").button("option", "text", false);
1131 $("#delete_cell").click(function () {IPYTHON.notebook.delete_cell();});
1132
1133 $("#cell_type").buttonset();
1134 $("#to_code").click(function () {IPYTHON.notebook.text_to_code();});
1135 $("#to_text").click(function () {IPYTHON.notebook.code_to_text();});
1136
1137 $("#sort").buttonset();
1138 $("#sort_cells").click(function () {IPYTHON.notebook.sort_cells();});
1139
1140 $("#toggle").buttonset();
1141 $("#collapse").click(function () {IPYTHON.notebook.collapse();});
1142 $("#expand").click(function () {IPYTHON.notebook.expand();});
1143
1144 });
1145
General Comments 0
You need to be logged in to leave comments. Login now