##// END OF EJS Templates
Clean up javascript based on js2-mode feedback.
Stefan van der Walt -
Show More
@@ -1,96 +1,96
1 //----------------------------------------------------------------------------
1 //----------------------------------------------------------------------------
2 // Copyright (C) 2008-2011 The IPython Development Team
2 // Copyright (C) 2008-2011 The IPython Development Team
3 //
3 //
4 // Distributed under the terms of the BSD License. The full license is in
4 // Distributed under the terms of the BSD License. The full license is in
5 // the file COPYING, distributed as part of this software.
5 // the file COPYING, distributed as part of this software.
6 //----------------------------------------------------------------------------
6 //----------------------------------------------------------------------------
7
7
8 //============================================================================
8 //============================================================================
9 // Cell
9 // Cell
10 //============================================================================
10 //============================================================================
11
11
12 var IPython = (function (IPython) {
12 var IPython = (function (IPython) {
13
13
14 var utils = IPython.utils;
14 var utils = IPython.utils;
15
15
16 var Cell = function (notebook) {
16 var Cell = function (notebook) {
17 this.notebook = notebook;
17 this.notebook = notebook;
18 this.read_only = false;
18 this.read_only = false;
19 if (notebook){
19 if (notebook){
20 this.read_only = notebook.read_only;
20 this.read_only = notebook.read_only;
21 }
21 }
22 this.selected = false;
22 this.selected = false;
23 this.element = null;
23 this.element = null;
24 this.create_element();
24 this.create_element();
25 if (this.element !== null) {
25 if (this.element !== null) {
26 this.set_autoindent(true);
26 this.set_autoindent(true);
27 this.element.data("cell", this);
27 this.element.data("cell", this);
28 this.bind_events();
28 this.bind_events();
29 }
29 }
30 this.cell_id = utils.uuid();
30 this.cell_id = utils.uuid();
31 };
31 };
32
32
33
33
34 Cell.prototype.select = function () {
34 Cell.prototype.select = function () {
35 this.element.addClass('ui-widget-content ui-corner-all');
35 this.element.addClass('ui-widget-content ui-corner-all');
36 this.selected = true;
36 this.selected = true;
37 };
37 };
38
38
39
39
40 Cell.prototype.unselect = function () {
40 Cell.prototype.unselect = function () {
41 this.element.removeClass('ui-widget-content ui-corner-all');
41 this.element.removeClass('ui-widget-content ui-corner-all');
42 this.selected = false;
42 this.selected = false;
43 };
43 };
44
44
45
45
46 Cell.prototype.bind_events = function () {
46 Cell.prototype.bind_events = function () {
47 var that = this;
47 var that = this;
48 var nb = that.notebook
48 var nb = that.notebook;
49 that.element.click(function (event) {
49 that.element.click(function (event) {
50 if (that.selected === false) {
50 if (that.selected === false) {
51 nb.select(nb.find_cell_index(that));
51 nb.select(nb.find_cell_index(that));
52 };
52 }
53 });
53 });
54 that.element.focusin(function (event) {
54 that.element.focusin(function (event) {
55 if (that.selected === false) {
55 if (that.selected === false) {
56 nb.select(nb.find_cell_index(that));
56 nb.select(nb.find_cell_index(that));
57 };
57 }
58 });
58 });
59 };
59 };
60
60
61 Cell.prototype.grow = function(element) {
61 Cell.prototype.grow = function(element) {
62 // Grow the cell by hand. This is used upon reloading from JSON, when the
62 // Grow the cell by hand. This is used upon reloading from JSON, when the
63 // autogrow handler is not called.
63 // autogrow handler is not called.
64 var dom = element.get(0);
64 var dom = element.get(0);
65 var lines_count = 0;
65 var lines_count = 0;
66 // modified split rule from
66 // modified split rule from
67 // http://stackoverflow.com/questions/2035910/how-to-get-the-number-of-lines-in-a-textarea/2036424#2036424
67 // http://stackoverflow.com/questions/2035910/how-to-get-the-number-of-lines-in-a-textarea/2036424#2036424
68 var lines = dom.value.split(/\r|\r\n|\n/);
68 var lines = dom.value.split(/\r|\r\n|\n/);
69 lines_count = lines.length;
69 lines_count = lines.length;
70 if (lines_count >= 1) {
70 if (lines_count >= 1) {
71 dom.rows = lines_count;
71 dom.rows = lines_count;
72 } else {
72 } else {
73 dom.rows = 1;
73 dom.rows = 1;
74 }
74 }
75 };
75 };
76
76
77
77
78 Cell.prototype.set_autoindent = function (state) {
78 Cell.prototype.set_autoindent = function (state) {
79 if (state) {
79 if (state) {
80 this.code_mirror.setOption('tabMode', 'indent');
80 this.code_mirror.setOption('tabMode', 'indent');
81 this.code_mirror.setOption('enterMode', 'indent');
81 this.code_mirror.setOption('enterMode', 'indent');
82 } else {
82 } else {
83 this.code_mirror.setOption('tabMode', 'shift');
83 this.code_mirror.setOption('tabMode', 'shift');
84 this.code_mirror.setOption('enterMode', 'flat');
84 this.code_mirror.setOption('enterMode', 'flat');
85 }
85 }
86 };
86 };
87
87
88 // Subclasses must implement create_element.
88 // Subclasses must implement create_element.
89 Cell.prototype.create_element = function () {};
89 Cell.prototype.create_element = function () {};
90
90
91 IPython.Cell = Cell;
91 IPython.Cell = Cell;
92
92
93 return IPython;
93 return IPython;
94
94
95 }(IPython));
95 }(IPython));
96
96
@@ -1,674 +1,675
1 //----------------------------------------------------------------------------
1 //----------------------------------------------------------------------------
2 // Copyright (C) 2008-2011 The IPython Development Team
2 // Copyright (C) 2008-2011 The IPython Development Team
3 //
3 //
4 // Distributed under the terms of the BSD License. The full license is in
4 // Distributed under the terms of the BSD License. The full license is in
5 // the file COPYING, distributed as part of this software.
5 // the file COPYING, distributed as part of this software.
6 //----------------------------------------------------------------------------
6 //----------------------------------------------------------------------------
7
7
8 //============================================================================
8 //============================================================================
9 // CodeCell
9 // CodeCell
10 //============================================================================
10 //============================================================================
11
11
12 var IPython = (function (IPython) {
12 var IPython = (function (IPython) {
13
13
14 var utils = IPython.utils;
14 var utils = IPython.utils;
15
15
16 var CodeCell = function (notebook) {
16 var CodeCell = function (notebook) {
17 this.code_mirror = null;
17 this.code_mirror = null;
18 this.input_prompt_number = ' ';
18 this.input_prompt_number = ' ';
19 this.is_completing = false;
19 this.is_completing = false;
20 this.completion_cursor = null;
20 this.completion_cursor = null;
21 this.outputs = [];
21 this.outputs = [];
22 this.collapsed = false;
22 this.collapsed = false;
23 IPython.Cell.apply(this, arguments);
23 IPython.Cell.apply(this, arguments);
24 };
24 };
25
25
26
26
27 CodeCell.prototype = new IPython.Cell();
27 CodeCell.prototype = new IPython.Cell();
28
28
29
29
30 CodeCell.prototype.create_element = function () {
30 CodeCell.prototype.create_element = function () {
31 var cell = $('<div></div>').addClass('cell border-box-sizing code_cell vbox');
31 var cell = $('<div></div>').addClass('cell border-box-sizing code_cell vbox');
32 cell.attr('tabindex','2');
32 cell.attr('tabindex','2');
33 var input = $('<div></div>').addClass('input hbox');
33 var input = $('<div></div>').addClass('input hbox');
34 input.append($('<div/>').addClass('prompt input_prompt'));
34 input.append($('<div/>').addClass('prompt input_prompt'));
35 var input_area = $('<div/>').addClass('input_area box-flex1');
35 var input_area = $('<div/>').addClass('input_area box-flex1');
36 this.code_mirror = CodeMirror(input_area.get(0), {
36 this.code_mirror = CodeMirror(input_area.get(0), {
37 indentUnit : 4,
37 indentUnit : 4,
38 mode: 'python',
38 mode: 'python',
39 theme: 'ipython',
39 theme: 'ipython',
40 readOnly: this.read_only,
40 readOnly: this.read_only,
41 onKeyEvent: $.proxy(this.handle_codemirror_keyevent,this)
41 onKeyEvent: $.proxy(this.handle_codemirror_keyevent,this)
42 });
42 });
43 input.append(input_area);
43 input.append(input_area);
44 var output = $('<div></div>').addClass('output vbox');
44 var output = $('<div></div>').addClass('output vbox');
45 cell.append(input).append(output);
45 cell.append(input).append(output);
46 this.element = cell;
46 this.element = cell;
47 this.collapse()
47 this.collapse();
48 };
48 };
49
49
50 //TODO, try to diminish the number of parameters.
50 //TODO, try to diminish the number of parameters.
51 CodeCell.prototype.request_tooltip_after_time = function (pre_cursor,time,that){
51 CodeCell.prototype.request_tooltip_after_time = function (pre_cursor,time,that){
52 if (pre_cursor === "" || pre_cursor === "(" ) {
52 if (pre_cursor === "" || pre_cursor === "(" ) {
53 // don't do anything if line beggin with '(' or is empty
53 // don't do anything if line beggin with '(' or is empty
54 } else {
54 } else {
55 // Will set a timer to request tooltip in `time`
55 // Will set a timer to request tooltip in `time`
56 that.tooltip_timeout = setTimeout(function(){
56 that.tooltip_timeout = setTimeout(function(){
57 IPython.notebook.request_tool_tip(that, pre_cursor)
57 IPython.notebook.request_tool_tip(that, pre_cursor)
58 },time);
58 },time);
59 }
59 }
60 };
60 };
61
61
62 CodeCell.prototype.handle_codemirror_keyevent = function (editor, event) {
62 CodeCell.prototype.handle_codemirror_keyevent = function (editor, event) {
63 // This method gets called in CodeMirror's onKeyDown/onKeyPress
63 // This method gets called in CodeMirror's onKeyDown/onKeyPress
64 // handlers and is used to provide custom key handling. Its return
64 // handlers and is used to provide custom key handling. Its return
65 // value is used to determine if CodeMirror should ignore the event:
65 // value is used to determine if CodeMirror should ignore the event:
66 // true = ignore, false = don't ignore.
66 // true = ignore, false = don't ignore.
67
67
68 // note that we are comparing and setting the time to wait at each key press.
68 // note that we are comparing and setting the time to wait at each key press.
69 // a better wqy might be to generate a new function on each time change and
69 // a better wqy might be to generate a new function on each time change and
70 // assign it to CodeCell.prototype.request_tooltip_after_time
70 // assign it to CodeCell.prototype.request_tooltip_after_time
71 tooltip_wait_time = this.notebook.time_before_tooltip;
71 tooltip_wait_time = this.notebook.time_before_tooltip;
72 tooltip_on_tab = this.notebook.tooltip_on_tab;
72 tooltip_on_tab = this.notebook.tooltip_on_tab;
73 var that = this;
73 var that = this;
74 // whatever key is pressed, first, cancel the tooltip request before
74 // whatever key is pressed, first, cancel the tooltip request before
75 // they are sent, and remove tooltip if any
75 // they are sent, and remove tooltip if any
76 if(event.type === 'keydown' && this.tooltip_timeout != null){
76 if(event.type === 'keydown' && this.tooltip_timeout != null){
77 CodeCell.prototype.remove_and_cancell_tooltip(that.tooltip_timeout);
77 CodeCell.prototype.remove_and_cancell_tooltip(that.tooltip_timeout);
78 that.tooltip_timeout=null;
78 that.tooltip_timeout=null;
79 }
79 }
80
80
81 if (event.keyCode === 13 && (event.shiftKey || event.ctrlKey)) {
81 if (event.keyCode === 13 && (event.shiftKey || event.ctrlKey)) {
82 // Always ignore shift-enter in CodeMirror as we handle it.
82 // Always ignore shift-enter in CodeMirror as we handle it.
83 return true;
83 return true;
84 }else if (event.which === 40 && event.type === 'keypress' && tooltip_wait_time >= 0) {
84 }else if (event.which === 40 && event.type === 'keypress' && tooltip_wait_time >= 0) {
85 // triger aon keypress (!) otherwise inconsistent event.which depending on plateform
85 // triger aon keypress (!) otherwise inconsistent event.which depending on plateform
86 // browser and keyboard layout !
86 // browser and keyboard layout !
87 // Pressing '(' , request tooltip, don't forget to reappend it
87 // Pressing '(' , request tooltip, don't forget to reappend it
88 var cursor = editor.getCursor();
88 var cursor = editor.getCursor();
89 var pre_cursor = editor.getRange({line:cursor.line,ch:0},cursor).trim()+'(';
89 var pre_cursor = editor.getRange({line:cursor.line,ch:0},cursor).trim()+'(';
90 CodeCell.prototype.request_tooltip_after_time(pre_cursor,tooltip_wait_time,that);
90 CodeCell.prototype.request_tooltip_after_time(pre_cursor,tooltip_wait_time,that);
91 } else if (event.keyCode === 9 && event.type == 'keydown') {
91 } else if (event.keyCode === 9 && event.type == 'keydown') {
92 // Tab completion.
92 // Tab completion.
93 var cur = editor.getCursor();
93 var cur = editor.getCursor();
94 //Do not trim here because of tooltip
94 //Do not trim here because of tooltip
95 var pre_cursor = editor.getRange({line:cur.line,ch:0},cur);
95 var pre_cursor = editor.getRange({line:cur.line,ch:0},cur);
96 if (pre_cursor.trim() === "") {
96 if (pre_cursor.trim() === "") {
97 // Don't autocomplete if the part of the line before the cursor
97 // Don't autocomplete if the part of the line before the cursor
98 // is empty. In this case, let CodeMirror handle indentation.
98 // is empty. In this case, let CodeMirror handle indentation.
99 return false;
99 return false;
100 } else if ((pre_cursor.substr(-1) === "("|| pre_cursor.substr(-1) === " ") && tooltip_on_tab ) {
100 } else if ((pre_cursor.substr(-1) === "("|| pre_cursor.substr(-1) === " ") && tooltip_on_tab ) {
101 CodeCell.prototype.request_tooltip_after_time(pre_cursor,0,that);
101 CodeCell.prototype.request_tooltip_after_time(pre_cursor,0,that);
102 } else {
102 } else {
103 pre_cursor.trim();
103 pre_cursor.trim();
104 // Autocomplete the current line.
104 // Autocomplete the current line.
105 event.stop();
105 event.stop();
106 var line = editor.getLine(cur.line);
106 var line = editor.getLine(cur.line);
107 this.is_completing = true;
107 this.is_completing = true;
108 this.completion_cursor = cur;
108 this.completion_cursor = cur;
109 IPython.notebook.complete_cell(this, line, cur.ch);
109 IPython.notebook.complete_cell(this, line, cur.ch);
110 return true;
110 return true;
111 }
111 }
112 } else if (event.keyCode === 8 && event.type == 'keydown') {
112 } else if (event.keyCode === 8 && event.type == 'keydown') {
113 // If backspace and the line ends with 4 spaces, remove them.
113 // If backspace and the line ends with 4 spaces, remove them.
114 var cur = editor.getCursor();
114 var cur = editor.getCursor();
115 var line = editor.getLine(cur.line);
115 var line = editor.getLine(cur.line);
116 var ending = line.slice(-4);
116 var ending = line.slice(-4);
117 if (ending === ' ') {
117 if (ending === ' ') {
118 editor.replaceRange('',
118 editor.replaceRange('',
119 {line: cur.line, ch: cur.ch-4},
119 {line: cur.line, ch: cur.ch-4},
120 {line: cur.line, ch: cur.ch}
120 {line: cur.line, ch: cur.ch}
121 );
121 );
122 event.stop();
122 event.stop();
123 return true;
123 return true;
124 } else {
124 } else {
125 return false;
125 return false;
126 };
126 }
127 } else if (event.keyCode === 76 && event.ctrlKey && event.shiftKey
127 } else if (event.keyCode === 76 && event.ctrlKey && event.shiftKey
128 && event.type == 'keydown') {
128 && event.type == 'keydown') {
129 // toggle line numbers with Ctrl-Shift-L
129 // toggle line numbers with Ctrl-Shift-L
130 this.toggle_line_numbers();
130 this.toggle_line_numbers();
131 }
131 }
132 else {
132 else {
133 // keypress/keyup also trigger on TAB press, and we don't want to
133 // keypress/keyup also trigger on TAB press, and we don't want to
134 // use those to disable tab completion.
134 // use those to disable tab completion.
135 if (this.is_completing && event.keyCode !== 9) {
135 if (this.is_completing && event.keyCode !== 9) {
136 var ed_cur = editor.getCursor();
136 var ed_cur = editor.getCursor();
137 var cc_cur = this.completion_cursor;
137 var cc_cur = this.completion_cursor;
138 if (ed_cur.line !== cc_cur.line || ed_cur.ch !== cc_cur.ch) {
138 if (ed_cur.line !== cc_cur.line || ed_cur.ch !== cc_cur.ch) {
139 this.is_completing = false;
139 this.is_completing = false;
140 this.completion_cursor = null;
140 this.completion_cursor = null;
141 };
141 }
142 };
142 }
143 return false;
143 return false;
144 };
144 };
145 return false;
145 };
146 };
146
147
147 CodeCell.prototype.remove_and_cancell_tooltip = function(timeout)
148 CodeCell.prototype.remove_and_cancell_tooltip = function(timeout)
148 {
149 {
149 // note that we don't handle closing directly inside the calltip
150 // note that we don't handle closing directly inside the calltip
150 // as in the completer, because it is not focusable, so won't
151 // as in the completer, because it is not focusable, so won't
151 // get the event.
152 // get the event.
152 clearTimeout(timeout);
153 clearTimeout(timeout);
153 $('#tooltip').remove();
154 $('#tooltip').remove();
154 }
155 }
155
156
156 CodeCell.prototype.finish_tooltip = function (reply) {
157 CodeCell.prototype.finish_tooltip = function (reply) {
157 defstring=reply.definition;
158 defstring=reply.definition;
158 docstring=reply.docstring;
159 docstring=reply.docstring;
159 if(docstring == null){docstring="<empty docstring>"};
160 if(docstring == null){docstring="<empty docstring>"};
160 name=reply.name;
161 name=reply.name;
161
162
162 var that = this;
163 var that = this;
163 var tooltip = $('<div/>').attr('id', 'tooltip').addClass('tooltip');
164 var tooltip = $('<div/>').attr('id', 'tooltip').addClass('tooltip');
164 // remove to have the tooltip not Limited in X and Y
165 // remove to have the tooltip not Limited in X and Y
165 tooltip.addClass('smalltooltip');
166 tooltip.addClass('smalltooltip');
166 var pre=$('<pre/>').html(utils.fixConsole(docstring));
167 var pre=$('<pre/>').html(utils.fixConsole(docstring));
167 var expandlink=$('<a/>').attr('href',"#");
168 var expandlink=$('<a/>').attr('href',"#");
168 expandlink.addClass("ui-corner-all"); //rounded corner
169 expandlink.addClass("ui-corner-all"); //rounded corner
169 expandlink.attr('role',"button");
170 expandlink.attr('role',"button");
170 //expandlink.addClass('ui-button');
171 //expandlink.addClass('ui-button');
171 //expandlink.addClass('ui-state-default');
172 //expandlink.addClass('ui-state-default');
172 var expandspan=$('<span/>').text('Expand');
173 var expandspan=$('<span/>').text('Expand');
173 expandspan.addClass('ui-icon');
174 expandspan.addClass('ui-icon');
174 expandspan.addClass('ui-icon-plus');
175 expandspan.addClass('ui-icon-plus');
175 expandlink.append(expandspan);
176 expandlink.append(expandspan);
176 expandlink.attr('id','expanbutton');
177 expandlink.attr('id','expanbutton');
177 expandlink.click(function(){
178 expandlink.click(function(){
178 tooltip.removeClass('smalltooltip');
179 tooltip.removeClass('smalltooltip');
179 tooltip.addClass('bigtooltip');
180 tooltip.addClass('bigtooltip');
180 $('#expanbutton').remove();
181 $('#expanbutton').remove();
181 setTimeout(function(){that.code_mirror.focus();}, 50);
182 setTimeout(function(){that.code_mirror.focus();}, 50);
182 });
183 });
183 var morelink=$('<a/>').attr('href',"#");
184 var morelink=$('<a/>').attr('href',"#");
184 morelink.attr('role',"button");
185 morelink.attr('role',"button");
185 morelink.addClass('ui-button');
186 morelink.addClass('ui-button');
186 //morelink.addClass("ui-corner-all"); //rounded corner
187 //morelink.addClass("ui-corner-all"); //rounded corner
187 //morelink.addClass('ui-state-default');
188 //morelink.addClass('ui-state-default');
188 var morespan=$('<span/>').text('Open in Pager');
189 var morespan=$('<span/>').text('Open in Pager');
189 morespan.addClass('ui-icon');
190 morespan.addClass('ui-icon');
190 morespan.addClass('ui-icon-arrowstop-l-n');
191 morespan.addClass('ui-icon-arrowstop-l-n');
191 morelink.append(morespan);
192 morelink.append(morespan);
192 morelink.click(function(){
193 morelink.click(function(){
193 var msg_id = IPython.notebook.kernel.execute(name+"?");
194 var msg_id = IPython.notebook.kernel.execute(name+"?");
194 IPython.notebook.msg_cell_map[msg_id] = IPython.notebook.selected_cell().cell_id;
195 IPython.notebook.msg_cell_map[msg_id] = IPython.notebook.selected_cell().cell_id;
195 CodeCell.prototype.remove_and_cancell_tooltip(that.tooltip_timeout);
196 CodeCell.prototype.remove_and_cancell_tooltip(that.tooltip_timeout);
196 setTimeout(function(){that.code_mirror.focus();}, 50);
197 setTimeout(function(){that.code_mirror.focus();}, 50);
197 });
198 });
198
199
199 var closelink=$('<a/>').attr('href',"#");
200 var closelink=$('<a/>').attr('href',"#");
200 closelink.attr('role',"button");
201 closelink.attr('role',"button");
201 closelink.addClass('ui-button');
202 closelink.addClass('ui-button');
202 //closelink.addClass("ui-corner-all"); //rounded corner
203 //closelink.addClass("ui-corner-all"); //rounded corner
203 //closelink.adClass('ui-state-default'); // grey background and blue cross
204 //closelink.adClass('ui-state-default'); // grey background and blue cross
204 var closespan=$('<span/>').text('Close');
205 var closespan=$('<span/>').text('Close');
205 closespan.addClass('ui-icon');
206 closespan.addClass('ui-icon');
206 closespan.addClass('ui-icon-close');
207 closespan.addClass('ui-icon-close');
207 closelink.append(closespan);
208 closelink.append(closespan);
208 closelink.click(function(){
209 closelink.click(function(){
209 CodeCell.prototype.remove_and_cancell_tooltip(that.tooltip_timeout);
210 CodeCell.prototype.remove_and_cancell_tooltip(that.tooltip_timeout);
210 setTimeout(function(){that.code_mirror.focus();}, 50);
211 setTimeout(function(){that.code_mirror.focus();}, 50);
211 });
212 });
212 //construct the tooltip
213 //construct the tooltip
213 tooltip.append(closelink);
214 tooltip.append(closelink);
214 tooltip.append(expandlink);
215 tooltip.append(expandlink);
215 tooltip.append(morelink);
216 tooltip.append(morelink);
216 if(defstring){
217 if(defstring){
217 defstring_html= $('<pre/>').html(utils.fixConsole(defstring));
218 defstring_html= $('<pre/>').html(utils.fixConsole(defstring));
218 tooltip.append(defstring_html);
219 tooltip.append(defstring_html);
219 }
220 }
220 tooltip.append(pre);
221 tooltip.append(pre);
221 var pos = this.code_mirror.cursorCoords();
222 var pos = this.code_mirror.cursorCoords();
222 tooltip.css('left',pos.x+'px');
223 tooltip.css('left',pos.x+'px');
223 tooltip.css('top',pos.yBot+'px');
224 tooltip.css('top',pos.yBot+'px');
224 $('body').append(tooltip);
225 $('body').append(tooltip);
225
226
226 // issues with cross-closing if multiple tooltip in less than 5sec
227 // issues with cross-closing if multiple tooltip in less than 5sec
227 // keep it comented for now
228 // keep it comented for now
228 // setTimeout(CodeCell.prototype.remove_and_cancell_tooltip, 5000);
229 // setTimeout(CodeCell.prototype.remove_and_cancell_tooltip, 5000);
229 };
230 };
230
231
231
232
232 CodeCell.prototype.finish_completing = function (matched_text, matches) {
233 CodeCell.prototype.finish_completing = function (matched_text, matches) {
233 // console.log("Got matches", matched_text, matches);
234 // console.log("Got matches", matched_text, matches);
234 var newm = new Array();
235 var newm = new Array();
235 if(this.notebook.smart_completer)
236 if(this.notebook.smart_completer)
236 {
237 {
237 kwargs = new Array();
238 kwargs = new Array();
238 other = new Array();
239 other = new Array();
239 for(var i=0;i<matches.length; ++i){
240 for(var i=0;i<matches.length; ++i){
240 if(matches[i].substr(-1) === '='){
241 if(matches[i].substr(-1) === '='){
241 kwargs.push(matches[i]);
242 kwargs.push(matches[i]);
242 }else{other.push(matches[i]);}
243 }else{other.push(matches[i]);}
243 }
244 }
244 newm = kwargs.concat(other);
245 newm = kwargs.concat(other);
245 matches=newm;
246 matches=newm;
246 }
247 }
247 if (!this.is_completing || matches.length === 0) {return;}
248 if (!this.is_completing || matches.length === 0) {return;}
248
249
249 //try to check if the user is typing tab at least twice after a word
250 //try to check if the user is typing tab at least twice after a word
250 // and completion is "done"
251 // and completion is "done"
251 fallback_on_tooltip_after=2
252 fallback_on_tooltip_after=2
252 if(matches.length==1 && matched_text === matches[0])
253 if(matches.length==1 && matched_text === matches[0])
253 {
254 {
254 if(this.npressed >fallback_on_tooltip_after && this.prevmatch==matched_text)
255 if(this.npressed >fallback_on_tooltip_after && this.prevmatch==matched_text)
255 {
256 {
256 console.log('Ok, you really want to complete after pressing tab '+this.npressed+' times !');
257 console.log('Ok, you really want to complete after pressing tab '+this.npressed+' times !');
257 console.log('You should understand that there is no (more) completion for that !');
258 console.log('You should understand that there is no (more) completion for that !');
258 console.log("I'll show you the tooltip, will you stop bothering me ?");
259 console.log("I'll show you the tooltip, will you stop bothering me ?");
259 this.request_tooltip_after_time(matched_text+'(',0,this);
260 this.request_tooltip_after_time(matched_text+'(',0,this);
260 return;
261 return;
261 }
262 }
262 this.prevmatch=matched_text
263 this.prevmatch=matched_text
263 this.npressed=this.npressed+1;
264 this.npressed=this.npressed+1;
264 }
265 }
265 else
266 else
266 {
267 {
267 this.prevmatch="";
268 this.prevmatch="";
268 this.npressed=0;
269 this.npressed=0;
269 }
270 }
270
271
271 var that = this;
272 var that = this;
272 var cur = this.completion_cursor;
273 var cur = this.completion_cursor;
273
274
274 var insert = function (selected_text) {
275 var insert = function (selected_text) {
275 that.code_mirror.replaceRange(
276 that.code_mirror.replaceRange(
276 selected_text,
277 selected_text,
277 {line: cur.line, ch: (cur.ch-matched_text.length)},
278 {line: cur.line, ch: (cur.ch-matched_text.length)},
278 {line: cur.line, ch: cur.ch}
279 {line: cur.line, ch: cur.ch}
279 );
280 );
280 };
281 };
281
282
282 if (matches.length === 1) {
283 if (matches.length === 1) {
283 insert(matches[0]);
284 insert(matches[0]);
284 setTimeout(function(){that.code_mirror.focus();}, 50);
285 setTimeout(function(){that.code_mirror.focus();}, 50);
285 return;
286 return;
286 };
287 };
287
288
288 var complete = $('<div/>').addClass('completions');
289 var complete = $('<div/>').addClass('completions');
289 var select = $('<select/>').attr('multiple','true');
290 var select = $('<select/>').attr('multiple','true');
290 for (var i=0; i<matches.length; ++i) {
291 for (var i=0; i<matches.length; ++i) {
291 select.append($('<option/>').text(matches[i]));
292 select.append($('<option/>').text(matches[i]));
292 }
293 }
293 select.children().first().attr('selected','true');
294 select.children().first().attr('selected','true');
294 select.attr('size',Math.min(10,matches.length));
295 select.attr('size',Math.min(10,matches.length));
295 var pos = this.code_mirror.cursorCoords();
296 var pos = this.code_mirror.cursorCoords();
296 complete.css('left',pos.x+'px');
297 complete.css('left',pos.x+'px');
297 complete.css('top',pos.yBot+'px');
298 complete.css('top',pos.yBot+'px');
298 complete.append(select);
299 complete.append(select);
299
300
300 $('body').append(complete);
301 $('body').append(complete);
301 var done = false;
302 var done = false;
302
303
303 var close = function () {
304 var close = function () {
304 if (done) return;
305 if (done) return;
305 done = true;
306 done = true;
306 complete.remove();
307 complete.remove();
307 that.is_completing = false;
308 that.is_completing = false;
308 that.completion_cursor = null;
309 that.completion_cursor = null;
309 };
310 };
310
311
311 var pick = function () {
312 var pick = function () {
312 insert(select.val()[0]);
313 insert(select.val()[0]);
313 close();
314 close();
314 setTimeout(function(){that.code_mirror.focus();}, 50);
315 setTimeout(function(){that.code_mirror.focus();}, 50);
315 };
316 };
316
317
317 select.blur(close);
318 select.blur(close);
318 select.keydown(function (event) {
319 select.keydown(function (event) {
319 var code = event.which;
320 var code = event.which;
320 if (code === 13 || code === 32) {
321 if (code === 13 || code === 32) {
321 // Pressing SPACE or ENTER will cause a pick
322 // Pressing SPACE or ENTER will cause a pick
322 event.stopPropagation();
323 event.stopPropagation();
323 event.preventDefault();
324 event.preventDefault();
324 pick();
325 pick();
325 } else if (code === 38 || code === 40) {
326 } else if (code === 38 || code === 40) {
326 // We don't want the document keydown handler to handle UP/DOWN,
327 // We don't want the document keydown handler to handle UP/DOWN,
327 // but we want the default action.
328 // but we want the default action.
328 event.stopPropagation();
329 event.stopPropagation();
329 } else {
330 } else {
330 // All other key presses exit completion.
331 // All other key presses exit completion.
331 event.stopPropagation();
332 event.stopPropagation();
332 event.preventDefault();
333 event.preventDefault();
333 close();
334 close();
334 that.code_mirror.focus();
335 that.code_mirror.focus();
335 }
336 }
336 });
337 });
337 // Double click also causes a pick.
338 // Double click also causes a pick.
338 select.dblclick(pick);
339 select.dblclick(pick);
339 select.focus();
340 select.focus();
340 };
341 };
341
342
342 CodeCell.prototype.toggle_line_numbers = function () {
343 CodeCell.prototype.toggle_line_numbers = function () {
343 if (this.code_mirror.getOption('lineNumbers') == false) {
344 if (this.code_mirror.getOption('lineNumbers') == false) {
344 this.code_mirror.setOption('lineNumbers', true);
345 this.code_mirror.setOption('lineNumbers', true);
345 } else {
346 } else {
346 this.code_mirror.setOption('lineNumbers', false);
347 this.code_mirror.setOption('lineNumbers', false);
347 }
348 }
348 this.code_mirror.refresh()
349 this.code_mirror.refresh();
349 };
350 };
350
351
351 CodeCell.prototype.select = function () {
352 CodeCell.prototype.select = function () {
352 IPython.Cell.prototype.select.apply(this);
353 IPython.Cell.prototype.select.apply(this);
353 // Todo: this dance is needed because as of CodeMirror 2.12, focus is
354 // Todo: this dance is needed because as of CodeMirror 2.12, focus is
354 // not causing the cursor to blink if the editor is empty initially.
355 // not causing the cursor to blink if the editor is empty initially.
355 // While this seems to fix the issue, this should be fixed
356 // While this seems to fix the issue, this should be fixed
356 // in CodeMirror proper.
357 // in CodeMirror proper.
357 var s = this.code_mirror.getValue();
358 var s = this.code_mirror.getValue();
358 this.code_mirror.focus();
359 this.code_mirror.focus();
359 if (s === '') this.code_mirror.setValue('');
360 if (s === '') this.code_mirror.setValue('');
360 };
361 };
361
362
362
363
363 CodeCell.prototype.select_all = function () {
364 CodeCell.prototype.select_all = function () {
364 var start = {line: 0, ch: 0};
365 var start = {line: 0, ch: 0};
365 var nlines = this.code_mirror.lineCount();
366 var nlines = this.code_mirror.lineCount();
366 var last_line = this.code_mirror.getLine(nlines-1);
367 var last_line = this.code_mirror.getLine(nlines-1);
367 var end = {line: nlines-1, ch: last_line.length};
368 var end = {line: nlines-1, ch: last_line.length};
368 this.code_mirror.setSelection(start, end);
369 this.code_mirror.setSelection(start, end);
369 };
370 };
370
371
371
372
372 CodeCell.prototype.append_output = function (json) {
373 CodeCell.prototype.append_output = function (json) {
373 this.expand();
374 this.expand();
374 if (json.output_type === 'pyout') {
375 if (json.output_type === 'pyout') {
375 this.append_pyout(json);
376 this.append_pyout(json);
376 } else if (json.output_type === 'pyerr') {
377 } else if (json.output_type === 'pyerr') {
377 this.append_pyerr(json);
378 this.append_pyerr(json);
378 } else if (json.output_type === 'display_data') {
379 } else if (json.output_type === 'display_data') {
379 this.append_display_data(json);
380 this.append_display_data(json);
380 } else if (json.output_type === 'stream') {
381 } else if (json.output_type === 'stream') {
381 this.append_stream(json);
382 this.append_stream(json);
382 };
383 };
383 this.outputs.push(json);
384 this.outputs.push(json);
384 };
385 };
385
386
386
387
387 CodeCell.prototype.create_output_area = function () {
388 CodeCell.prototype.create_output_area = function () {
388 var oa = $("<div/>").addClass("hbox output_area");
389 var oa = $("<div/>").addClass("hbox output_area");
389 oa.append($('<div/>').addClass('prompt'));
390 oa.append($('<div/>').addClass('prompt'));
390 return oa;
391 return oa;
391 };
392 };
392
393
393
394
394 CodeCell.prototype.append_pyout = function (json) {
395 CodeCell.prototype.append_pyout = function (json) {
395 n = json.prompt_number || ' ';
396 n = json.prompt_number || ' ';
396 var toinsert = this.create_output_area();
397 var toinsert = this.create_output_area();
397 toinsert.find('div.prompt').addClass('output_prompt').html('Out[' + n + ']:');
398 toinsert.find('div.prompt').addClass('output_prompt').html('Out[' + n + ']:');
398 this.append_mime_type(json, toinsert);
399 this.append_mime_type(json, toinsert);
399 this.element.find('div.output').append(toinsert);
400 this.element.find('div.output').append(toinsert);
400 // If we just output latex, typeset it.
401 // If we just output latex, typeset it.
401 if ((json.latex !== undefined) || (json.html !== undefined)) {
402 if ((json.latex !== undefined) || (json.html !== undefined)) {
402 MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
403 MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
403 };
404 };
404 };
405 };
405
406
406
407
407 CodeCell.prototype.append_pyerr = function (json) {
408 CodeCell.prototype.append_pyerr = function (json) {
408 var tb = json.traceback;
409 var tb = json.traceback;
409 if (tb !== undefined && tb.length > 0) {
410 if (tb !== undefined && tb.length > 0) {
410 var s = '';
411 var s = '';
411 var len = tb.length;
412 var len = tb.length;
412 for (var i=0; i<len; i++) {
413 for (var i=0; i<len; i++) {
413 s = s + tb[i] + '\n';
414 s = s + tb[i] + '\n';
414 }
415 }
415 s = s + '\n';
416 s = s + '\n';
416 var toinsert = this.create_output_area();
417 var toinsert = this.create_output_area();
417 this.append_text(s, toinsert);
418 this.append_text(s, toinsert);
418 this.element.find('div.output').append(toinsert);
419 this.element.find('div.output').append(toinsert);
419 };
420 };
420 };
421 };
421
422
422
423
423 CodeCell.prototype.append_stream = function (json) {
424 CodeCell.prototype.append_stream = function (json) {
424 // temporary fix: if stream undefined (json file written prior to this patch),
425 // temporary fix: if stream undefined (json file written prior to this patch),
425 // default to most likely stdout:
426 // default to most likely stdout:
426 if (json.stream == undefined){
427 if (json.stream == undefined){
427 json.stream = 'stdout';
428 json.stream = 'stdout';
428 }
429 }
429 var subclass = "output_"+json.stream;
430 var subclass = "output_"+json.stream;
430 if (this.outputs.length > 0){
431 if (this.outputs.length > 0){
431 // have at least one output to consider
432 // have at least one output to consider
432 var last = this.outputs[this.outputs.length-1];
433 var last = this.outputs[this.outputs.length-1];
433 if (last.output_type == 'stream' && json.stream == last.stream){
434 if (last.output_type == 'stream' && json.stream == last.stream){
434 // latest output was in the same stream,
435 // latest output was in the same stream,
435 // so append directly into its pre tag
436 // so append directly into its pre tag
436 this.element.find('div.'+subclass).last().find('pre').append(json.text);
437 this.element.find('div.'+subclass).last().find('pre').append(json.text);
437 return;
438 return;
438 }
439 }
439 }
440 }
440
441
441 // If we got here, attach a new div
442 // If we got here, attach a new div
442 var toinsert = this.create_output_area();
443 var toinsert = this.create_output_area();
443 this.append_text(json.text, toinsert, "output_stream "+subclass);
444 this.append_text(json.text, toinsert, "output_stream "+subclass);
444 this.element.find('div.output').append(toinsert);
445 this.element.find('div.output').append(toinsert);
445 };
446 };
446
447
447
448
448 CodeCell.prototype.append_display_data = function (json) {
449 CodeCell.prototype.append_display_data = function (json) {
449 var toinsert = this.create_output_area();
450 var toinsert = this.create_output_area();
450 this.append_mime_type(json, toinsert)
451 this.append_mime_type(json, toinsert);
451 this.element.find('div.output').append(toinsert);
452 this.element.find('div.output').append(toinsert);
452 // If we just output latex, typeset it.
453 // If we just output latex, typeset it.
453 if ( (json.latex !== undefined) || (json.html !== undefined) ) {
454 if ( (json.latex !== undefined) || (json.html !== undefined) ) {
454 MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
455 MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
455 };
456 };
456 };
457 };
457
458
458
459
459 CodeCell.prototype.append_mime_type = function (json, element) {
460 CodeCell.prototype.append_mime_type = function (json, element) {
460 if (json.html !== undefined) {
461 if (json.html !== undefined) {
461 this.append_html(json.html, element);
462 this.append_html(json.html, element);
462 } else if (json.latex !== undefined) {
463 } else if (json.latex !== undefined) {
463 this.append_latex(json.latex, element);
464 this.append_latex(json.latex, element);
464 } else if (json.svg !== undefined) {
465 } else if (json.svg !== undefined) {
465 this.append_svg(json.svg, element);
466 this.append_svg(json.svg, element);
466 } else if (json.png !== undefined) {
467 } else if (json.png !== undefined) {
467 this.append_png(json.png, element);
468 this.append_png(json.png, element);
468 } else if (json.jpeg !== undefined) {
469 } else if (json.jpeg !== undefined) {
469 this.append_jpeg(json.jpeg, element);
470 this.append_jpeg(json.jpeg, element);
470 } else if (json.text !== undefined) {
471 } else if (json.text !== undefined) {
471 this.append_text(json.text, element);
472 this.append_text(json.text, element);
472 };
473 };
473 };
474 };
474
475
475
476
476 CodeCell.prototype.append_html = function (html, element) {
477 CodeCell.prototype.append_html = function (html, element) {
477 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_html rendered_html");
478 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_html rendered_html");
478 toinsert.append(html);
479 toinsert.append(html);
479 element.append(toinsert);
480 element.append(toinsert);
480 }
481 };
481
482
482
483
483 CodeCell.prototype.append_text = function (data, element, extra_class) {
484 CodeCell.prototype.append_text = function (data, element, extra_class) {
484 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_text");
485 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_text");
485 if (extra_class){
486 if (extra_class){
486 toinsert.addClass(extra_class);
487 toinsert.addClass(extra_class);
487 }
488 }
488 toinsert.append($("<pre/>").html(data));
489 toinsert.append($("<pre/>").html(data));
489 element.append(toinsert);
490 element.append(toinsert);
490 };
491 };
491
492
492
493
493 CodeCell.prototype.append_svg = function (svg, element) {
494 CodeCell.prototype.append_svg = function (svg, element) {
494 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_svg");
495 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_svg");
495 toinsert.append(svg);
496 toinsert.append(svg);
496 element.append(toinsert);
497 element.append(toinsert);
497 };
498 };
498
499
499
500
500 CodeCell.prototype.append_png = function (png, element) {
501 CodeCell.prototype.append_png = function (png, element) {
501 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_png");
502 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_png");
502 toinsert.append($("<img/>").attr('src','data:image/png;base64,'+png));
503 toinsert.append($("<img/>").attr('src','data:image/png;base64,'+png));
503 element.append(toinsert);
504 element.append(toinsert);
504 };
505 };
505
506
506
507
507 CodeCell.prototype.append_jpeg = function (jpeg, element) {
508 CodeCell.prototype.append_jpeg = function (jpeg, element) {
508 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_jpeg");
509 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_jpeg");
509 toinsert.append($("<img/>").attr('src','data:image/jpeg;base64,'+jpeg));
510 toinsert.append($("<img/>").attr('src','data:image/jpeg;base64,'+jpeg));
510 element.append(toinsert);
511 element.append(toinsert);
511 };
512 };
512
513
513
514
514 CodeCell.prototype.append_latex = function (latex, element) {
515 CodeCell.prototype.append_latex = function (latex, element) {
515 // This method cannot do the typesetting because the latex first has to
516 // This method cannot do the typesetting because the latex first has to
516 // be on the page.
517 // be on the page.
517 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_latex");
518 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_latex");
518 toinsert.append(latex);
519 toinsert.append(latex);
519 element.append(toinsert);
520 element.append(toinsert);
520 }
521 };
521
522
522
523
523 CodeCell.prototype.clear_output = function (stdout, stderr, other) {
524 CodeCell.prototype.clear_output = function (stdout, stderr, other) {
524 var output_div = this.element.find("div.output");
525 var output_div = this.element.find("div.output");
525 if (stdout && stderr && other){
526 if (stdout && stderr && other){
526 // clear all, no need for logic
527 // clear all, no need for logic
527 output_div.html("");
528 output_div.html("");
528 this.outputs = [];
529 this.outputs = [];
529 return;
530 return;
530 }
531 }
531 // remove html output
532 // remove html output
532 // each output_subarea that has an identifying class is in an output_area
533 // each output_subarea that has an identifying class is in an output_area
533 // which is the element to be removed.
534 // which is the element to be removed.
534 if (stdout){
535 if (stdout){
535 output_div.find("div.output_stdout").parent().remove();
536 output_div.find("div.output_stdout").parent().remove();
536 }
537 }
537 if (stderr){
538 if (stderr){
538 output_div.find("div.output_stderr").parent().remove();
539 output_div.find("div.output_stderr").parent().remove();
539 }
540 }
540 if (other){
541 if (other){
541 output_div.find("div.output_subarea").not("div.output_stderr").not("div.output_stdout").parent().remove();
542 output_div.find("div.output_subarea").not("div.output_stderr").not("div.output_stdout").parent().remove();
542 }
543 }
543
544
544 // remove cleared outputs from JSON list:
545 // remove cleared outputs from JSON list:
545 for (var i = this.outputs.length - 1; i >= 0; i--){
546 for (var i = this.outputs.length - 1; i >= 0; i--){
546 var out = this.outputs[i];
547 var out = this.outputs[i];
547 var output_type = out.output_type;
548 var output_type = out.output_type;
548 if (output_type == "display_data" && other){
549 if (output_type == "display_data" && other){
549 this.outputs.splice(i,1);
550 this.outputs.splice(i,1);
550 }else if (output_type == "stream"){
551 }else if (output_type == "stream"){
551 if (stdout && out.stream == "stdout"){
552 if (stdout && out.stream == "stdout"){
552 this.outputs.splice(i,1);
553 this.outputs.splice(i,1);
553 }else if (stderr && out.stream == "stderr"){
554 }else if (stderr && out.stream == "stderr"){
554 this.outputs.splice(i,1);
555 this.outputs.splice(i,1);
555 }
556 }
556 }
557 }
557 }
558 }
558 };
559 };
559
560
560
561
561 CodeCell.prototype.clear_input = function () {
562 CodeCell.prototype.clear_input = function () {
562 this.code_mirror.setValue('');
563 this.code_mirror.setValue('');
563 };
564 };
564
565
565
566
566 CodeCell.prototype.collapse = function () {
567 CodeCell.prototype.collapse = function () {
567 if (!this.collapsed) {
568 if (!this.collapsed) {
568 this.element.find('div.output').hide();
569 this.element.find('div.output').hide();
569 this.collapsed = true;
570 this.collapsed = true;
570 };
571 };
571 };
572 };
572
573
573
574
574 CodeCell.prototype.expand = function () {
575 CodeCell.prototype.expand = function () {
575 if (this.collapsed) {
576 if (this.collapsed) {
576 this.element.find('div.output').show();
577 this.element.find('div.output').show();
577 this.collapsed = false;
578 this.collapsed = false;
578 };
579 };
579 };
580 };
580
581
581
582
582 CodeCell.prototype.toggle_output = function () {
583 CodeCell.prototype.toggle_output = function () {
583 if (this.collapsed) {
584 if (this.collapsed) {
584 this.expand();
585 this.expand();
585 } else {
586 } else {
586 this.collapse();
587 this.collapse();
587 };
588 };
588 };
589 };
589
590
590 CodeCell.prototype.set_input_prompt = function (number) {
591 CodeCell.prototype.set_input_prompt = function (number) {
591 var n = number || '&nbsp;';
592 var n = number || '&nbsp;';
592 this.input_prompt_number = n
593 this.input_prompt_number = n;
593 this.element.find('div.input_prompt').html('In&nbsp;[' + n + ']:');
594 this.element.find('div.input_prompt').html('In&nbsp;[' + n + ']:');
594 };
595 };
595
596
596
597
597 CodeCell.prototype.get_code = function () {
598 CodeCell.prototype.get_code = function () {
598 return this.code_mirror.getValue();
599 return this.code_mirror.getValue();
599 };
600 };
600
601
601
602
602 CodeCell.prototype.set_code = function (code) {
603 CodeCell.prototype.set_code = function (code) {
603 return this.code_mirror.setValue(code);
604 return this.code_mirror.setValue(code);
604 };
605 };
605
606
606
607
607 CodeCell.prototype.at_top = function () {
608 CodeCell.prototype.at_top = function () {
608 var cursor = this.code_mirror.getCursor();
609 var cursor = this.code_mirror.getCursor();
609 if (cursor.line === 0) {
610 if (cursor.line === 0) {
610 return true;
611 return true;
611 } else {
612 } else {
612 return false;
613 return false;
613 }
614 }
614 };
615 };
615
616
616
617
617 CodeCell.prototype.at_bottom = function () {
618 CodeCell.prototype.at_bottom = function () {
618 var cursor = this.code_mirror.getCursor();
619 var cursor = this.code_mirror.getCursor();
619 if (cursor.line === (this.code_mirror.lineCount()-1)) {
620 if (cursor.line === (this.code_mirror.lineCount()-1)) {
620 return true;
621 return true;
621 } else {
622 } else {
622 return false;
623 return false;
623 }
624 }
624 };
625 };
625
626
626
627
627 CodeCell.prototype.fromJSON = function (data) {
628 CodeCell.prototype.fromJSON = function (data) {
628 console.log('Import from JSON:', data);
629 console.log('Import from JSON:', data);
629 if (data.cell_type === 'code') {
630 if (data.cell_type === 'code') {
630 if (data.input !== undefined) {
631 if (data.input !== undefined) {
631 this.set_code(data.input);
632 this.set_code(data.input);
632 }
633 }
633 if (data.prompt_number !== undefined) {
634 if (data.prompt_number !== undefined) {
634 this.set_input_prompt(data.prompt_number);
635 this.set_input_prompt(data.prompt_number);
635 } else {
636 } else {
636 this.set_input_prompt();
637 this.set_input_prompt();
637 };
638 };
638 var len = data.outputs.length;
639 var len = data.outputs.length;
639 for (var i=0; i<len; i++) {
640 for (var i=0; i<len; i++) {
640 this.append_output(data.outputs[i]);
641 this.append_output(data.outputs[i]);
641 };
642 };
642 if (data.collapsed !== undefined) {
643 if (data.collapsed !== undefined) {
643 if (data.collapsed) {
644 if (data.collapsed) {
644 this.collapse();
645 this.collapse();
645 };
646 };
646 };
647 };
647 };
648 };
648 };
649 };
649
650
650
651
651 CodeCell.prototype.toJSON = function () {
652 CodeCell.prototype.toJSON = function () {
652 var data = {};
653 var data = {};
653 data.input = this.get_code();
654 data.input = this.get_code();
654 data.cell_type = 'code';
655 data.cell_type = 'code';
655 if (this.input_prompt_number !== ' ') {
656 if (this.input_prompt_number !== ' ') {
656 data.prompt_number = this.input_prompt_number
657 data.prompt_number = this.input_prompt_number;
657 };
658 };
658 var outputs = [];
659 var outputs = [];
659 var len = this.outputs.length;
660 var len = this.outputs.length;
660 for (var i=0; i<len; i++) {
661 for (var i=0; i<len; i++) {
661 outputs[i] = this.outputs[i];
662 outputs[i] = this.outputs[i];
662 };
663 };
663 data.outputs = outputs;
664 data.outputs = outputs;
664 data.language = 'python';
665 data.language = 'python';
665 data.collapsed = this.collapsed;
666 data.collapsed = this.collapsed;
666 // console.log('Export to JSON:',data);
667 // console.log('Export to JSON:',data);
667 return data;
668 return data;
668 };
669 };
669
670
670
671
671 IPython.CodeCell = CodeCell;
672 IPython.CodeCell = CodeCell;
672
673
673 return IPython;
674 return IPython;
674 }(IPython));
675 }(IPython));
@@ -1,235 +1,235
1 //----------------------------------------------------------------------------
1 //----------------------------------------------------------------------------
2 // Copyright (C) 2008-2011 The IPython Development Team
2 // Copyright (C) 2008-2011 The IPython Development Team
3 //
3 //
4 // Distributed under the terms of the BSD License. The full license is in
4 // Distributed under the terms of the BSD License. The full license is in
5 // the file COPYING, distributed as part of this software.
5 // the file COPYING, distributed as part of this software.
6 //----------------------------------------------------------------------------
6 //----------------------------------------------------------------------------
7
7
8 //============================================================================
8 //============================================================================
9 // Kernel
9 // Kernel
10 //============================================================================
10 //============================================================================
11
11
12 var IPython = (function (IPython) {
12 var IPython = (function (IPython) {
13
13
14 var utils = IPython.utils;
14 var utils = IPython.utils;
15
15
16 var Kernel = function () {
16 var Kernel = function () {
17 this.kernel_id = null;
17 this.kernel_id = null;
18 this.shell_channel = null;
18 this.shell_channel = null;
19 this.iopub_channel = null;
19 this.iopub_channel = null;
20 this.base_url = $('body').data('baseKernelUrl') + "kernels";
20 this.base_url = $('body').data('baseKernelUrl') + "kernels";
21 this.running = false;
21 this.running = false;
22 this.username = "username";
22 this.username = "username";
23 this.session_id = utils.uuid();
23 this.session_id = utils.uuid();
24
24
25 if (typeof(WebSocket) !== 'undefined') {
25 if (typeof(WebSocket) !== 'undefined') {
26 this.WebSocket = WebSocket
26 this.WebSocket = WebSocket;
27 } else if (typeof(MozWebSocket) !== 'undefined') {
27 } else if (typeof(MozWebSocket) !== 'undefined') {
28 this.WebSocket = MozWebSocket
28 this.WebSocket = MozWebSocket;
29 } else {
29 } else {
30 alert('Your browser does not have WebSocket support, please try Chrome, Safari or Firefox β‰₯ 6. Firefox 4 and 5 are also supported by you have to enable WebSockets in about:config.');
30 alert('Your browser does not have WebSocket support, please try Chrome, Safari or Firefox β‰₯ 6. Firefox 4 and 5 are also supported by you have to enable WebSockets in about:config.');
31 };
31 };
32 };
32 };
33
33
34
34
35 Kernel.prototype.get_msg = function (msg_type, content) {
35 Kernel.prototype.get_msg = function (msg_type, content) {
36 var msg = {
36 var msg = {
37 header : {
37 header : {
38 msg_id : utils.uuid(),
38 msg_id : utils.uuid(),
39 username : this.username,
39 username : this.username,
40 session : this.session_id,
40 session : this.session_id,
41 msg_type : msg_type
41 msg_type : msg_type
42 },
42 },
43 content : content,
43 content : content,
44 parent_header : {}
44 parent_header : {}
45 };
45 };
46 return msg;
46 return msg;
47 }
47 };
48
48
49 Kernel.prototype.start = function (notebook_id, callback) {
49 Kernel.prototype.start = function (notebook_id, callback) {
50 var that = this;
50 var that = this;
51 if (!this.running) {
51 if (!this.running) {
52 var qs = $.param({notebook:notebook_id});
52 var qs = $.param({notebook:notebook_id});
53 var url = this.base_url + '?' + qs
53 var url = this.base_url + '?' + qs;
54 $.post(url,
54 $.post(url,
55 function (kernel_id) {
55 function (kernel_id) {
56 that._handle_start_kernel(kernel_id, callback);
56 that._handle_start_kernel(kernel_id, callback);
57 },
57 },
58 'json'
58 'json'
59 );
59 );
60 };
60 };
61 };
61 };
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.kernel_status_widget.status_restarting();
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) {
69 this.stop_channels();
69 this.stop_channels();
70 $.post(url,
70 $.post(url,
71 function (kernel_id) {
71 function (kernel_id) {
72 that._handle_start_kernel(kernel_id, callback);
72 that._handle_start_kernel(kernel_id, callback);
73 },
73 },
74 'json'
74 'json'
75 );
75 );
76 };
76 };
77 };
77 };
78
78
79
79
80 Kernel.prototype._handle_start_kernel = function (json, callback) {
80 Kernel.prototype._handle_start_kernel = function (json, callback) {
81 this.running = true;
81 this.running = true;
82 this.kernel_id = json.kernel_id;
82 this.kernel_id = json.kernel_id;
83 this.ws_url = json.ws_url;
83 this.ws_url = json.ws_url;
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();
87 IPython.kernel_status_widget.status_idle();
88 };
88 };
89
89
90 Kernel.prototype._websocket_closed = function(ws_url, early){
90 Kernel.prototype._websocket_closed = function(ws_url, early){
91 var msg;
91 var msg;
92 var parent_item = $('body');
92 var parent_item = $('body');
93 if (early) {
93 if (early) {
94 msg = "Websocket connection to " + ws_url + " could not be established.<br/>" +
94 msg = "Websocket connection to " + ws_url + " could not be established.<br/>" +
95 " You will NOT be able to run code.<br/>" +
95 " You will NOT be able to run code.<br/>" +
96 " Your browser may not be compatible with the websocket version in the server," +
96 " 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" +
97 " or if the url does not look right, there could be an error in the" +
98 " server's configuration."
98 " server's configuration.";
99 } else {
99 } else {
100 msg = "Websocket connection closed unexpectedly.<br/>" +
100 msg = "Websocket connection closed unexpectedly.<br/>" +
101 " The kernel will no longer be responsive."
101 " The kernel will no longer be responsive.";
102 }
102 }
103 var dialog = $('<div/>');
103 var dialog = $('<div/>');
104 dialog.html(msg);
104 dialog.html(msg);
105 parent_item.append(dialog);
105 parent_item.append(dialog);
106 dialog.dialog({
106 dialog.dialog({
107 resizable: false,
107 resizable: false,
108 modal: true,
108 modal: true,
109 title: "Websocket closed",
109 title: "Websocket closed",
110 buttons : {
110 buttons : {
111 "Okay": function () {
111 "Okay": function () {
112 $(this).dialog('close');
112 $(this).dialog('close');
113 }
113 }
114 }
114 }
115 });
115 });
116
116
117 }
117 };
118
118
119 Kernel.prototype.start_channels = function () {
119 Kernel.prototype.start_channels = function () {
120 var that = this;
120 var that = this;
121 this.stop_channels();
121 this.stop_channels();
122 var ws_url = this.ws_url + this.kernel_url;
122 var ws_url = this.ws_url + this.kernel_url;
123 console.log("Starting WS:", ws_url);
123 console.log("Starting WS:", ws_url);
124 this.shell_channel = new this.WebSocket(ws_url + "/shell");
124 this.shell_channel = new this.WebSocket(ws_url + "/shell");
125 this.iopub_channel = new this.WebSocket(ws_url + "/iopub");
125 this.iopub_channel = new this.WebSocket(ws_url + "/iopub");
126 send_cookie = function(){
126 send_cookie = function(){
127 this.send(document.cookie);
127 this.send(document.cookie);
128 }
128 };
129 var already_called_onclose = false; // only alert once
129 var already_called_onclose = false; // only alert once
130 ws_closed_early = function(evt){
130 ws_closed_early = function(evt){
131 if (already_called_onclose){
131 if (already_called_onclose){
132 return;
132 return;
133 }
133 }
134 already_called_onclose = true;
134 already_called_onclose = true;
135 if ( ! evt.wasClean ){
135 if ( ! evt.wasClean ){
136 that._websocket_closed(ws_url, true);
136 that._websocket_closed(ws_url, true);
137 }
137 }
138 }
138 };
139 ws_closed_late = function(evt){
139 ws_closed_late = function(evt){
140 if (already_called_onclose){
140 if (already_called_onclose){
141 return;
141 return;
142 }
142 }
143 already_called_onclose = true;
143 already_called_onclose = true;
144 if ( ! evt.wasClean ){
144 if ( ! evt.wasClean ){
145 that._websocket_closed(ws_url, false);
145 that._websocket_closed(ws_url, false);
146 }
146 }
147 }
147 };
148 this.shell_channel.onopen = send_cookie;
148 this.shell_channel.onopen = send_cookie;
149 this.shell_channel.onclose = ws_closed_early;
149 this.shell_channel.onclose = ws_closed_early;
150 this.iopub_channel.onopen = send_cookie;
150 this.iopub_channel.onopen = send_cookie;
151 this.iopub_channel.onclose = ws_closed_early;
151 this.iopub_channel.onclose = ws_closed_early;
152 // switch from early-close to late-close message after 1s
152 // switch from early-close to late-close message after 1s
153 setTimeout(function(){
153 setTimeout(function(){
154 that.shell_channel.onclose = ws_closed_late;
154 that.shell_channel.onclose = ws_closed_late;
155 that.iopub_channel.onclose = ws_closed_late;
155 that.iopub_channel.onclose = ws_closed_late;
156 }, 1000);
156 }, 1000);
157 };
157 };
158
158
159
159
160 Kernel.prototype.stop_channels = function () {
160 Kernel.prototype.stop_channels = function () {
161 if (this.shell_channel !== null) {
161 if (this.shell_channel !== null) {
162 this.shell_channel.onclose = function (evt) {null};
162 this.shell_channel.onclose = function (evt) {};
163 this.shell_channel.close();
163 this.shell_channel.close();
164 this.shell_channel = null;
164 this.shell_channel = null;
165 };
165 };
166 if (this.iopub_channel !== null) {
166 if (this.iopub_channel !== null) {
167 this.iopub_channel.onclose = function (evt) {null};
167 this.iopub_channel.onclose = function (evt) {};
168 this.iopub_channel.close();
168 this.iopub_channel.close();
169 this.iopub_channel = null;
169 this.iopub_channel = null;
170 };
170 };
171 };
171 };
172
172
173 Kernel.prototype.object_info_request = function (objname) {
173 Kernel.prototype.object_info_request = function (objname) {
174 if(typeof(objname)!=null)
174 if(typeof(objname)!=null)
175 {
175 {
176 var content = {
176 var content = {
177 oname : objname.toString(),
177 oname : objname.toString(),
178 };
178 };
179 var msg = this.get_msg("object_info_request", content);
179 var msg = this.get_msg("object_info_request", content);
180 this.shell_channel.send(JSON.stringify(msg));
180 this.shell_channel.send(JSON.stringify(msg));
181 return msg.header.msg_id;
181 return msg.header.msg_id;
182 }
182 }
183 return;
183 return;
184 }
184 }
185
185
186 Kernel.prototype.execute = function (code) {
186 Kernel.prototype.execute = function (code) {
187 var content = {
187 var content = {
188 code : code,
188 code : code,
189 silent : false,
189 silent : false,
190 user_variables : [],
190 user_variables : [],
191 user_expressions : {},
191 user_expressions : {},
192 allow_stdin : false,
192 allow_stdin : false
193 };
193 };
194 var msg = this.get_msg("execute_request", content);
194 var msg = this.get_msg("execute_request", content);
195 this.shell_channel.send(JSON.stringify(msg));
195 this.shell_channel.send(JSON.stringify(msg));
196 return msg.header.msg_id;
196 return msg.header.msg_id;
197 }
197 };
198
198
199
199
200 Kernel.prototype.complete = function (line, cursor_pos) {
200 Kernel.prototype.complete = function (line, cursor_pos) {
201 var content = {
201 var content = {
202 text : '',
202 text : '',
203 line : line,
203 line : line,
204 cursor_pos : cursor_pos
204 cursor_pos : cursor_pos
205 };
205 };
206 var msg = this.get_msg("complete_request", content);
206 var msg = this.get_msg("complete_request", content);
207 this.shell_channel.send(JSON.stringify(msg));
207 this.shell_channel.send(JSON.stringify(msg));
208 return msg.header.msg_id;
208 return msg.header.msg_id;
209 }
209 };
210
210
211
211
212 Kernel.prototype.interrupt = function () {
212 Kernel.prototype.interrupt = function () {
213 if (this.running) {
213 if (this.running) {
214 $.post(this.kernel_url + "/interrupt");
214 $.post(this.kernel_url + "/interrupt");
215 };
215 };
216 };
216 };
217
217
218
218
219 Kernel.prototype.kill = function () {
219 Kernel.prototype.kill = function () {
220 if (this.running) {
220 if (this.running) {
221 this.running = false;
221 this.running = false;
222 var settings = {
222 var settings = {
223 cache : false,
223 cache : false,
224 type : "DELETE",
224 type : "DELETE"
225 };
225 };
226 $.ajax(this.kernel_url, settings);
226 $.ajax(this.kernel_url, settings);
227 };
227 };
228 };
228 };
229
229
230 IPython.Kernel = Kernel;
230 IPython.Kernel = Kernel;
231
231
232 return IPython;
232 return IPython;
233
233
234 }(IPython));
234 }(IPython));
235
235
@@ -1,63 +1,63
1 //----------------------------------------------------------------------------
1 //----------------------------------------------------------------------------
2 // Copyright (C) 2008-2011 The IPython Development Team
2 // Copyright (C) 2008-2011 The IPython Development Team
3 //
3 //
4 // Distributed under the terms of the BSD License. The full license is in
4 // Distributed under the terms of the BSD License. The full license is in
5 // the file COPYING, distributed as part of this software.
5 // the file COPYING, distributed as part of this software.
6 //----------------------------------------------------------------------------
6 //----------------------------------------------------------------------------
7
7
8 //============================================================================
8 //============================================================================
9 // Kernel Status widget
9 // Kernel Status widget
10 //============================================================================
10 //============================================================================
11
11
12 var IPython = (function (IPython) {
12 var IPython = (function (IPython) {
13
13
14 var utils = IPython.utils;
14 var utils = IPython.utils;
15
15
16 var KernelStatusWidget = function (selector) {
16 var KernelStatusWidget = function (selector) {
17 this.selector = selector;
17 this.selector = selector;
18 if (this.selector !== undefined) {
18 if (this.selector !== undefined) {
19 this.element = $(selector);
19 this.element = $(selector);
20 this.style();
20 this.style();
21 }
21 }
22 };
22 };
23
23
24
24
25 KernelStatusWidget.prototype.style = function () {
25 KernelStatusWidget.prototype.style = function () {
26 this.element.addClass('ui-widget');
26 this.element.addClass('ui-widget');
27 this.element.attr('title', "The kernel execution status." +
27 this.element.attr('title', "The kernel execution status." +
28 " If 'Busy', the kernel is currently running code." +
28 " If 'Busy', the kernel is currently running code." +
29 " If 'Idle', it is available for execution.")
29 " If 'Idle', it is available for execution.");
30 };
30 };
31
31
32
32
33 KernelStatusWidget.prototype.status_busy = function () {
33 KernelStatusWidget.prototype.status_busy = function () {
34 this.element.removeClass("status_idle");
34 this.element.removeClass("status_idle");
35 this.element.removeClass("status_restarting");
35 this.element.removeClass("status_restarting");
36 this.element.addClass("status_busy");
36 this.element.addClass("status_busy");
37 this.element.text("Busy");
37 this.element.text("Busy");
38 };
38 };
39
39
40
40
41 KernelStatusWidget.prototype.status_idle = function () {
41 KernelStatusWidget.prototype.status_idle = function () {
42 this.element.removeClass("status_busy");
42 this.element.removeClass("status_busy");
43 this.element.removeClass("status_restarting");
43 this.element.removeClass("status_restarting");
44 this.element.addClass("status_idle");
44 this.element.addClass("status_idle");
45 this.element.text("Idle");
45 this.element.text("Idle");
46 };
46 };
47
47
48 KernelStatusWidget.prototype.status_restarting = function () {
48 KernelStatusWidget.prototype.status_restarting = function () {
49 this.element.removeClass("status_busy");
49 this.element.removeClass("status_busy");
50 this.element.removeClass("status_idle");
50 this.element.removeClass("status_idle");
51 this.element.addClass("status_restarting");
51 this.element.addClass("status_restarting");
52 this.element.text("Restarting");
52 this.element.text("Restarting");
53 };
53 };
54
54
55
55
56
56
57
57
58 IPython.KernelStatusWidget = KernelStatusWidget;
58 IPython.KernelStatusWidget = KernelStatusWidget;
59
59
60 return IPython;
60 return IPython;
61
61
62 }(IPython));
62 }(IPython));
63
63
@@ -1,61 +1,61
1 //----------------------------------------------------------------------------
1 //----------------------------------------------------------------------------
2 // Copyright (C) 2008-2011 The IPython Development Team
2 // Copyright (C) 2008-2011 The IPython Development Team
3 //
3 //
4 // Distributed under the terms of the BSD License. The full license is in
4 // Distributed under the terms of the BSD License. The full license is in
5 // the file COPYING, distributed as part of this software.
5 // the file COPYING, distributed as part of this software.
6 //----------------------------------------------------------------------------
6 //----------------------------------------------------------------------------
7
7
8 //============================================================================
8 //============================================================================
9 // Layout
9 // Layout
10 //============================================================================
10 //============================================================================
11
11
12 var IPython = (function (IPython) {
12 var IPython = (function (IPython) {
13
13
14 var LayoutManager = function () {
14 var LayoutManager = function () {
15 this.bind_events();
15 this.bind_events();
16 };
16 };
17
17
18
18
19 LayoutManager.prototype.bind_events = function () {
19 LayoutManager.prototype.bind_events = function () {
20 $(window).resize($.proxy(this.do_resize,this));
20 $(window).resize($.proxy(this.do_resize,this));
21 };
21 };
22
22
23
23
24 LayoutManager.prototype.do_resize = function () {
24 LayoutManager.prototype.do_resize = function () {
25 var win = $(window);
25 var win = $(window);
26 var w = win.width();
26 var w = win.width();
27 var h = win.height();
27 var h = win.height();
28 var header_height = $('div#header').outerHeight(true);
28 var header_height = $('div#header').outerHeight(true);
29 var app_height = h - header_height - 2; // content height
29 var app_height = h - header_height - 2; // content height
30
30
31 $('div#main_app').height(app_height + 2); // content+padding+border height
31 $('div#main_app').height(app_height + 2); // content+padding+border height
32
32
33 $('div#left_panel').height(app_height);
33 $('div#left_panel').height(app_height);
34
34
35 $('div#left_panel_splitter').height(app_height);
35 $('div#left_panel_splitter').height(app_height);
36
36
37 $('div#notebook_panel').height(app_height);
37 $('div#notebook_panel').height(app_height);
38 var left_panel_width = $('div#left_panel').outerWidth();
38 var left_panel_width = $('div#left_panel').outerWidth();
39 var left_panel_splitter_width = $('div#left_panel_splitter').outerWidth();
39 var left_panel_splitter_width = $('div#left_panel_splitter').outerWidth();
40 if (IPython.left_panel.expanded) {
40 if (IPython.left_panel.expanded) {
41 $('div#notebook_panel').css({marginLeft : left_panel_width+left_panel_splitter_width});
41 $('div#notebook_panel').css({marginLeft : left_panel_width+left_panel_splitter_width});
42 } else {
42 } else {
43 $('div#notebook_panel').css({marginLeft : left_panel_splitter_width});
43 $('div#notebook_panel').css({marginLeft : left_panel_splitter_width});
44 }
44 }
45
45
46
46
47 var pager_height = IPython.pager.percentage_height*app_height;
47 var pager_height = IPython.pager.percentage_height*app_height;
48 var pager_splitter_height = $('div#pager_splitter').outerHeight(true);
48 var pager_splitter_height = $('div#pager_splitter').outerHeight(true);
49 $('div#pager').height(pager_height);
49 $('div#pager').height(pager_height);
50 if (IPython.pager.expanded) {
50 if (IPython.pager.expanded) {
51 $('div#notebook').height(app_height-pager_height-pager_splitter_height);
51 $('div#notebook').height(app_height-pager_height-pager_splitter_height);
52 } else {
52 } else {
53 $('div#notebook').height(app_height-pager_splitter_height);
53 $('div#notebook').height(app_height-pager_splitter_height);
54 }
54 }
55 };
55 };
56
56
57 IPython.LayoutManager = LayoutManager
57 IPython.LayoutManager = LayoutManager;
58
58
59 return IPython;
59 return IPython;
60
60
61 }(IPython));
61 }(IPython));
@@ -1,105 +1,105
1 //----------------------------------------------------------------------------
1 //----------------------------------------------------------------------------
2 // Copyright (C) 2008-2011 The IPython Development Team
2 // Copyright (C) 2008-2011 The IPython Development Team
3 //
3 //
4 // Distributed under the terms of the BSD License. The full license is in
4 // Distributed under the terms of the BSD License. The full license is in
5 // the file COPYING, distributed as part of this software.
5 // the file COPYING, distributed as part of this software.
6 //----------------------------------------------------------------------------
6 //----------------------------------------------------------------------------
7
7
8 //============================================================================
8 //============================================================================
9 // LeftPanel
9 // LeftPanel
10 //============================================================================
10 //============================================================================
11
11
12
12
13 var IPython = (function (IPython) {
13 var IPython = (function (IPython) {
14
14
15 var utils = IPython.utils;
15 var utils = IPython.utils;
16
16
17 var LeftPanel = function (left_panel_selector, left_panel_splitter_selector) {
17 var LeftPanel = function (left_panel_selector, left_panel_splitter_selector) {
18 this.left_panel_element = $(left_panel_selector);
18 this.left_panel_element = $(left_panel_selector);
19 this.left_panel_splitter_element = $(left_panel_splitter_selector);
19 this.left_panel_splitter_element = $(left_panel_splitter_selector);
20 this.expanded = true;
20 this.expanded = true;
21 this.width = 300;
21 this.width = 300;
22 this.style();
22 this.style();
23 this.bind_events();
23 this.bind_events();
24 this.create_children();
24 this.create_children();
25 };
25 };
26
26
27
27
28 LeftPanel.prototype.style = function () {
28 LeftPanel.prototype.style = function () {
29 this.left_panel_splitter_element.addClass('border-box-sizing ui-widget ui-state-default');
29 this.left_panel_splitter_element.addClass('border-box-sizing ui-widget ui-state-default');
30 this.left_panel_element.addClass('border-box-sizing ui-widget');
30 this.left_panel_element.addClass('border-box-sizing ui-widget');
31 this.left_panel_element.width(this.width);
31 this.left_panel_element.width(this.width);
32 this.left_panel_splitter_element.css({left : this.width});
32 this.left_panel_splitter_element.css({left : this.width});
33 this.left_panel_splitter_element.attr('title', 'Click to Show/Hide left panel');
33 this.left_panel_splitter_element.attr('title', 'Click to Show/Hide left panel');
34 };
34 };
35
35
36
36
37 LeftPanel.prototype.bind_events = function () {
37 LeftPanel.prototype.bind_events = function () {
38 var that = this;
38 var that = this;
39
39
40 this.left_panel_element.bind('collapse_left_panel', function () {
40 this.left_panel_element.bind('collapse_left_panel', function () {
41 that.left_panel_element.hide('fast');
41 that.left_panel_element.hide('fast');
42 that.left_panel_splitter_element.animate({left : 0}, 'fast');
42 that.left_panel_splitter_element.animate({left : 0}, 'fast');
43 });
43 });
44
44
45 this.left_panel_element.bind('expand_left_panel', function () {
45 this.left_panel_element.bind('expand_left_panel', function () {
46 that.left_panel_element.show('fast');
46 that.left_panel_element.show('fast');
47 that.left_panel_splitter_element.animate({left : that.width}, 'fast');
47 that.left_panel_splitter_element.animate({left : that.width}, 'fast');
48 });
48 });
49
49
50 this.left_panel_splitter_element.hover(
50 this.left_panel_splitter_element.hover(
51 function () {
51 function () {
52 that.left_panel_splitter_element.addClass('ui-state-hover');
52 that.left_panel_splitter_element.addClass('ui-state-hover');
53 },
53 },
54 function () {
54 function () {
55 that.left_panel_splitter_element.removeClass('ui-state-hover');
55 that.left_panel_splitter_element.removeClass('ui-state-hover');
56 }
56 }
57 );
57 );
58
58
59 this.left_panel_splitter_element.click(function () {
59 this.left_panel_splitter_element.click(function () {
60 that.toggle();
60 that.toggle();
61 });
61 });
62
62
63 };
63 };
64
64
65
65
66 LeftPanel.prototype.create_children = function () {
66 LeftPanel.prototype.create_children = function () {
67 this.notebook_section = new IPython.NotebookSection('div#notebook_section');
67 this.notebook_section = new IPython.NotebookSection('div#notebook_section');
68 if (! IPython.read_only){
68 if (! IPython.read_only){
69 this.cell_section = new IPython.CellSection('div#cell_section');
69 this.cell_section = new IPython.CellSection('div#cell_section');
70 this.config_section = new IPython.ConfigSection('div#config_section');
70 this.config_section = new IPython.ConfigSection('div#config_section');
71 this.kernel_section = new IPython.KernelSection('div#kernel_section');
71 this.kernel_section = new IPython.KernelSection('div#kernel_section');
72 }
72 }
73 this.help_section = new IPython.HelpSection('div#help_section');
73 this.help_section = new IPython.HelpSection('div#help_section');
74 }
74 };
75
75
76 LeftPanel.prototype.collapse = function () {
76 LeftPanel.prototype.collapse = function () {
77 if (this.expanded === true) {
77 if (this.expanded === true) {
78 this.left_panel_element.add($('div#notebook')).trigger('collapse_left_panel');
78 this.left_panel_element.add($('div#notebook')).trigger('collapse_left_panel');
79 this.expanded = false;
79 this.expanded = false;
80 };
80 };
81 };
81 };
82
82
83
83
84 LeftPanel.prototype.expand = function () {
84 LeftPanel.prototype.expand = function () {
85 if (this.expanded !== true) {
85 if (this.expanded !== true) {
86 this.left_panel_element.add($('div#notebook')).trigger('expand_left_panel');
86 this.left_panel_element.add($('div#notebook')).trigger('expand_left_panel');
87 this.expanded = true;
87 this.expanded = true;
88 };
88 };
89 };
89 };
90
90
91
91
92 LeftPanel.prototype.toggle = function () {
92 LeftPanel.prototype.toggle = function () {
93 if (this.expanded === true) {
93 if (this.expanded === true) {
94 this.collapse();
94 this.collapse();
95 } else {
95 } else {
96 this.expand();
96 this.expand();
97 };
97 };
98 };
98 };
99
99
100 IPython.LeftPanel = LeftPanel;
100 IPython.LeftPanel = LeftPanel;
101
101
102 return IPython;
102 return IPython;
103
103
104 }(IPython));
104 }(IPython));
105
105
@@ -1,30 +1,30
1 //----------------------------------------------------------------------------
1 //----------------------------------------------------------------------------
2 // Copyright (C) 2008-2011 The IPython Development Team
2 // Copyright (C) 2008-2011 The IPython Development Team
3 //
3 //
4 // Distributed under the terms of the BSD License. The full license is in
4 // Distributed under the terms of the BSD License. The full license is in
5 // the file COPYING, distributed as part of this software.
5 // the file COPYING, distributed as part of this software.
6 //----------------------------------------------------------------------------
6 //----------------------------------------------------------------------------
7
7
8 var IPython = IPython || {};
8 var IPython = IPython || {};
9
9
10 IPython.namespace = function (ns_string) {
10 IPython.namespace = function (ns_string) {
11 var parts = ns_string.split('.'),
11 var parts = ns_string.split('.'),
12 parent = IPython,
12 parent = IPython,
13 i;
13 i;
14
14
15 // String redundant leading global
15 // String redundant leading global
16 if (parts[0] === "IPython") {
16 if (parts[0] === "IPython") {
17 parts = parts.slice(1);
17 parts = parts.slice(1);
18 }
18 }
19
19
20 for (i=0; i<parts.length; i+=1) {
20 for (i=0; i<parts.length; i+=1) {
21 // Create property if it doesn't exist
21 // Create property if it doesn't exist
22 if (typeof parent[parts[i]] === "undefined") {
22 if (typeof parent[parts[i]] === "undefined") {
23 parent[parts[i]] == {};
23 parent[parts[i]] = {};
24 }
24 }
25 }
25 }
26 return parent;
26 return parent;
27 };
27 };
28
28
29
29
30
30
@@ -1,1074 +1,1077
1 //----------------------------------------------------------------------------
1 //----------------------------------------------------------------------------
2 // Copyright (C) 2008-2011 The IPython Development Team
2 // Copyright (C) 2008-2011 The IPython Development Team
3 //
3 //
4 // Distributed under the terms of the BSD License. The full license is in
4 // Distributed under the terms of the BSD License. The full license is in
5 // the file COPYING, distributed as part of this software.
5 // the file COPYING, distributed as part of this software.
6 //----------------------------------------------------------------------------
6 //----------------------------------------------------------------------------
7
7
8 //============================================================================
8 //============================================================================
9 // Notebook
9 // Notebook
10 //============================================================================
10 //============================================================================
11
11
12 var IPython = (function (IPython) {
12 var IPython = (function (IPython) {
13
13
14 var utils = IPython.utils;
14 var utils = IPython.utils;
15
15
16 var Notebook = function (selector) {
16 var Notebook = function (selector) {
17 this.read_only = IPython.read_only;
17 this.read_only = IPython.read_only;
18 this.element = $(selector);
18 this.element = $(selector);
19 this.element.scroll();
19 this.element.scroll();
20 this.element.data("notebook", this);
20 this.element.data("notebook", this);
21 this.next_prompt_number = 1;
21 this.next_prompt_number = 1;
22 this.kernel = null;
22 this.kernel = null;
23 this.dirty = false;
23 this.dirty = false;
24 this.msg_cell_map = {};
24 this.msg_cell_map = {};
25 this.metadata = {};
25 this.metadata = {};
26 this.control_key_active = false;
26 this.control_key_active = false;
27 this.style();
27 this.style();
28 this.create_elements();
28 this.create_elements();
29 this.bind_events();
29 this.bind_events();
30 this.set_tooltipontab(true);
30 this.set_tooltipontab(true);
31 this.set_smartcompleter(true);
31 this.set_smartcompleter(true);
32 this.set_timebeforetooltip(1200);
32 this.set_timebeforetooltip(1200);
33 };
33 };
34
34
35
35
36 Notebook.prototype.style = function () {
36 Notebook.prototype.style = function () {
37 $('div#notebook').addClass('border-box-sizing');
37 $('div#notebook').addClass('border-box-sizing');
38 };
38 };
39
39
40
40
41 Notebook.prototype.create_elements = function () {
41 Notebook.prototype.create_elements = function () {
42 // We add this end_space div to the end of the notebook div to:
42 // We add this end_space div to the end of the notebook div to:
43 // i) provide a margin between the last cell and the end of the notebook
43 // i) provide a margin between the last cell and the end of the notebook
44 // ii) to prevent the div from scrolling up when the last cell is being
44 // ii) to prevent the div from scrolling up when the last cell is being
45 // edited, but is too low on the page, which browsers will do automatically.
45 // edited, but is too low on the page, which browsers will do automatically.
46 var that = this;
46 var that = this;
47 var end_space = $('<div class="end_space"></div>').height(150);
47 var end_space = $('<div class="end_space"></div>').height(150);
48 end_space.dblclick(function (e) {
48 end_space.dblclick(function (e) {
49 if (that.read_only) return;
49 if (that.read_only) return;
50 var ncells = that.ncells();
50 var ncells = that.ncells();
51 that.insert_code_cell_below(ncells-1);
51 that.insert_code_cell_below(ncells-1);
52 });
52 });
53 this.element.append(end_space);
53 this.element.append(end_space);
54 $('div#notebook').addClass('border-box-sizing');
54 $('div#notebook').addClass('border-box-sizing');
55 };
55 };
56
56
57
57
58 Notebook.prototype.bind_events = function () {
58 Notebook.prototype.bind_events = function () {
59 var that = this;
59 var that = this;
60 $(document).keydown(function (event) {
60 $(document).keydown(function (event) {
61 // console.log(event);
61 // console.log(event);
62 if (that.read_only) return;
62 if (that.read_only) return false;
63 if (event.which === 27) {
63 if (event.which === 27) {
64 // Intercept escape at highest level to avoid closing
64 // Intercept escape at highest level to avoid closing
65 // websocket connection with firefox
65 // websocket connection with firefox
66 event.preventDefault();
66 event.preventDefault();
67 }
67 }
68 if (event.which === 38 && !event.shiftKey) {
68 if (event.which === 38 && !event.shiftKey) {
69 var cell = that.selected_cell();
69 var cell = that.selected_cell();
70 if (cell.at_top()) {
70 if (cell.at_top()) {
71 event.preventDefault();
71 event.preventDefault();
72 that.select_prev();
72 that.select_prev();
73 };
73 };
74 } else if (event.which === 40 && !event.shiftKey) {
74 } else if (event.which === 40 && !event.shiftKey) {
75 var cell = that.selected_cell();
75 var cell = that.selected_cell();
76 if (cell.at_bottom()) {
76 if (cell.at_bottom()) {
77 event.preventDefault();
77 event.preventDefault();
78 that.select_next();
78 that.select_next();
79 };
79 };
80 } else if (event.which === 13 && event.shiftKey) {
80 } else if (event.which === 13 && event.shiftKey) {
81 that.execute_selected_cell();
81 that.execute_selected_cell();
82 return false;
82 return false;
83 } else if (event.which === 13 && event.ctrlKey) {
83 } else if (event.which === 13 && event.ctrlKey) {
84 that.execute_selected_cell({terminal:true});
84 that.execute_selected_cell({terminal:true});
85 return false;
85 return false;
86 } else if (event.which === 77 && event.ctrlKey) {
86 } else if (event.which === 77 && event.ctrlKey) {
87 that.control_key_active = true;
87 that.control_key_active = true;
88 return false;
88 return false;
89 } else if (event.which === 68 && that.control_key_active) {
89 } else if (event.which === 68 && that.control_key_active) {
90 // Delete selected cell = d
90 // Delete selected cell = d
91 that.delete_cell();
91 that.delete_cell();
92 that.control_key_active = false;
92 that.control_key_active = false;
93 return false;
93 return false;
94 } else if (event.which === 65 && that.control_key_active) {
94 } else if (event.which === 65 && that.control_key_active) {
95 // Insert code cell above selected = a
95 // Insert code cell above selected = a
96 that.insert_code_cell_above();
96 that.insert_code_cell_above();
97 that.control_key_active = false;
97 that.control_key_active = false;
98 return false;
98 return false;
99 } else if (event.which === 66 && that.control_key_active) {
99 } else if (event.which === 66 && that.control_key_active) {
100 // Insert code cell below selected = b
100 // Insert code cell below selected = b
101 that.insert_code_cell_below();
101 that.insert_code_cell_below();
102 that.control_key_active = false;
102 that.control_key_active = false;
103 return false;
103 return false;
104 } else if (event.which === 67 && that.control_key_active) {
104 } else if (event.which === 67 && that.control_key_active) {
105 // To code = c
105 // To code = c
106 that.to_code();
106 that.to_code();
107 that.control_key_active = false;
107 that.control_key_active = false;
108 return false;
108 return false;
109 } else if (event.which === 77 && that.control_key_active) {
109 } else if (event.which === 77 && that.control_key_active) {
110 // To markdown = m
110 // To markdown = m
111 that.to_markdown();
111 that.to_markdown();
112 that.control_key_active = false;
112 that.control_key_active = false;
113 return false;
113 return false;
114 } else if (event.which === 84 && that.control_key_active) {
114 } else if (event.which === 84 && that.control_key_active) {
115 // Toggle output = t
115 // Toggle output = t
116 that.toggle_output();
116 that.toggle_output();
117 that.control_key_active = false;
117 that.control_key_active = false;
118 return false;
118 return false;
119 } else if (event.which === 83 && that.control_key_active) {
119 } else if (event.which === 83 && that.control_key_active) {
120 // Save notebook = s
120 // Save notebook = s
121 IPython.save_widget.save_notebook();
121 IPython.save_widget.save_notebook();
122 that.control_key_active = false;
122 that.control_key_active = false;
123 return false;
123 return false;
124 } else if (event.which === 74 && that.control_key_active) {
124 } else if (event.which === 74 && that.control_key_active) {
125 // Move cell down = j
125 // Move cell down = j
126 that.move_cell_down();
126 that.move_cell_down();
127 that.control_key_active = false;
127 that.control_key_active = false;
128 return false;
128 return false;
129 } else if (event.which === 75 && that.control_key_active) {
129 } else if (event.which === 75 && that.control_key_active) {
130 // Move cell up = k
130 // Move cell up = k
131 that.move_cell_up();
131 that.move_cell_up();
132 that.control_key_active = false;
132 that.control_key_active = false;
133 return false;
133 return false;
134 } else if (event.which === 80 && that.control_key_active) {
134 } else if (event.which === 80 && that.control_key_active) {
135 // Select previous = p
135 // Select previous = p
136 that.select_prev();
136 that.select_prev();
137 that.control_key_active = false;
137 that.control_key_active = false;
138 return false;
138 return false;
139 } else if (event.which === 78 && that.control_key_active) {
139 } else if (event.which === 78 && that.control_key_active) {
140 // Select next = n
140 // Select next = n
141 that.select_next();
141 that.select_next();
142 that.control_key_active = false;
142 that.control_key_active = false;
143 return false;
143 return false;
144 } else if (event.which === 76 && that.control_key_active) {
144 } else if (event.which === 76 && that.control_key_active) {
145 // Toggle line numbers = l
145 // Toggle line numbers = l
146 that.cell_toggle_line_numbers();
146 that.cell_toggle_line_numbers();
147 that.control_key_active = false;
147 that.control_key_active = false;
148 return false;
148 return false;
149 } else if (event.which === 73 && that.control_key_active) {
149 } else if (event.which === 73 && that.control_key_active) {
150 // Interrupt kernel = i
150 // Interrupt kernel = i
151 IPython.notebook.kernel.interrupt();
151 IPython.notebook.kernel.interrupt();
152 that.control_key_active = false;
152 that.control_key_active = false;
153 return false;
153 return false;
154 } else if (event.which === 190 && that.control_key_active) {
154 } else if (event.which === 190 && that.control_key_active) {
155 // Restart kernel = . # matches qt console
155 // Restart kernel = . # matches qt console
156 IPython.notebook.restart_kernel();
156 IPython.notebook.restart_kernel();
157 that.control_key_active = false;
157 that.control_key_active = false;
158 return false;
158 return false;
159 } else if (event.which === 72 && that.control_key_active) {
159 } else if (event.which === 72 && that.control_key_active) {
160 // Show keyboard shortcuts = h
160 // Show keyboard shortcuts = h
161 that.toggle_keyboard_shortcuts();
161 that.toggle_keyboard_shortcuts();
162 that.control_key_active = false;
162 that.control_key_active = false;
163 return false;
163 return false;
164 } else if (that.control_key_active) {
164 } else if (that.control_key_active) {
165 that.control_key_active = false;
165 that.control_key_active = false;
166 return true;
166 return true;
167 };
167 };
168 return true;
168 });
169 });
169
170
170 this.element.bind('collapse_pager', function () {
171 this.element.bind('collapse_pager', function () {
171 var app_height = $('div#main_app').height(); // content height
172 var app_height = $('div#main_app').height(); // content height
172 var splitter_height = $('div#pager_splitter').outerHeight(true);
173 var splitter_height = $('div#pager_splitter').outerHeight(true);
173 var new_height = app_height - splitter_height;
174 var new_height = app_height - splitter_height;
174 that.element.animate({height : new_height + 'px'}, 'fast');
175 that.element.animate({height : new_height + 'px'}, 'fast');
175 });
176 });
176
177
177 this.element.bind('expand_pager', function () {
178 this.element.bind('expand_pager', function () {
178 var app_height = $('div#main_app').height(); // content height
179 var app_height = $('div#main_app').height(); // content height
179 var splitter_height = $('div#pager_splitter').outerHeight(true);
180 var splitter_height = $('div#pager_splitter').outerHeight(true);
180 var pager_height = $('div#pager').outerHeight(true);
181 var pager_height = $('div#pager').outerHeight(true);
181 var new_height = app_height - pager_height - splitter_height;
182 var new_height = app_height - pager_height - splitter_height;
182 that.element.animate({height : new_height + 'px'}, 'fast');
183 that.element.animate({height : new_height + 'px'}, 'fast');
183 });
184 });
184
185
185 this.element.bind('collapse_left_panel', function () {
186 this.element.bind('collapse_left_panel', function () {
186 var splitter_width = $('div#left_panel_splitter').outerWidth(true);
187 var splitter_width = $('div#left_panel_splitter').outerWidth(true);
187 var new_margin = splitter_width;
188 var new_margin = splitter_width;
188 $('div#notebook_panel').animate({marginLeft : new_margin + 'px'}, 'fast');
189 $('div#notebook_panel').animate({marginLeft : new_margin + 'px'}, 'fast');
189 });
190 });
190
191
191 this.element.bind('expand_left_panel', function () {
192 this.element.bind('expand_left_panel', function () {
192 var splitter_width = $('div#left_panel_splitter').outerWidth(true);
193 var splitter_width = $('div#left_panel_splitter').outerWidth(true);
193 var left_panel_width = IPython.left_panel.width;
194 var left_panel_width = IPython.left_panel.width;
194 var new_margin = splitter_width + left_panel_width;
195 var new_margin = splitter_width + left_panel_width;
195 $('div#notebook_panel').animate({marginLeft : new_margin + 'px'}, 'fast');
196 $('div#notebook_panel').animate({marginLeft : new_margin + 'px'}, 'fast');
196 });
197 });
197
198
198 $(window).bind('beforeunload', function () {
199 $(window).bind('beforeunload', function () {
199 var kill_kernel = $('#kill_kernel').prop('checked');
200 var kill_kernel = $('#kill_kernel').prop('checked');
200 if (kill_kernel) {
201 if (kill_kernel) {
201 that.kernel.kill();
202 that.kernel.kill();
202 }
203 }
203 if (that.dirty && ! that.read_only) {
204 if (that.dirty && ! that.read_only) {
204 return "You have unsaved changes that will be lost if you leave this page.";
205 return "You have unsaved changes that will be lost if you leave this page.";
205 };
206 };
207 return true;
206 });
208 });
207 };
209 };
208
210
209
211
210 Notebook.prototype.toggle_keyboard_shortcuts = function () {
212 Notebook.prototype.toggle_keyboard_shortcuts = function () {
211 // toggles display of keyboard shortcut dialog
213 // toggles display of keyboard shortcut dialog
212 var that = this;
214 var that = this;
213 if ( this.shortcut_dialog ){
215 if ( this.shortcut_dialog ){
214 // if dialog is already shown, close it
216 // if dialog is already shown, close it
215 this.shortcut_dialog.dialog("close");
217 this.shortcut_dialog.dialog("close");
216 this.shortcut_dialog = null;
218 this.shortcut_dialog = null;
217 return;
219 return;
218 }
220 }
219 var dialog = $('<div/>');
221 var dialog = $('<div/>');
220 this.shortcut_dialog = dialog;
222 this.shortcut_dialog = dialog;
221 var shortcuts = [
223 var shortcuts = [
222 {key: 'Shift-Enter', help: 'run cell'},
224 {key: 'Shift-Enter', help: 'run cell'},
223 {key: 'Ctrl-Enter', help: 'run cell in-place'},
225 {key: 'Ctrl-Enter', help: 'run cell in-place'},
224 {key: 'Ctrl-m d', help: 'delete cell'},
226 {key: 'Ctrl-m d', help: 'delete cell'},
225 {key: 'Ctrl-m a', help: 'insert cell above'},
227 {key: 'Ctrl-m a', help: 'insert cell above'},
226 {key: 'Ctrl-m b', help: 'insert cell below'},
228 {key: 'Ctrl-m b', help: 'insert cell below'},
227 {key: 'Ctrl-m t', help: 'toggle output'},
229 {key: 'Ctrl-m t', help: 'toggle output'},
228 {key: 'Ctrl-m l', help: 'toggle line numbers'},
230 {key: 'Ctrl-m l', help: 'toggle line numbers'},
229 {key: 'Ctrl-m s', help: 'save notebook'},
231 {key: 'Ctrl-m s', help: 'save notebook'},
230 {key: 'Ctrl-m j', help: 'move cell down'},
232 {key: 'Ctrl-m j', help: 'move cell down'},
231 {key: 'Ctrl-m k', help: 'move cell up'},
233 {key: 'Ctrl-m k', help: 'move cell up'},
232 {key: 'Ctrl-m c', help: 'code cell'},
234 {key: 'Ctrl-m c', help: 'code cell'},
233 {key: 'Ctrl-m m', help: 'markdown cell'},
235 {key: 'Ctrl-m m', help: 'markdown cell'},
234 {key: 'Ctrl-m p', help: 'select previous'},
236 {key: 'Ctrl-m p', help: 'select previous'},
235 {key: 'Ctrl-m n', help: 'select next'},
237 {key: 'Ctrl-m n', help: 'select next'},
236 {key: 'Ctrl-m i', help: 'interrupt kernel'},
238 {key: 'Ctrl-m i', help: 'interrupt kernel'},
237 {key: 'Ctrl-m .', help: 'restart kernel'},
239 {key: 'Ctrl-m .', help: 'restart kernel'},
238 {key: 'Ctrl-m h', help: 'show keyboard shortcuts'}
240 {key: 'Ctrl-m h', help: 'show keyboard shortcuts'}
239 ];
241 ];
240 for (var i=0; i<shortcuts.length; i++) {
242 for (var i=0; i<shortcuts.length; i++) {
241 dialog.append($('<div>').
243 dialog.append($('<div>').
242 append($('<span/>').addClass('shortcut_key').html(shortcuts[i].key)).
244 append($('<span/>').addClass('shortcut_key').html(shortcuts[i].key)).
243 append($('<span/>').addClass('shortcut_descr').html(' : ' + shortcuts[i].help))
245 append($('<span/>').addClass('shortcut_descr').html(' : ' + shortcuts[i].help))
244 );
246 );
245 };
247 };
246 dialog.bind('dialogclose', function(event) {
248 dialog.bind('dialogclose', function(event) {
247 // dialog has been closed, allow it to be drawn again.
249 // dialog has been closed, allow it to be drawn again.
248 that.shortcut_dialog = null;
250 that.shortcut_dialog = null;
249 });
251 });
250 dialog.dialog({title: 'Keyboard shortcuts'});
252 dialog.dialog({title: 'Keyboard shortcuts'});
251 };
253 };
252
254
253
255
254 Notebook.prototype.scroll_to_bottom = function () {
256 Notebook.prototype.scroll_to_bottom = function () {
255 this.element.animate({scrollTop:this.element.get(0).scrollHeight}, 0);
257 this.element.animate({scrollTop:this.element.get(0).scrollHeight}, 0);
256 };
258 };
257
259
258
260
259 Notebook.prototype.scroll_to_top = function () {
261 Notebook.prototype.scroll_to_top = function () {
260 this.element.animate({scrollTop:0}, 0);
262 this.element.animate({scrollTop:0}, 0);
261 };
263 };
262
264
263
265
264 // Cell indexing, retrieval, etc.
266 // Cell indexing, retrieval, etc.
265
267
266
268
267 Notebook.prototype.cell_elements = function () {
269 Notebook.prototype.cell_elements = function () {
268 return this.element.children("div.cell");
270 return this.element.children("div.cell");
269 }
271 };
270
272
271
273
272 Notebook.prototype.ncells = function (cell) {
274 Notebook.prototype.ncells = function (cell) {
273 return this.cell_elements().length;
275 return this.cell_elements().length;
274 }
276 };
275
277
276
278
277 // TODO: we are often calling cells as cells()[i], which we should optimize
279 // TODO: we are often calling cells as cells()[i], which we should optimize
278 // to cells(i) or a new method.
280 // to cells(i) or a new method.
279 Notebook.prototype.cells = function () {
281 Notebook.prototype.cells = function () {
280 return this.cell_elements().toArray().map(function (e) {
282 return this.cell_elements().toArray().map(function (e) {
281 return $(e).data("cell");
283 return $(e).data("cell");
282 });
284 });
283 }
285 };
284
286
285
287
286 Notebook.prototype.find_cell_index = function (cell) {
288 Notebook.prototype.find_cell_index = function (cell) {
287 var result = null;
289 var result = null;
288 this.cell_elements().filter(function (index) {
290 this.cell_elements().filter(function (index) {
289 if ($(this).data("cell") === cell) {
291 if ($(this).data("cell") === cell) {
290 result = index;
292 result = index;
291 };
293 };
292 });
294 });
293 return result;
295 return result;
294 };
296 };
295
297
296
298
297 Notebook.prototype.index_or_selected = function (index) {
299 Notebook.prototype.index_or_selected = function (index) {
298 return index || this.selected_index() || 0;
300 return index || this.selected_index() || 0;
299 }
301 };
300
302
301
303
302 Notebook.prototype.select = function (index) {
304 Notebook.prototype.select = function (index) {
303 if (index !== undefined && index >= 0 && index < this.ncells()) {
305 if (index !== undefined && index >= 0 && index < this.ncells()) {
304 if (this.selected_index() !== null) {
306 if (this.selected_index() !== null) {
305 this.selected_cell().unselect();
307 this.selected_cell().unselect();
306 };
308 };
307 this.cells()[index].select();
309 this.cells()[index].select();
308 };
310 };
309 return this;
311 return this;
310 };
312 };
311
313
312
314
313 Notebook.prototype.select_next = function () {
315 Notebook.prototype.select_next = function () {
314 var index = this.selected_index();
316 var index = this.selected_index();
315 if (index !== null && index >= 0 && (index+1) < this.ncells()) {
317 if (index !== null && index >= 0 && (index+1) < this.ncells()) {
316 this.select(index+1);
318 this.select(index+1);
317 };
319 };
318 return this;
320 return this;
319 };
321 };
320
322
321
323
322 Notebook.prototype.select_prev = function () {
324 Notebook.prototype.select_prev = function () {
323 var index = this.selected_index();
325 var index = this.selected_index();
324 if (index !== null && index >= 0 && (index-1) < this.ncells()) {
326 if (index !== null && index >= 0 && (index-1) < this.ncells()) {
325 this.select(index-1);
327 this.select(index-1);
326 };
328 };
327 return this;
329 return this;
328 };
330 };
329
331
330
332
331 Notebook.prototype.selected_index = function () {
333 Notebook.prototype.selected_index = function () {
332 var result = null;
334 var result = null;
333 this.cell_elements().filter(function (index) {
335 this.cell_elements().filter(function (index) {
334 if ($(this).data("cell").selected === true) {
336 if ($(this).data("cell").selected === true) {
335 result = index;
337 result = index;
336 };
338 };
337 });
339 });
338 return result;
340 return result;
339 };
341 };
340
342
341
343
342 Notebook.prototype.cell_for_msg = function (msg_id) {
344 Notebook.prototype.cell_for_msg = function (msg_id) {
343 var cell_id = this.msg_cell_map[msg_id];
345 var cell_id = this.msg_cell_map[msg_id];
344 var result = null;
346 var result = null;
345 this.cell_elements().filter(function (index) {
347 this.cell_elements().filter(function (index) {
346 cell = $(this).data("cell");
348 cell = $(this).data("cell");
347 if (cell.cell_id === cell_id) {
349 if (cell.cell_id === cell_id) {
348 result = cell;
350 result = cell;
349 };
351 };
350 });
352 });
351 return result;
353 return result;
352 };
354 };
353
355
354
356
355 Notebook.prototype.selected_cell = function () {
357 Notebook.prototype.selected_cell = function () {
356 return this.cell_elements().eq(this.selected_index()).data("cell");
358 return this.cell_elements().eq(this.selected_index()).data("cell");
357 }
359 };
358
360
359
361
360 // Cell insertion, deletion and moving.
362 // Cell insertion, deletion and moving.
361
363
362
364
363 Notebook.prototype.delete_cell = function (index) {
365 Notebook.prototype.delete_cell = function (index) {
364 var i = index || this.selected_index();
366 var i = index || this.selected_index();
365 if (i !== null && i >= 0 && i < this.ncells()) {
367 if (i !== null && i >= 0 && i < this.ncells()) {
366 this.cell_elements().eq(i).remove();
368 this.cell_elements().eq(i).remove();
367 if (i === (this.ncells())) {
369 if (i === (this.ncells())) {
368 this.select(i-1);
370 this.select(i-1);
369 } else {
371 } else {
370 this.select(i);
372 this.select(i);
371 };
373 };
372 };
374 };
373 this.dirty = true;
375 this.dirty = true;
374 return this;
376 return this;
375 };
377 };
376
378
377
379
378 Notebook.prototype.append_cell = function (cell) {
380 Notebook.prototype.append_cell = function (cell) {
379 this.element.find('div.end_space').before(cell.element);
381 this.element.find('div.end_space').before(cell.element);
380 this.dirty = true;
382 this.dirty = true;
381 return this;
383 return this;
382 };
384 };
383
385
384
386
385 Notebook.prototype.insert_cell_below = function (cell, index) {
387 Notebook.prototype.insert_cell_below = function (cell, index) {
386 var ncells = this.ncells();
388 var ncells = this.ncells();
387 if (ncells === 0) {
389 if (ncells === 0) {
388 this.append_cell(cell);
390 this.append_cell(cell);
389 return this;
391 return this;
390 };
392 };
391 if (index >= 0 && index < ncells) {
393 if (index >= 0 && index < ncells) {
392 this.cell_elements().eq(index).after(cell.element);
394 this.cell_elements().eq(index).after(cell.element);
393 };
395 };
394 this.dirty = true;
396 this.dirty = true;
395 return this
397 return this;
396 };
398 };
397
399
398
400
399 Notebook.prototype.insert_cell_above = function (cell, index) {
401 Notebook.prototype.insert_cell_above = function (cell, index) {
400 var ncells = this.ncells();
402 var ncells = this.ncells();
401 if (ncells === 0) {
403 if (ncells === 0) {
402 this.append_cell(cell);
404 this.append_cell(cell);
403 return this;
405 return this;
404 };
406 };
405 if (index >= 0 && index < ncells) {
407 if (index >= 0 && index < ncells) {
406 this.cell_elements().eq(index).before(cell.element);
408 this.cell_elements().eq(index).before(cell.element);
407 };
409 };
408 this.dirty = true;
410 this.dirty = true;
409 return this;
411 return this;
410 };
412 };
411
413
412
414
413 Notebook.prototype.move_cell_up = function (index) {
415 Notebook.prototype.move_cell_up = function (index) {
414 var i = index || this.selected_index();
416 var i = index || this.selected_index();
415 if (i !== null && i < this.ncells() && i > 0) {
417 if (i !== null && i < this.ncells() && i > 0) {
416 var pivot = this.cell_elements().eq(i-1);
418 var pivot = this.cell_elements().eq(i-1);
417 var tomove = this.cell_elements().eq(i);
419 var tomove = this.cell_elements().eq(i);
418 if (pivot !== null && tomove !== null) {
420 if (pivot !== null && tomove !== null) {
419 tomove.detach();
421 tomove.detach();
420 pivot.before(tomove);
422 pivot.before(tomove);
421 this.select(i-1);
423 this.select(i-1);
422 };
424 };
423 };
425 };
424 this.dirty = true;
426 this.dirty = true;
425 return this;
427 return this;
426 }
428 };
427
429
428
430
429 Notebook.prototype.move_cell_down = function (index) {
431 Notebook.prototype.move_cell_down = function (index) {
430 var i = index || this.selected_index();
432 var i = index || this.selected_index();
431 if (i !== null && i < (this.ncells()-1) && i >= 0) {
433 if (i !== null && i < (this.ncells()-1) && i >= 0) {
432 var pivot = this.cell_elements().eq(i+1)
434 var pivot = this.cell_elements().eq(i+1);
433 var tomove = this.cell_elements().eq(i)
435 var tomove = this.cell_elements().eq(i);
434 if (pivot !== null && tomove !== null) {
436 if (pivot !== null && tomove !== null) {
435 tomove.detach();
437 tomove.detach();
436 pivot.after(tomove);
438 pivot.after(tomove);
437 this.select(i+1);
439 this.select(i+1);
438 };
440 };
439 };
441 };
440 this.dirty = true;
442 this.dirty = true;
441 return this;
443 return this;
442 }
444 };
443
445
444
446
445 Notebook.prototype.sort_cells = function () {
447 Notebook.prototype.sort_cells = function () {
446 var ncells = this.ncells();
448 var ncells = this.ncells();
447 var sindex = this.selected_index();
449 var sindex = this.selected_index();
448 var swapped;
450 var swapped;
449 do {
451 do {
450 swapped = false
452 swapped = false;
451 for (var i=1; i<ncells; i++) {
453 for (var i=1; i<ncells; i++) {
452 current = this.cell_elements().eq(i).data("cell");
454 current = this.cell_elements().eq(i).data("cell");
453 previous = this.cell_elements().eq(i-1).data("cell");
455 previous = this.cell_elements().eq(i-1).data("cell");
454 if (previous.input_prompt_number > current.input_prompt_number) {
456 if (previous.input_prompt_number > current.input_prompt_number) {
455 this.move_cell_up(i);
457 this.move_cell_up(i);
456 swapped = true;
458 swapped = true;
457 };
459 };
458 };
460 };
459 } while (swapped);
461 } while (swapped);
460 this.select(sindex);
462 this.select(sindex);
461 return this;
463 return this;
462 };
464 };
463
465
464
466
465 Notebook.prototype.insert_code_cell_above = function (index) {
467 Notebook.prototype.insert_code_cell_above = function (index) {
466 // TODO: Bounds check for i
468 // TODO: Bounds check for i
467 var i = this.index_or_selected(index);
469 var i = this.index_or_selected(index);
468 var cell = new IPython.CodeCell(this);
470 var cell = new IPython.CodeCell(this);
469 cell.set_input_prompt();
471 cell.set_input_prompt();
470 this.insert_cell_above(cell, i);
472 this.insert_cell_above(cell, i);
471 this.select(this.find_cell_index(cell));
473 this.select(this.find_cell_index(cell));
472 return cell;
474 return cell;
473 }
475 };
474
476
475
477
476 Notebook.prototype.insert_code_cell_below = function (index) {
478 Notebook.prototype.insert_code_cell_below = function (index) {
477 // TODO: Bounds check for i
479 // TODO: Bounds check for i
478 var i = this.index_or_selected(index);
480 var i = this.index_or_selected(index);
479 var cell = new IPython.CodeCell(this);
481 var cell = new IPython.CodeCell(this);
480 cell.set_input_prompt();
482 cell.set_input_prompt();
481 this.insert_cell_below(cell, i);
483 this.insert_cell_below(cell, i);
482 this.select(this.find_cell_index(cell));
484 this.select(this.find_cell_index(cell));
483 return cell;
485 return cell;
484 }
486 };
485
487
486
488
487 Notebook.prototype.insert_html_cell_above = function (index) {
489 Notebook.prototype.insert_html_cell_above = function (index) {
488 // TODO: Bounds check for i
490 // TODO: Bounds check for i
489 var i = this.index_or_selected(index);
491 var i = this.index_or_selected(index);
490 var cell = new IPython.HTMLCell(this);
492 var cell = new IPython.HTMLCell(this);
491 cell.config_mathjax();
493 cell.config_mathjax();
492 this.insert_cell_above(cell, i);
494 this.insert_cell_above(cell, i);
493 this.select(this.find_cell_index(cell));
495 this.select(this.find_cell_index(cell));
494 return cell;
496 return cell;
495 }
497 };
496
498
497
499
498 Notebook.prototype.insert_html_cell_below = function (index) {
500 Notebook.prototype.insert_html_cell_below = function (index) {
499 // TODO: Bounds check for i
501 // TODO: Bounds check for i
500 var i = this.index_or_selected(index);
502 var i = this.index_or_selected(index);
501 var cell = new IPython.HTMLCell(this);
503 var cell = new IPython.HTMLCell(this);
502 cell.config_mathjax();
504 cell.config_mathjax();
503 this.insert_cell_below(cell, i);
505 this.insert_cell_below(cell, i);
504 this.select(this.find_cell_index(cell));
506 this.select(this.find_cell_index(cell));
505 return cell;
507 return cell;
506 }
508 };
507
509
508
510
509 Notebook.prototype.insert_markdown_cell_above = function (index) {
511 Notebook.prototype.insert_markdown_cell_above = function (index) {
510 // TODO: Bounds check for i
512 // TODO: Bounds check for i
511 var i = this.index_or_selected(index);
513 var i = this.index_or_selected(index);
512 var cell = new IPython.MarkdownCell(this);
514 var cell = new IPython.MarkdownCell(this);
513 cell.config_mathjax();
515 cell.config_mathjax();
514 this.insert_cell_above(cell, i);
516 this.insert_cell_above(cell, i);
515 this.select(this.find_cell_index(cell));
517 this.select(this.find_cell_index(cell));
516 return cell;
518 return cell;
517 }
519 };
518
520
519
521
520 Notebook.prototype.insert_markdown_cell_below = function (index) {
522 Notebook.prototype.insert_markdown_cell_below = function (index) {
521 // TODO: Bounds check for i
523 // TODO: Bounds check for i
522 var i = this.index_or_selected(index);
524 var i = this.index_or_selected(index);
523 var cell = new IPython.MarkdownCell(this);
525 var cell = new IPython.MarkdownCell(this);
524 cell.config_mathjax();
526 cell.config_mathjax();
525 this.insert_cell_below(cell, i);
527 this.insert_cell_below(cell, i);
526 this.select(this.find_cell_index(cell));
528 this.select(this.find_cell_index(cell));
527 return cell;
529 return cell;
528 }
530 };
529
531
530
532
531 Notebook.prototype.to_code = function (index) {
533 Notebook.prototype.to_code = function (index) {
532 // TODO: Bounds check for i
534 // TODO: Bounds check for i
533 var i = this.index_or_selected(index);
535 var i = this.index_or_selected(index);
534 var source_element = this.cell_elements().eq(i);
536 var source_element = this.cell_elements().eq(i);
535 var source_cell = source_element.data("cell");
537 var source_cell = source_element.data("cell");
536 if (source_cell instanceof IPython.HTMLCell ||
538 if (source_cell instanceof IPython.HTMLCell ||
537 source_cell instanceof IPython.MarkdownCell) {
539 source_cell instanceof IPython.MarkdownCell) {
538 this.insert_code_cell_below(i);
540 this.insert_code_cell_below(i);
539 var target_cell = this.cells()[i+1];
541 var target_cell = this.cells()[i+1];
540 target_cell.set_code(source_cell.get_source());
542 target_cell.set_code(source_cell.get_source());
541 source_element.remove();
543 source_element.remove();
542 target_cell.select();
544 target_cell.select();
543 };
545 };
544 this.dirty = true;
546 this.dirty = true;
545 };
547 };
546
548
547
549
548 Notebook.prototype.to_markdown = function (index) {
550 Notebook.prototype.to_markdown = function (index) {
549 // TODO: Bounds check for i
551 // TODO: Bounds check for i
550 var i = this.index_or_selected(index);
552 var i = this.index_or_selected(index);
551 var source_element = this.cell_elements().eq(i);
553 var source_element = this.cell_elements().eq(i);
552 var source_cell = source_element.data("cell");
554 var source_cell = source_element.data("cell");
553 var target_cell = null;
555 var target_cell = null;
554 if (source_cell instanceof IPython.CodeCell) {
556 if (source_cell instanceof IPython.CodeCell) {
555 this.insert_markdown_cell_below(i);
557 this.insert_markdown_cell_below(i);
556 var target_cell = this.cells()[i+1];
558 target_cell = this.cells()[i+1];
557 var text = source_cell.get_code();
559 var text = source_cell.get_code();
558 } else if (source_cell instanceof IPython.HTMLCell) {
560 } else if (source_cell instanceof IPython.HTMLCell) {
559 this.insert_markdown_cell_below(i);
561 this.insert_markdown_cell_below(i);
560 var target_cell = this.cells()[i+1];
562 target_cell = this.cells()[i+1];
561 var text = source_cell.get_source();
563 var text = source_cell.get_source();
562 if (text === source_cell.placeholder) {
564 if (text === source_cell.placeholder) {
563 text = target_cell.placeholder;
565 text = target_cell.placeholder;
564 }
566 }
565 }
567 }
566 if (target_cell !== null) {
568 if (target_cell !== null) {
567 if (text === "") {text = target_cell.placeholder;};
569 if (text === "") {text = target_cell.placeholder;};
568 target_cell.set_source(text);
570 target_cell.set_source(text);
569 source_element.remove();
571 source_element.remove();
570 target_cell.edit();
572 target_cell.edit();
571 }
573 }
572 this.dirty = true;
574 this.dirty = true;
573 };
575 };
574
576
575
577
576 Notebook.prototype.to_html = function (index) {
578 Notebook.prototype.to_html = function (index) {
577 // TODO: Bounds check for i
579 // TODO: Bounds check for i
578 var i = this.index_or_selected(index);
580 var i = this.index_or_selected(index);
579 var source_element = this.cell_elements().eq(i);
581 var source_element = this.cell_elements().eq(i);
580 var source_cell = source_element.data("cell");
582 var source_cell = source_element.data("cell");
581 var target_cell = null;
583 var target_cell = null;
582 if (source_cell instanceof IPython.CodeCell) {
584 if (source_cell instanceof IPython.CodeCell) {
583 this.insert_html_cell_below(i);
585 this.insert_html_cell_below(i);
584 var target_cell = this.cells()[i+1];
586 target_cell = this.cells()[i+1];
585 var text = source_cell.get_code();
587 var text = source_cell.get_code();
586 } else if (source_cell instanceof IPython.MarkdownCell) {
588 } else if (source_cell instanceof IPython.MarkdownCell) {
587 this.insert_html_cell_below(i);
589 this.insert_html_cell_below(i);
588 var target_cell = this.cells()[i+1];
590 target_cell = this.cells()[i+1];
589 var text = source_cell.get_source();
591 var text = source_cell.get_source();
590 if (text === source_cell.placeholder) {
592 if (text === source_cell.placeholder) {
591 text = target_cell.placeholder;
593 text = target_cell.placeholder;
592 }
594 }
593 }
595 }
594 if (target_cell !== null) {
596 if (target_cell !== null) {
595 if (text === "") {text = target_cell.placeholder;};
597 if (text === "") {text = target_cell.placeholder;};
596 target_cell.set_source(text);
598 target_cell.set_source(text);
597 source_element.remove();
599 source_element.remove();
598 target_cell.edit();
600 target_cell.edit();
599 }
601 }
600 this.dirty = true;
602 this.dirty = true;
601 };
603 };
602
604
603
605
604 // Cell collapsing and output clearing
606 // Cell collapsing and output clearing
605
607
606 Notebook.prototype.collapse = function (index) {
608 Notebook.prototype.collapse = function (index) {
607 var i = this.index_or_selected(index);
609 var i = this.index_or_selected(index);
608 this.cells()[i].collapse();
610 this.cells()[i].collapse();
609 this.dirty = true;
611 this.dirty = true;
610 };
612 };
611
613
612
614
613 Notebook.prototype.expand = function (index) {
615 Notebook.prototype.expand = function (index) {
614 var i = this.index_or_selected(index);
616 var i = this.index_or_selected(index);
615 this.cells()[i].expand();
617 this.cells()[i].expand();
616 this.dirty = true;
618 this.dirty = true;
617 };
619 };
618
620
619
621
620 Notebook.prototype.toggle_output = function (index) {
622 Notebook.prototype.toggle_output = function (index) {
621 var i = this.index_or_selected(index);
623 var i = this.index_or_selected(index);
622 this.cells()[i].toggle_output();
624 this.cells()[i].toggle_output();
623 this.dirty = true;
625 this.dirty = true;
624 };
626 };
625
627
626
628
627 Notebook.prototype.set_timebeforetooltip = function (time) {
629 Notebook.prototype.set_timebeforetooltip = function (time) {
628 console.log("change time before tooltip to : "+time);
630 console.log("change time before tooltip to : "+time);
629 this.time_before_tooltip = time;
631 this.time_before_tooltip = time;
630 };
632 };
631
633
632 Notebook.prototype.set_tooltipontab = function (state) {
634 Notebook.prototype.set_tooltipontab = function (state) {
633 console.log("change tooltip on tab to : "+state);
635 console.log("change tooltip on tab to : "+state);
634 this.tooltip_on_tab = state;
636 this.tooltip_on_tab = state;
635 };
637 };
636
638
637 Notebook.prototype.set_smartcompleter = function (state) {
639 Notebook.prototype.set_smartcompleter = function (state) {
638 console.log("Smart completion (kwargs first) changed to to : "+state);
640 console.log("Smart completion (kwargs first) changed to to : "+state);
639 this.smart_completer = state;
641 this.smart_completer = state;
640 };
642 };
641
643
642 Notebook.prototype.set_autoindent = function (state) {
644 Notebook.prototype.set_autoindent = function (state) {
643 var cells = this.cells();
645 var cells = this.cells();
644 len = cells.length;
646 len = cells.length;
645 for (var i=0; i<len; i++) {
647 for (var i=0; i<len; i++) {
646 cells[i].set_autoindent(state)
648 cells[i].set_autoindent(state);
647 };
649 };
648 };
650 };
649
651
650
652
651 Notebook.prototype.clear_all_output = function () {
653 Notebook.prototype.clear_all_output = function () {
652 var ncells = this.ncells();
654 var ncells = this.ncells();
653 var cells = this.cells();
655 var cells = this.cells();
654 for (var i=0; i<ncells; i++) {
656 for (var i=0; i<ncells; i++) {
655 if (cells[i] instanceof IPython.CodeCell) {
657 if (cells[i] instanceof IPython.CodeCell) {
656 cells[i].clear_output(true,true,true);
658 cells[i].clear_output(true,true,true);
657 }
659 }
658 };
660 };
659 this.dirty = true;
661 this.dirty = true;
660 };
662 };
661
663
662 // Other cell functions: line numbers, ...
664 // Other cell functions: line numbers, ...
663
665
664 Notebook.prototype.cell_toggle_line_numbers = function() {
666 Notebook.prototype.cell_toggle_line_numbers = function() {
665 this.selected_cell().toggle_line_numbers()
667 this.selected_cell().toggle_line_numbers();
666 };
668 };
667
669
668 // Kernel related things
670 // Kernel related things
669
671
670 Notebook.prototype.start_kernel = function () {
672 Notebook.prototype.start_kernel = function () {
671 this.kernel = new IPython.Kernel();
673 this.kernel = new IPython.Kernel();
672 var notebook_id = IPython.save_widget.get_notebook_id();
674 var notebook_id = IPython.save_widget.get_notebook_id();
673 this.kernel.start(notebook_id, $.proxy(this.kernel_started, this));
675 this.kernel.start(notebook_id, $.proxy(this.kernel_started, this));
674 };
676 };
675
677
676
678
677 Notebook.prototype.restart_kernel = function () {
679 Notebook.prototype.restart_kernel = function () {
678 var that = this;
680 var that = this;
679 var notebook_id = IPython.save_widget.get_notebook_id();
681 var notebook_id = IPython.save_widget.get_notebook_id();
680
682
681 var dialog = $('<div/>');
683 var dialog = $('<div/>');
682 dialog.html('Do you want to restart the current kernel? You will lose all variables defined in it.');
684 dialog.html('Do you want to restart the current kernel? You will lose all variables defined in it.');
683 $(document).append(dialog);
685 $(document).append(dialog);
684 dialog.dialog({
686 dialog.dialog({
685 resizable: false,
687 resizable: false,
686 modal: true,
688 modal: true,
687 title: "Restart kernel or continue running?",
689 title: "Restart kernel or continue running?",
688 buttons : {
690 buttons : {
689 "Restart": function () {
691 "Restart": function () {
690 that.kernel.restart($.proxy(that.kernel_started, that));
692 that.kernel.restart($.proxy(that.kernel_started, that));
691 $(this).dialog('close');
693 $(this).dialog('close');
692 },
694 },
693 "Continue running": function () {
695 "Continue running": function () {
694 $(this).dialog('close');
696 $(this).dialog('close');
695 }
697 }
696 }
698 }
697 });
699 });
698 };
700 };
699
701
700
702
701 Notebook.prototype.kernel_started = function () {
703 Notebook.prototype.kernel_started = function () {
702 console.log("Kernel started: ", this.kernel.kernel_id);
704 console.log("Kernel started: ", this.kernel.kernel_id);
703 this.kernel.shell_channel.onmessage = $.proxy(this.handle_shell_reply,this);
705 this.kernel.shell_channel.onmessage = $.proxy(this.handle_shell_reply,this);
704 this.kernel.iopub_channel.onmessage = $.proxy(this.handle_iopub_reply,this);
706 this.kernel.iopub_channel.onmessage = $.proxy(this.handle_iopub_reply,this);
705 };
707 };
706
708
707
709
708 Notebook.prototype.handle_shell_reply = function (e) {
710 Notebook.prototype.handle_shell_reply = function (e) {
709 reply = $.parseJSON(e.data);
711 reply = $.parseJSON(e.data);
710 var header = reply.header;
712 var header = reply.header;
711 var content = reply.content;
713 var content = reply.content;
712 var msg_type = header.msg_type;
714 var msg_type = header.msg_type;
713 // console.log(reply);
715 // console.log(reply);
714 var cell = this.cell_for_msg(reply.parent_header.msg_id);
716 var cell = this.cell_for_msg(reply.parent_header.msg_id);
715 if (msg_type === "execute_reply") {
717 if (msg_type === "execute_reply") {
716 cell.set_input_prompt(content.execution_count);
718 cell.set_input_prompt(content.execution_count);
717 cell.element.removeClass("running");
719 cell.element.removeClass("running");
718 this.dirty = true;
720 this.dirty = true;
719 } else if (msg_type === "complete_reply") {
721 } else if (msg_type === "complete_reply") {
720 cell.finish_completing(content.matched_text, content.matches);
722 cell.finish_completing(content.matched_text, content.matches);
721 } else if (msg_type === "object_info_reply"){
723 } else if (msg_type === "object_info_reply"){
722 //console.log('back from object_info_request : ')
724 //console.log('back from object_info_request : ')
723 rep = reply.content;
725 rep = reply.content;
724 if(rep.found)
726 if(rep.found)
725 {
727 {
726 cell.finish_tooltip(rep);
728 cell.finish_tooltip(rep);
727 }
729 }
728 } else {
730 } else {
729 //console.log("unknown reply:"+msg_type);
731 //console.log("unknown reply:"+msg_type);
730 }
732 }
731 // when having a rely from object_info_reply,
733 // when having a rely from object_info_reply,
732 // no payload so no nned to handle it
734 // no payload so no nned to handle it
733 if(typeof(content.payload)!='undefined') {
735 if(typeof(content.payload)!='undefined') {
734 var payload = content.payload || [];
736 var payload = content.payload || [];
735 this.handle_payload(cell, payload);
737 this.handle_payload(cell, payload);
736 }
738 }
737 };
739 };
738
740
739
741
740 Notebook.prototype.handle_payload = function (cell, payload) {
742 Notebook.prototype.handle_payload = function (cell, payload) {
741 var l = payload.length;
743 var l = payload.length;
742 for (var i=0; i<l; i++) {
744 for (var i=0; i<l; i++) {
743 if (payload[i].source === 'IPython.zmq.page.page') {
745 if (payload[i].source === 'IPython.zmq.page.page') {
744 if (payload[i].text.trim() !== '') {
746 if (payload[i].text.trim() !== '') {
745 IPython.pager.clear();
747 IPython.pager.clear();
746 IPython.pager.expand();
748 IPython.pager.expand();
747 IPython.pager.append_text(payload[i].text);
749 IPython.pager.append_text(payload[i].text);
748 }
750 }
749 } else if (payload[i].source === 'IPython.zmq.zmqshell.ZMQInteractiveShell.set_next_input') {
751 } else if (payload[i].source === 'IPython.zmq.zmqshell.ZMQInteractiveShell.set_next_input') {
750 var index = this.find_cell_index(cell);
752 var index = this.find_cell_index(cell);
751 var new_cell = this.insert_code_cell_below(index);
753 var new_cell = this.insert_code_cell_below(index);
752 new_cell.set_code(payload[i].text);
754 new_cell.set_code(payload[i].text);
753 this.dirty = true;
755 this.dirty = true;
754 }
756 }
755 };
757 };
756 };
758 };
757
759
758
760
759 Notebook.prototype.handle_iopub_reply = function (e) {
761 Notebook.prototype.handle_iopub_reply = function (e) {
760 reply = $.parseJSON(e.data);
762 reply = $.parseJSON(e.data);
761 var content = reply.content;
763 var content = reply.content;
762 // console.log(reply);
764 // console.log(reply);
763 var msg_type = reply.header.msg_type;
765 var msg_type = reply.header.msg_type;
764 var cell = this.cell_for_msg(reply.parent_header.msg_id);
766 var cell = this.cell_for_msg(reply.parent_header.msg_id);
765 if (!cell){
767 if (!cell){
766 // message not from this notebook
768 // message not from this notebook
767 console.log("Received IOPub message not caused by one of my cells");
769 console.log("Received IOPub message not caused by one of my cells");
768 return;
770 return;
769 }
771 }
770 var output_types = ['stream','display_data','pyout','pyerr'];
772 var output_types = ['stream','display_data','pyout','pyerr'];
771 if (output_types.indexOf(msg_type) >= 0) {
773 if (output_types.indexOf(msg_type) >= 0) {
772 this.handle_output(cell, msg_type, content);
774 this.handle_output(cell, msg_type, content);
773 } else if (msg_type === 'status') {
775 } else if (msg_type === 'status') {
774 if (content.execution_state === 'busy') {
776 if (content.execution_state === 'busy') {
775 IPython.kernel_status_widget.status_busy();
777 IPython.kernel_status_widget.status_busy();
776 } else if (content.execution_state === 'idle') {
778 } else if (content.execution_state === 'idle') {
777 IPython.kernel_status_widget.status_idle();
779 IPython.kernel_status_widget.status_idle();
778 } else if (content.execution_state === 'dead') {
780 } else if (content.execution_state === 'dead') {
779 this.handle_status_dead();
781 this.handle_status_dead();
780 };
782 };
781 } else if (msg_type === 'clear_output') {
783 } else if (msg_type === 'clear_output') {
782 cell.clear_output(content.stdout, content.stderr, content.other);
784 cell.clear_output(content.stdout, content.stderr, content.other);
783 };
785 };
784 };
786 };
785
787
786
788
787 Notebook.prototype.handle_status_dead = function () {
789 Notebook.prototype.handle_status_dead = function () {
788 var that = this;
790 var that = this;
789 this.kernel.stop_channels();
791 this.kernel.stop_channels();
790 var dialog = $('<div/>');
792 var dialog = $('<div/>');
791 dialog.html('The kernel has died, would you like to restart it? If you do not restart the kernel, you will be able to save the notebook, but running code will not work until the notebook is reopened.');
793 dialog.html('The kernel has died, would you like to restart it? If you do not restart the kernel, you will be able to save the notebook, but running code will not work until the notebook is reopened.');
792 $(document).append(dialog);
794 $(document).append(dialog);
793 dialog.dialog({
795 dialog.dialog({
794 resizable: false,
796 resizable: false,
795 modal: true,
797 modal: true,
796 title: "Dead kernel",
798 title: "Dead kernel",
797 buttons : {
799 buttons : {
798 "Restart": function () {
800 "Restart": function () {
799 that.start_kernel();
801 that.start_kernel();
800 $(this).dialog('close');
802 $(this).dialog('close');
801 },
803 },
802 "Continue running": function () {
804 "Continue running": function () {
803 $(this).dialog('close');
805 $(this).dialog('close');
804 }
806 }
805 }
807 }
806 });
808 });
807 };
809 };
808
810
809
811
810 Notebook.prototype.handle_output = function (cell, msg_type, content) {
812 Notebook.prototype.handle_output = function (cell, msg_type, content) {
811 var json = {};
813 var json = {};
812 json.output_type = msg_type;
814 json.output_type = msg_type;
813 if (msg_type === "stream") {
815 if (msg_type === "stream") {
814 json.text = utils.fixConsole(content.data);
816 json.text = utils.fixConsole(content.data);
815 json.stream = content.name;
817 json.stream = content.name;
816 } else if (msg_type === "display_data") {
818 } else if (msg_type === "display_data") {
817 json = this.convert_mime_types(json, content.data);
819 json = this.convert_mime_types(json, content.data);
818 } else if (msg_type === "pyout") {
820 } else if (msg_type === "pyout") {
819 json.prompt_number = content.execution_count;
821 json.prompt_number = content.execution_count;
820 json = this.convert_mime_types(json, content.data);
822 json = this.convert_mime_types(json, content.data);
821 } else if (msg_type === "pyerr") {
823 } else if (msg_type === "pyerr") {
822 json.ename = content.ename;
824 json.ename = content.ename;
823 json.evalue = content.evalue;
825 json.evalue = content.evalue;
824 var traceback = [];
826 var traceback = [];
825 for (var i=0; i<content.traceback.length; i++) {
827 for (var i=0; i<content.traceback.length; i++) {
826 traceback.push(utils.fixConsole(content.traceback[i]));
828 traceback.push(utils.fixConsole(content.traceback[i]));
827 }
829 }
828 json.traceback = traceback;
830 json.traceback = traceback;
829 };
831 };
830 cell.append_output(json);
832 cell.append_output(json);
831 this.dirty = true;
833 this.dirty = true;
832 };
834 };
833
835
834
836
835 Notebook.prototype.convert_mime_types = function (json, data) {
837 Notebook.prototype.convert_mime_types = function (json, data) {
836 if (data['text/plain'] !== undefined) {
838 if (data['text/plain'] !== undefined) {
837 json.text = utils.fixConsole(data['text/plain']);
839 json.text = utils.fixConsole(data['text/plain']);
838 };
840 };
839 if (data['text/html'] !== undefined) {
841 if (data['text/html'] !== undefined) {
840 json.html = data['text/html'];
842 json.html = data['text/html'];
841 };
843 };
842 if (data['image/svg+xml'] !== undefined) {
844 if (data['image/svg+xml'] !== undefined) {
843 json.svg = data['image/svg+xml'];
845 json.svg = data['image/svg+xml'];
844 };
846 };
845 if (data['image/png'] !== undefined) {
847 if (data['image/png'] !== undefined) {
846 json.png = data['image/png'];
848 json.png = data['image/png'];
847 };
849 };
848 if (data['image/jpeg'] !== undefined) {
850 if (data['image/jpeg'] !== undefined) {
849 json.jpeg = data['image/jpeg'];
851 json.jpeg = data['image/jpeg'];
850 };
852 };
851 if (data['text/latex'] !== undefined) {
853 if (data['text/latex'] !== undefined) {
852 json.latex = data['text/latex'];
854 json.latex = data['text/latex'];
853 };
855 };
854 if (data['application/json'] !== undefined) {
856 if (data['application/json'] !== undefined) {
855 json.json = data['application/json'];
857 json.json = data['application/json'];
856 };
858 };
857 if (data['application/javascript'] !== undefined) {
859 if (data['application/javascript'] !== undefined) {
858 json.javascript = data['application/javascript'];
860 json.javascript = data['application/javascript'];
859 }
861 }
860 return json;
862 return json;
861 };
863 };
862
864
863
865
864 Notebook.prototype.execute_selected_cell = function (options) {
866 Notebook.prototype.execute_selected_cell = function (options) {
865 // add_new: should a new cell be added if we are at the end of the nb
867 // add_new: should a new cell be added if we are at the end of the nb
866 // terminal: execute in terminal mode, which stays in the current cell
868 // terminal: execute in terminal mode, which stays in the current cell
867 default_options = {terminal: false, add_new: true}
869 default_options = {terminal: false, add_new: true};
868 $.extend(default_options, options)
870 $.extend(default_options, options);
869 var that = this;
871 var that = this;
870 var cell = that.selected_cell();
872 var cell = that.selected_cell();
871 var cell_index = that.find_cell_index(cell);
873 var cell_index = that.find_cell_index(cell);
872 if (cell instanceof IPython.CodeCell) {
874 if (cell instanceof IPython.CodeCell) {
873 cell.clear_output(true, true, true);
875 cell.clear_output(true, true, true);
874 cell.set_input_prompt('*');
876 cell.set_input_prompt('*');
875 cell.element.addClass("running");
877 cell.element.addClass("running");
876 var code = cell.get_code();
878 var code = cell.get_code();
877 var msg_id = that.kernel.execute(cell.get_code());
879 var msg_id = that.kernel.execute(cell.get_code());
878 that.msg_cell_map[msg_id] = cell.cell_id;
880 that.msg_cell_map[msg_id] = cell.cell_id;
879 } else if (cell instanceof IPython.HTMLCell) {
881 } else if (cell instanceof IPython.HTMLCell) {
880 cell.render();
882 cell.render();
881 }
883 }
882 if (default_options.terminal) {
884 if (default_options.terminal) {
883 cell.select_all();
885 cell.select_all();
884 } else {
886 } else {
885 if ((cell_index === (that.ncells()-1)) && default_options.add_new) {
887 if ((cell_index === (that.ncells()-1)) && default_options.add_new) {
886 that.insert_code_cell_below();
888 that.insert_code_cell_below();
887 // If we are adding a new cell at the end, scroll down to show it.
889 // If we are adding a new cell at the end, scroll down to show it.
888 that.scroll_to_bottom();
890 that.scroll_to_bottom();
889 } else {
891 } else {
890 that.select(cell_index+1);
892 that.select(cell_index+1);
891 };
893 };
892 };
894 };
893 this.dirty = true;
895 this.dirty = true;
894 };
896 };
895
897
896
898
897 Notebook.prototype.execute_all_cells = function () {
899 Notebook.prototype.execute_all_cells = function () {
898 var ncells = this.ncells();
900 var ncells = this.ncells();
899 for (var i=0; i<ncells; i++) {
901 for (var i=0; i<ncells; i++) {
900 this.select(i);
902 this.select(i);
901 this.execute_selected_cell({add_new:false});
903 this.execute_selected_cell({add_new:false});
902 };
904 };
903 this.scroll_to_bottom();
905 this.scroll_to_bottom();
904 };
906 };
905
907
906
908
907 Notebook.prototype.request_tool_tip = function (cell,func) {
909 Notebook.prototype.request_tool_tip = function (cell,func) {
908 // Feel free to shorten this logic if you are better
910 // Feel free to shorten this logic if you are better
909 // than me in regEx
911 // than me in regEx
910 // basicaly you shoul be able to get xxx.xxx.xxx from
912 // basicaly you shoul be able to get xxx.xxx.xxx from
911 // something(range(10), kwarg=smth) ; xxx.xxx.xxx( firstarg, rand(234,23), kwarg1=2,
913 // something(range(10), kwarg=smth) ; xxx.xxx.xxx( firstarg, rand(234,23), kwarg1=2,
912 // remove everything between matchin bracket (need to iterate)
914 // remove everything between matchin bracket (need to iterate)
913 matchBracket = /\([^\(\)]+\)/g;
915 matchBracket = /\([^\(\)]+\)/g;
914 oldfunc = func;
916 oldfunc = func;
915 func = func.replace(matchBracket,"");
917 func = func.replace(matchBracket,"");
916 while( oldfunc != func )
918 while( oldfunc != func )
917 {
919 {
918 oldfunc = func;
920 oldfunc = func;
919 func = func.replace(matchBracket,"");
921 func = func.replace(matchBracket,"");
920 }
922 }
921 // remove everythin after last open bracket
923 // remove everythin after last open bracket
922 endBracket = /\([^\(]*$/g;
924 endBracket = /\([^\(]*$/g;
923 func = func.replace(endBracket,"");
925 func = func.replace(endBracket,"");
924 var re = /[a-zA-Z._]+$/g;
926 var re = /[a-zA-Z._]+$/g;
925 var msg_id = this.kernel.object_info_request(re.exec(func));
927 var msg_id = this.kernel.object_info_request(re.exec(func));
926 if(typeof(msg_id)!='undefined'){
928 if(typeof(msg_id)!='undefined'){
927 this.msg_cell_map[msg_id] = cell.cell_id;
929 this.msg_cell_map[msg_id] = cell.cell_id;
928 }
930 }
929 };
931 };
930
932
931 Notebook.prototype.complete_cell = function (cell, line, cursor_pos) {
933 Notebook.prototype.complete_cell = function (cell, line, cursor_pos) {
932 var msg_id = this.kernel.complete(line, cursor_pos);
934 var msg_id = this.kernel.complete(line, cursor_pos);
933 this.msg_cell_map[msg_id] = cell.cell_id;
935 this.msg_cell_map[msg_id] = cell.cell_id;
934 };
936 };
935
937
936 // Persistance and loading
938 // Persistance and loading
937
939
938
940
939 Notebook.prototype.fromJSON = function (data) {
941 Notebook.prototype.fromJSON = function (data) {
940 var ncells = this.ncells();
942 var ncells = this.ncells();
941 for (var i=0; i<ncells; i++) {
943 var i;
944 for (i=0; i<ncells; i++) {
942 // Always delete cell 0 as they get renumbered as they are deleted.
945 // Always delete cell 0 as they get renumbered as they are deleted.
943 this.delete_cell(0);
946 this.delete_cell(0);
944 };
947 };
945 // Save the metadata
948 // Save the metadata
946 this.metadata = data.metadata;
949 this.metadata = data.metadata;
947 // Only handle 1 worksheet for now.
950 // Only handle 1 worksheet for now.
948 var worksheet = data.worksheets[0];
951 var worksheet = data.worksheets[0];
949 if (worksheet !== undefined) {
952 if (worksheet !== undefined) {
950 var new_cells = worksheet.cells;
953 var new_cells = worksheet.cells;
951 ncells = new_cells.length;
954 ncells = new_cells.length;
952 var cell_data = null;
955 var cell_data = null;
953 var new_cell = null;
956 var new_cell = null;
954 for (var i=0; i<ncells; i++) {
957 for (i=0; i<ncells; i++) {
955 cell_data = new_cells[i];
958 cell_data = new_cells[i];
956 if (cell_data.cell_type == 'code') {
959 if (cell_data.cell_type == 'code') {
957 new_cell = this.insert_code_cell_below();
960 new_cell = this.insert_code_cell_below();
958 new_cell.fromJSON(cell_data);
961 new_cell.fromJSON(cell_data);
959 } else if (cell_data.cell_type === 'html') {
962 } else if (cell_data.cell_type === 'html') {
960 new_cell = this.insert_html_cell_below();
963 new_cell = this.insert_html_cell_below();
961 new_cell.fromJSON(cell_data);
964 new_cell.fromJSON(cell_data);
962 } else if (cell_data.cell_type === 'markdown') {
965 } else if (cell_data.cell_type === 'markdown') {
963 new_cell = this.insert_markdown_cell_below();
966 new_cell = this.insert_markdown_cell_below();
964 new_cell.fromJSON(cell_data);
967 new_cell.fromJSON(cell_data);
965 };
968 };
966 };
969 };
967 };
970 };
968 };
971 };
969
972
970
973
971 Notebook.prototype.toJSON = function () {
974 Notebook.prototype.toJSON = function () {
972 var cells = this.cells();
975 var cells = this.cells();
973 var ncells = cells.length;
976 var ncells = cells.length;
974 cell_array = new Array(ncells);
977 cell_array = new Array(ncells);
975 for (var i=0; i<ncells; i++) {
978 for (var i=0; i<ncells; i++) {
976 cell_array[i] = cells[i].toJSON();
979 cell_array[i] = cells[i].toJSON();
977 };
980 };
978 data = {
981 data = {
979 // Only handle 1 worksheet for now.
982 // Only handle 1 worksheet for now.
980 worksheets : [{cells:cell_array}],
983 worksheets : [{cells:cell_array}],
981 metadata : this.metadata
984 metadata : this.metadata
982 }
985 };
983 return data
986 return data;
984 };
987 };
985
988
986 Notebook.prototype.save_notebook = function () {
989 Notebook.prototype.save_notebook = function () {
987 if (IPython.save_widget.test_notebook_name()) {
990 if (IPython.save_widget.test_notebook_name()) {
988 var notebook_id = IPython.save_widget.get_notebook_id();
991 var notebook_id = IPython.save_widget.get_notebook_id();
989 var nbname = IPython.save_widget.get_notebook_name();
992 var nbname = IPython.save_widget.get_notebook_name();
990 // We may want to move the name/id/nbformat logic inside toJSON?
993 // We may want to move the name/id/nbformat logic inside toJSON?
991 var data = this.toJSON();
994 var data = this.toJSON();
992 data.metadata.name = nbname;
995 data.metadata.name = nbname;
993 data.nbformat = 2;
996 data.nbformat = 2;
994 // We do the call with settings so we can set cache to false.
997 // We do the call with settings so we can set cache to false.
995 var settings = {
998 var settings = {
996 processData : false,
999 processData : false,
997 cache : false,
1000 cache : false,
998 type : "PUT",
1001 type : "PUT",
999 data : JSON.stringify(data),
1002 data : JSON.stringify(data),
1000 headers : {'Content-Type': 'application/json'},
1003 headers : {'Content-Type': 'application/json'},
1001 success : $.proxy(this.notebook_saved,this),
1004 success : $.proxy(this.notebook_saved,this),
1002 error : $.proxy(this.notebook_save_failed,this)
1005 error : $.proxy(this.notebook_save_failed,this)
1003 };
1006 };
1004 IPython.save_widget.status_saving();
1007 IPython.save_widget.status_saving();
1005 var url = $('body').data('baseProjectUrl') + 'notebooks/' + notebook_id
1008 var url = $('body').data('baseProjectUrl') + 'notebooks/' + notebook_id;
1006 $.ajax(url, settings);
1009 $.ajax(url, settings);
1007 };
1010 };
1008 };
1011 };
1009
1012
1010
1013
1011 Notebook.prototype.notebook_saved = function (data, status, xhr) {
1014 Notebook.prototype.notebook_saved = function (data, status, xhr) {
1012 this.dirty = false;
1015 this.dirty = false;
1013 IPython.save_widget.notebook_saved();
1016 IPython.save_widget.notebook_saved();
1014 IPython.save_widget.status_save();
1017 IPython.save_widget.status_save();
1015 }
1018 };
1016
1019
1017
1020
1018 Notebook.prototype.notebook_save_failed = function (xhr, status, error_msg) {
1021 Notebook.prototype.notebook_save_failed = function (xhr, status, error_msg) {
1019 // Notify the user and reset the save button
1022 // Notify the user and reset the save button
1020 // TODO: Handle different types of errors (timeout etc.)
1023 // TODO: Handle different types of errors (timeout etc.)
1021 alert('An unexpected error occured while saving the notebook.');
1024 alert('An unexpected error occured while saving the notebook.');
1022 IPython.save_widget.reset_status();
1025 IPython.save_widget.reset_status();
1023 }
1026 };
1024
1027
1025
1028
1026 Notebook.prototype.load_notebook = function (callback) {
1029 Notebook.prototype.load_notebook = function (callback) {
1027 var that = this;
1030 var that = this;
1028 var notebook_id = IPython.save_widget.get_notebook_id();
1031 var notebook_id = IPython.save_widget.get_notebook_id();
1029 // We do the call with settings so we can set cache to false.
1032 // We do the call with settings so we can set cache to false.
1030 var settings = {
1033 var settings = {
1031 processData : false,
1034 processData : false,
1032 cache : false,
1035 cache : false,
1033 type : "GET",
1036 type : "GET",
1034 dataType : "json",
1037 dataType : "json",
1035 success : function (data, status, xhr) {
1038 success : function (data, status, xhr) {
1036 that.notebook_loaded(data, status, xhr);
1039 that.notebook_loaded(data, status, xhr);
1037 if (callback !== undefined) {
1040 if (callback !== undefined) {
1038 callback();
1041 callback();
1039 };
1042 };
1040 }
1043 }
1041 };
1044 };
1042 IPython.save_widget.status_loading();
1045 IPython.save_widget.status_loading();
1043 var url = $('body').data('baseProjectUrl') + 'notebooks/' + notebook_id
1046 var url = $('body').data('baseProjectUrl') + 'notebooks/' + notebook_id;
1044 $.ajax(url, settings);
1047 $.ajax(url, settings);
1045 }
1048 };
1046
1049
1047
1050
1048 Notebook.prototype.notebook_loaded = function (data, status, xhr) {
1051 Notebook.prototype.notebook_loaded = function (data, status, xhr) {
1049 var allowed = xhr.getResponseHeader('Allow');
1052 var allowed = xhr.getResponseHeader('Allow');
1050 this.fromJSON(data);
1053 this.fromJSON(data);
1051 if (this.ncells() === 0) {
1054 if (this.ncells() === 0) {
1052 this.insert_code_cell_below();
1055 this.insert_code_cell_below();
1053 };
1056 };
1054 IPython.save_widget.status_save();
1057 IPython.save_widget.status_save();
1055 IPython.save_widget.set_notebook_name(data.metadata.name);
1058 IPython.save_widget.set_notebook_name(data.metadata.name);
1056 this.dirty = false;
1059 this.dirty = false;
1057 if (! this.read_only) {
1060 if (! this.read_only) {
1058 this.start_kernel();
1061 this.start_kernel();
1059 }
1062 }
1060 // fromJSON always selects the last cell inserted. We need to wait
1063 // fromJSON always selects the last cell inserted. We need to wait
1061 // until that is done before scrolling to the top.
1064 // until that is done before scrolling to the top.
1062 setTimeout(function () {
1065 setTimeout(function () {
1063 IPython.notebook.select(0);
1066 IPython.notebook.select(0);
1064 IPython.notebook.scroll_to_top();
1067 IPython.notebook.scroll_to_top();
1065 }, 50);
1068 }, 50);
1066 };
1069 };
1067
1070
1068 IPython.Notebook = Notebook;
1071 IPython.Notebook = Notebook;
1069
1072
1070
1073
1071 return IPython;
1074 return IPython;
1072
1075
1073 }(IPython));
1076 }(IPython));
1074
1077
@@ -1,248 +1,248
1 //----------------------------------------------------------------------------
1 //----------------------------------------------------------------------------
2 // Copyright (C) 2008-2011 The IPython Development Team
2 // Copyright (C) 2008-2011 The IPython Development Team
3 //
3 //
4 // Distributed under the terms of the BSD License. The full license is in
4 // Distributed under the terms of the BSD License. The full license is in
5 // the file COPYING, distributed as part of this software.
5 // the file COPYING, distributed as part of this software.
6 //----------------------------------------------------------------------------
6 //----------------------------------------------------------------------------
7
7
8 //============================================================================
8 //============================================================================
9 // NotebookList
9 // NotebookList
10 //============================================================================
10 //============================================================================
11
11
12 var IPython = (function (IPython) {
12 var IPython = (function (IPython) {
13
13
14 var NotebookList = function (selector) {
14 var NotebookList = function (selector) {
15 this.selector = selector;
15 this.selector = selector;
16 if (this.selector !== undefined) {
16 if (this.selector !== undefined) {
17 this.element = $(selector);
17 this.element = $(selector);
18 this.style();
18 this.style();
19 this.bind_events();
19 this.bind_events();
20 }
20 }
21 };
21 };
22
22
23 NotebookList.prototype.style = function () {
23 NotebookList.prototype.style = function () {
24 this.element.addClass('ui-widget ui-widget-content');
24 this.element.addClass('ui-widget ui-widget-content');
25 $('div#project_name').addClass('ui-widget ui-widget-header');
25 $('div#project_name').addClass('ui-widget ui-widget-header');
26 };
26 };
27
27
28
28
29 NotebookList.prototype.bind_events = function () {
29 NotebookList.prototype.bind_events = function () {
30 var that = this;
30 var that = this;
31 this.element.bind('dragover', function () {
31 this.element.bind('dragover', function () {
32 return false;
32 return false;
33 });
33 });
34 this.element.bind('drop', function (event) {
34 this.element.bind('drop', function (event) {
35 var files = event.originalEvent.dataTransfer.files;
35 var files = event.originalEvent.dataTransfer.files;
36 for (var i = 0, f; f = files[i]; i++) {
36 for (var i = 0, f; f = files[i]; i++) {
37 var reader = new FileReader();
37 var reader = new FileReader();
38 reader.readAsText(f);
38 reader.readAsText(f);
39 var fname = f.name.split('.');
39 var fname = f.name.split('.');
40 var nbname = fname.slice(0,-1).join('.');
40 var nbname = fname.slice(0,-1).join('.');
41 var nbformat = fname.slice(-1)[0];
41 var nbformat = fname.slice(-1)[0];
42 if (nbformat === 'ipynb') {nbformat = 'json';};
42 if (nbformat === 'ipynb') {nbformat = 'json';};
43 if (nbformat === 'py' || nbformat === 'json') {
43 if (nbformat === 'py' || nbformat === 'json') {
44 var item = that.new_notebook_item(0);
44 var item = that.new_notebook_item(0);
45 that.add_name_input(nbname, item);
45 that.add_name_input(nbname, item);
46 item.data('nbformat', nbformat);
46 item.data('nbformat', nbformat);
47 // Store the notebook item in the reader so we can use it later
47 // Store the notebook item in the reader so we can use it later
48 // to know which item it belongs to.
48 // to know which item it belongs to.
49 $(reader).data('item', item);
49 $(reader).data('item', item);
50 reader.onload = function (event) {
50 reader.onload = function (event) {
51 var nbitem = $(event.target).data('item');
51 var nbitem = $(event.target).data('item');
52 that.add_notebook_data(event.target.result, nbitem);
52 that.add_notebook_data(event.target.result, nbitem);
53 that.add_upload_button(nbitem);
53 that.add_upload_button(nbitem);
54 };
54 };
55 };
55 };
56 }
56 }
57 return false;
57 return false;
58 });
58 });
59 };
59 };
60
60
61
61
62 NotebookList.prototype.load_list = function () {
62 NotebookList.prototype.load_list = function () {
63 var settings = {
63 var settings = {
64 processData : false,
64 processData : false,
65 cache : false,
65 cache : false,
66 type : "GET",
66 type : "GET",
67 dataType : "json",
67 dataType : "json",
68 success : $.proxy(this.list_loaded, this)
68 success : $.proxy(this.list_loaded, this)
69 };
69 };
70 var url = $('body').data('baseProjectUrl') + 'notebooks'
70 var url = $('body').data('baseProjectUrl') + 'notebooks';
71 $.ajax(url, settings);
71 $.ajax(url, settings);
72 };
72 };
73
73
74
74
75 NotebookList.prototype.list_loaded = function (data, status, xhr) {
75 NotebookList.prototype.list_loaded = function (data, status, xhr) {
76 var len = data.length;
76 var len = data.length;
77 // Todo: remove old children
77 // Todo: remove old children
78 for (var i=0; i<len; i++) {
78 for (var i=0; i<len; i++) {
79 var notebook_id = data[i].notebook_id;
79 var notebook_id = data[i].notebook_id;
80 var nbname = data[i].name;
80 var nbname = data[i].name;
81 var item = this.new_notebook_item(i);
81 var item = this.new_notebook_item(i);
82 this.add_link(notebook_id, nbname, item);
82 this.add_link(notebook_id, nbname, item);
83 if (!IPython.read_only){
83 if (!IPython.read_only){
84 // hide delete buttons when readonly
84 // hide delete buttons when readonly
85 this.add_delete_button(item);
85 this.add_delete_button(item);
86 }
86 }
87 };
87 };
88 };
88 };
89
89
90
90
91 NotebookList.prototype.new_notebook_item = function (index) {
91 NotebookList.prototype.new_notebook_item = function (index) {
92 var item = $('<div/>');
92 var item = $('<div/>');
93 item.addClass('notebook_item ui-widget ui-widget-content ui-helper-clearfix');
93 item.addClass('notebook_item ui-widget ui-widget-content ui-helper-clearfix');
94 var item_name = $('<span/>').addClass('item_name');
94 var item_name = $('<span/>').addClass('item_name');
95
95
96 item.append(item_name);
96 item.append(item_name);
97 if (index === -1) {
97 if (index === -1) {
98 this.element.append(item);
98 this.element.append(item);
99 } else {
99 } else {
100 this.element.children().eq(index).after(item);
100 this.element.children().eq(index).after(item);
101 }
101 }
102 return item;
102 return item;
103 };
103 };
104
104
105
105
106 NotebookList.prototype.add_link = function (notebook_id, nbname, item) {
106 NotebookList.prototype.add_link = function (notebook_id, nbname, item) {
107 item.data('nbname', nbname);
107 item.data('nbname', nbname);
108 item.data('notebook_id', notebook_id);
108 item.data('notebook_id', notebook_id);
109 var new_item_name = $('<span/>').addClass('item_name');
109 var new_item_name = $('<span/>').addClass('item_name');
110 new_item_name.append(
110 new_item_name.append(
111 $('<a/>').
111 $('<a/>').
112 attr('href', $('body').data('baseProjectURL')+notebook_id).
112 attr('href', $('body').data('baseProjectURL')+notebook_id).
113 attr('target','_blank').
113 attr('target','_blank').
114 text(nbname)
114 text(nbname)
115 );
115 );
116 var e = item.find('.item_name');
116 var e = item.find('.item_name');
117 if (e.length === 0) {
117 if (e.length === 0) {
118 item.append(new_item_name);
118 item.append(new_item_name);
119 } else {
119 } else {
120 e.replaceWith(new_item_name);
120 e.replaceWith(new_item_name);
121 };
121 };
122 };
122 };
123
123
124
124
125 NotebookList.prototype.add_name_input = function (nbname, item) {
125 NotebookList.prototype.add_name_input = function (nbname, item) {
126 item.data('nbname', nbname);
126 item.data('nbname', nbname);
127 var new_item_name = $('<span/>').addClass('item_name');
127 var new_item_name = $('<span/>').addClass('item_name');
128 new_item_name.append(
128 new_item_name.append(
129 $('<input/>').addClass('ui-widget ui-widget-content').
129 $('<input/>').addClass('ui-widget ui-widget-content').
130 attr('value', nbname).
130 attr('value', nbname).
131 attr('size', '30').
131 attr('size', '30').
132 attr('type', 'text')
132 attr('type', 'text')
133 );
133 );
134 var e = item.find('.item_name');
134 var e = item.find('.item_name');
135 if (e.length === 0) {
135 if (e.length === 0) {
136 item.append(new_item_name);
136 item.append(new_item_name);
137 } else {
137 } else {
138 e.replaceWith(new_item_name);
138 e.replaceWith(new_item_name);
139 };
139 };
140 };
140 };
141
141
142
142
143 NotebookList.prototype.add_notebook_data = function (data, item) {
143 NotebookList.prototype.add_notebook_data = function (data, item) {
144 item.data('nbdata',data);
144 item.data('nbdata',data);
145 };
145 };
146
146
147
147
148 NotebookList.prototype.add_delete_button = function (item) {
148 NotebookList.prototype.add_delete_button = function (item) {
149 var new_buttons = $('<span/>').addClass('item_buttons');
149 var new_buttons = $('<span/>').addClass('item_buttons');
150 var delete_button = $('<button>Delete</button>').button().
150 var delete_button = $('<button>Delete</button>').button().
151 click(function (e) {
151 click(function (e) {
152 // $(this) is the button that was clicked.
152 // $(this) is the button that was clicked.
153 var that = $(this);
153 var that = $(this);
154 // We use the nbname and notebook_id from the parent notebook_item element's
154 // We use the nbname and notebook_id from the parent notebook_item element's
155 // data because the outer scopes values change as we iterate through the loop.
155 // data because the outer scopes values change as we iterate through the loop.
156 var parent_item = that.parents('div.notebook_item');
156 var parent_item = that.parents('div.notebook_item');
157 var nbname = parent_item.data('nbname');
157 var nbname = parent_item.data('nbname');
158 var notebook_id = parent_item.data('notebook_id');
158 var notebook_id = parent_item.data('notebook_id');
159 var dialog = $('<div/>');
159 var dialog = $('<div/>');
160 dialog.html('Are you sure you want to permanently delete the notebook: ' + nbname + '?');
160 dialog.html('Are you sure you want to permanently delete the notebook: ' + nbname + '?');
161 parent_item.append(dialog);
161 parent_item.append(dialog);
162 dialog.dialog({
162 dialog.dialog({
163 resizable: false,
163 resizable: false,
164 modal: true,
164 modal: true,
165 title: "Delete notebook",
165 title: "Delete notebook",
166 buttons : {
166 buttons : {
167 "Delete": function () {
167 "Delete": function () {
168 var settings = {
168 var settings = {
169 processData : false,
169 processData : false,
170 cache : false,
170 cache : false,
171 type : "DELETE",
171 type : "DELETE",
172 dataType : "json",
172 dataType : "json",
173 success : function (data, status, xhr) {
173 success : function (data, status, xhr) {
174 parent_item.remove();
174 parent_item.remove();
175 }
175 }
176 };
176 };
177 var url = $('body').data('baseProjectUrl') + 'notebooks/' + notebook_id
177 var url = $('body').data('baseProjectUrl') + 'notebooks/' + notebook_id;
178 $.ajax(url, settings);
178 $.ajax(url, settings);
179 $(this).dialog('close');
179 $(this).dialog('close');
180 },
180 },
181 "Cancel": function () {
181 "Cancel": function () {
182 $(this).dialog('close');
182 $(this).dialog('close');
183 }
183 }
184 }
184 }
185 });
185 });
186 });
186 });
187 new_buttons.append(delete_button);
187 new_buttons.append(delete_button);
188 var e = item.find('.item_buttons');
188 var e = item.find('.item_buttons');
189 if (e.length === 0) {
189 if (e.length === 0) {
190 item.append(new_buttons);
190 item.append(new_buttons);
191 } else {
191 } else {
192 e.replaceWith(new_buttons);
192 e.replaceWith(new_buttons);
193 };
193 };
194 };
194 };
195
195
196
196
197 NotebookList.prototype.add_upload_button = function (item) {
197 NotebookList.prototype.add_upload_button = function (item) {
198 var that = this;
198 var that = this;
199 var new_buttons = $('<span/>').addClass('item_buttons');
199 var new_buttons = $('<span/>').addClass('item_buttons');
200 var upload_button = $('<button>Upload</button>').button().
200 var upload_button = $('<button>Upload</button>').button().
201 click(function (e) {
201 click(function (e) {
202 var nbname = item.find('.item_name > input').attr('value');
202 var nbname = item.find('.item_name > input').attr('value');
203 var nbformat = item.data('nbformat');
203 var nbformat = item.data('nbformat');
204 var nbdata = item.data('nbdata');
204 var nbdata = item.data('nbdata');
205 var content_type = 'text/plain';
205 var content_type = 'text/plain';
206 if (nbformat === 'json') {
206 if (nbformat === 'json') {
207 content_type = 'application/json';
207 content_type = 'application/json';
208 } else if (nbformat === 'py') {
208 } else if (nbformat === 'py') {
209 content_type = 'application/x-python';
209 content_type = 'application/x-python';
210 };
210 };
211 var settings = {
211 var settings = {
212 processData : false,
212 processData : false,
213 cache : false,
213 cache : false,
214 type : 'POST',
214 type : 'POST',
215 dataType : 'json',
215 dataType : 'json',
216 data : nbdata,
216 data : nbdata,
217 headers : {'Content-Type': content_type},
217 headers : {'Content-Type': content_type},
218 success : function (data, status, xhr) {
218 success : function (data, status, xhr) {
219 that.add_link(data, nbname, item);
219 that.add_link(data, nbname, item);
220 that.add_delete_button(item);
220 that.add_delete_button(item);
221 }
221 }
222 };
222 };
223
223
224 var qs = $.param({name:nbname, format:nbformat});
224 var qs = $.param({name:nbname, format:nbformat});
225 var url = $('body').data('baseProjectUrl') + 'notebooks?' + qs
225 var url = $('body').data('baseProjectUrl') + 'notebooks?' + qs;
226 $.ajax(url, settings);
226 $.ajax(url, settings);
227 });
227 });
228 var cancel_button = $('<button>Cancel</button>').button().
228 var cancel_button = $('<button>Cancel</button>').button().
229 click(function (e) {
229 click(function (e) {
230 item.remove();
230 item.remove();
231 });
231 });
232 upload_button.addClass('upload_button');
232 upload_button.addClass('upload_button');
233 new_buttons.append(upload_button).append(cancel_button);
233 new_buttons.append(upload_button).append(cancel_button);
234 var e = item.find('.item_buttons');
234 var e = item.find('.item_buttons');
235 if (e.length === 0) {
235 if (e.length === 0) {
236 item.append(new_buttons);
236 item.append(new_buttons);
237 } else {
237 } else {
238 e.replaceWith(new_buttons);
238 e.replaceWith(new_buttons);
239 };
239 };
240 };
240 };
241
241
242
242
243 IPython.NotebookList = NotebookList;
243 IPython.NotebookList = NotebookList;
244
244
245 return IPython;
245 return IPython;
246
246
247 }(IPython));
247 }(IPython));
248
248
@@ -1,85 +1,85
1 //----------------------------------------------------------------------------
1 //----------------------------------------------------------------------------
2 // Copyright (C) 2008-2011 The IPython Development Team
2 // Copyright (C) 2008-2011 The IPython Development Team
3 //
3 //
4 // Distributed under the terms of the BSD License. The full license is in
4 // Distributed under the terms of the BSD License. The full license is in
5 // the file COPYING, distributed as part of this software.
5 // the file COPYING, distributed as part of this software.
6 //----------------------------------------------------------------------------
6 //----------------------------------------------------------------------------
7
7
8 //============================================================================
8 //============================================================================
9 // On document ready
9 // On document ready
10 //============================================================================
10 //============================================================================
11
11
12
12
13 $(document).ready(function () {
13 $(document).ready(function () {
14
14
15 MathJax.Hub.Config({
15 MathJax.Hub.Config({
16 tex2jax: {
16 tex2jax: {
17 inlineMath: [ ['$','$'], ["\\(","\\)"] ],
17 inlineMath: [ ['$','$'], ["\\(","\\)"] ],
18 displayMath: [ ['$$','$$'], ["\\[","\\]"] ],
18 displayMath: [ ['$$','$$'], ["\\[","\\]"] ]
19 },
19 },
20 displayAlign: 'left', // Change this to 'center' to center equations.
20 displayAlign: 'left', // Change this to 'center' to center equations.
21 "HTML-CSS": {
21 "HTML-CSS": {
22 styles: {'.MathJax_Display': {"margin": 0}}
22 styles: {'.MathJax_Display': {"margin": 0}}
23 }
23 }
24 });
24 });
25 IPython.markdown_converter = new Markdown.Converter();
25 IPython.markdown_converter = new Markdown.Converter();
26 IPython.read_only = $('meta[name=read_only]').attr("content") == 'True';
26 IPython.read_only = $('meta[name=read_only]').attr("content") == 'True';
27
27
28 $('div#header').addClass('border-box-sizing');
28 $('div#header').addClass('border-box-sizing');
29 $('div#main_app').addClass('border-box-sizing ui-widget ui-widget-content');
29 $('div#main_app').addClass('border-box-sizing ui-widget ui-widget-content');
30 $('div#notebook_panel').addClass('border-box-sizing ui-widget');
30 $('div#notebook_panel').addClass('border-box-sizing ui-widget');
31
31
32 IPython.layout_manager = new IPython.LayoutManager();
32 IPython.layout_manager = new IPython.LayoutManager();
33 IPython.pager = new IPython.Pager('div#pager', 'div#pager_splitter');
33 IPython.pager = new IPython.Pager('div#pager', 'div#pager_splitter');
34 IPython.left_panel = new IPython.LeftPanel('div#left_panel', 'div#left_panel_splitter');
34 IPython.left_panel = new IPython.LeftPanel('div#left_panel', 'div#left_panel_splitter');
35 IPython.save_widget = new IPython.SaveWidget('span#save_widget');
35 IPython.save_widget = new IPython.SaveWidget('span#save_widget');
36 IPython.quick_help = new IPython.QuickHelp('span#quick_help_area');
36 IPython.quick_help = new IPython.QuickHelp('span#quick_help_area');
37 IPython.login_widget = new IPython.LoginWidget('span#login_widget');
37 IPython.login_widget = new IPython.LoginWidget('span#login_widget');
38 IPython.print_widget = new IPython.PrintWidget('span#print_widget');
38 IPython.print_widget = new IPython.PrintWidget('span#print_widget');
39 IPython.notebook = new IPython.Notebook('div#notebook');
39 IPython.notebook = new IPython.Notebook('div#notebook');
40 IPython.kernel_status_widget = new IPython.KernelStatusWidget('#kernel_status');
40 IPython.kernel_status_widget = new IPython.KernelStatusWidget('#kernel_status');
41 IPython.kernel_status_widget.status_idle();
41 IPython.kernel_status_widget.status_idle();
42
42
43 IPython.layout_manager.do_resize();
43 IPython.layout_manager.do_resize();
44
44
45 // These have display: none in the css file and are made visible here to prevent FLOUC.
45 // These have display: none in the css file and are made visible here to prevent FLOUC.
46 $('div#header').css('display','block');
46 $('div#header').css('display','block');
47
47
48 if(IPython.read_only){
48 if(IPython.read_only){
49 // hide various elements from read-only view
49 // hide various elements from read-only view
50 IPython.save_widget.element.find('button#save_notebook').addClass('hidden');
50 IPython.save_widget.element.find('button#save_notebook').addClass('hidden');
51 IPython.quick_help.element.addClass('hidden'); // shortcuts are disabled in read_only
51 IPython.quick_help.element.addClass('hidden'); // shortcuts are disabled in read_only
52 $('button#new_notebook').addClass('hidden');
52 $('button#new_notebook').addClass('hidden');
53 $('div#cell_section').addClass('hidden');
53 $('div#cell_section').addClass('hidden');
54 $('div#config_section').addClass('hidden');
54 $('div#config_section').addClass('hidden');
55 $('div#kernel_section').addClass('hidden');
55 $('div#kernel_section').addClass('hidden');
56 $('span#login_widget').removeClass('hidden');
56 $('span#login_widget').removeClass('hidden');
57 // left panel starts collapsed, but the collapse must happen after
57 // left panel starts collapsed, but the collapse must happen after
58 // elements start drawing. Don't draw contents of the panel until
58 // elements start drawing. Don't draw contents of the panel until
59 // after they are collapsed
59 // after they are collapsed
60 IPython.left_panel.left_panel_element.css('visibility', 'hidden');
60 IPython.left_panel.left_panel_element.css('visibility', 'hidden');
61 }
61 }
62
62
63 $('div#main_app').css('display','block');
63 $('div#main_app').css('display','block');
64
64
65 // Perform these actions after the notebook has been loaded.
65 // Perform these actions after the notebook has been loaded.
66 // We wait 100 milliseconds because the notebook scrolls to the top after a load
66 // We wait 100 milliseconds because the notebook scrolls to the top after a load
67 // is completed and we need to wait for that to mostly finish.
67 // is completed and we need to wait for that to mostly finish.
68 IPython.notebook.load_notebook(function () {
68 IPython.notebook.load_notebook(function () {
69 setTimeout(function () {
69 setTimeout(function () {
70 IPython.save_widget.update_url();
70 IPython.save_widget.update_url();
71 IPython.layout_manager.do_resize();
71 IPython.layout_manager.do_resize();
72 IPython.pager.collapse();
72 IPython.pager.collapse();
73 if(IPython.read_only){
73 if(IPython.read_only){
74 // collapse the left panel on read-only
74 // collapse the left panel on read-only
75 IPython.left_panel.collapse();
75 IPython.left_panel.collapse();
76 // and finally unhide the panel contents after collapse
76 // and finally unhide the panel contents after collapse
77 setTimeout(function(){
77 setTimeout(function(){
78 IPython.left_panel.left_panel_element.css('visibility', 'visible');
78 IPython.left_panel.left_panel_element.css('visibility', 'visible');
79 }, 200)
79 }, 200);
80 }
80 }
81 },100);
81 },100);
82 });
82 });
83
83
84 });
84 });
85
85
@@ -1,333 +1,333
1 //----------------------------------------------------------------------------
1 //----------------------------------------------------------------------------
2 // Copyright (C) 2008-2011 The IPython Development Team
2 // Copyright (C) 2008-2011 The IPython Development Team
3 //
3 //
4 // Distributed under the terms of the BSD License. The full license is in
4 // Distributed under the terms of the BSD License. The full license is in
5 // the file COPYING, distributed as part of this software.
5 // the file COPYING, distributed as part of this software.
6 //----------------------------------------------------------------------------
6 //----------------------------------------------------------------------------
7
7
8 //============================================================================
8 //============================================================================
9 // PanelSection
9 // PanelSection
10 //============================================================================
10 //============================================================================
11
11
12 var IPython = (function (IPython) {
12 var IPython = (function (IPython) {
13
13
14 var utils = IPython.utils;
14 var utils = IPython.utils;
15
15
16 // Base PanelSection class
16 // Base PanelSection class
17
17
18 var PanelSection = function (selector) {
18 var PanelSection = function (selector) {
19 this.selector = selector;
19 this.selector = selector;
20 if (this.selector !== undefined) {
20 if (this.selector !== undefined) {
21 this.element = $(selector);
21 this.element = $(selector);
22 this.header = this.element.find('div.section_header');
22 this.header = this.element.find('div.section_header');
23 this.content = this.element.find('div.section_content');
23 this.content = this.element.find('div.section_content');
24 this.style();
24 this.style();
25 this.bind_events();
25 this.bind_events();
26 }
26 }
27 this.expanded = true;
27 this.expanded = true;
28 };
28 };
29
29
30
30
31 PanelSection.prototype.style = function () {
31 PanelSection.prototype.style = function () {
32 this.header.addClass('ui-widget ui-state-default ui-helper-clearfix');
32 this.header.addClass('ui-widget ui-state-default ui-helper-clearfix');
33 this.header.attr('title', "Click to Show/Hide Section");
33 this.header.attr('title', "Click to Show/Hide Section");
34 this.content.addClass('ui-widget section_content');
34 this.content.addClass('ui-widget section_content');
35 };
35 };
36
36
37
37
38 PanelSection.prototype.bind_events = function () {
38 PanelSection.prototype.bind_events = function () {
39 var that = this;
39 var that = this;
40 this.header.click(function () {
40 this.header.click(function () {
41 that.toggle();
41 that.toggle();
42 });
42 });
43 this.header.hover(function () {
43 this.header.hover(function () {
44 that.header.toggleClass('ui-state-hover');
44 that.header.toggleClass('ui-state-hover');
45 });
45 });
46 };
46 };
47
47
48
48
49 PanelSection.prototype.expand = function () {
49 PanelSection.prototype.expand = function () {
50 if (!this.expanded) {
50 if (!this.expanded) {
51 this.content.slideDown('fast');
51 this.content.slideDown('fast');
52 this.expanded = true;
52 this.expanded = true;
53 };
53 };
54 };
54 };
55
55
56
56
57 PanelSection.prototype.collapse = function () {
57 PanelSection.prototype.collapse = function () {
58 if (this.expanded) {
58 if (this.expanded) {
59 this.content.slideUp('fast');
59 this.content.slideUp('fast');
60 this.expanded = false;
60 this.expanded = false;
61 };
61 };
62 };
62 };
63
63
64
64
65 PanelSection.prototype.toggle = function () {
65 PanelSection.prototype.toggle = function () {
66 if (this.expanded === true) {
66 if (this.expanded === true) {
67 this.collapse();
67 this.collapse();
68 } else {
68 } else {
69 this.expand();
69 this.expand();
70 };
70 };
71 };
71 };
72
72
73
73
74 PanelSection.prototype.create_children = function () {};
74 PanelSection.prototype.create_children = function () {};
75
75
76
76
77 // NotebookSection
77 // NotebookSection
78
78
79 var NotebookSection = function () {
79 var NotebookSection = function () {
80 PanelSection.apply(this, arguments);
80 PanelSection.apply(this, arguments);
81 };
81 };
82
82
83
83
84 NotebookSection.prototype = new PanelSection();
84 NotebookSection.prototype = new PanelSection();
85
85
86
86
87 NotebookSection.prototype.style = function () {
87 NotebookSection.prototype.style = function () {
88 PanelSection.prototype.style.apply(this);
88 PanelSection.prototype.style.apply(this);
89 this.content.addClass('ui-helper-clearfix');
89 this.content.addClass('ui-helper-clearfix');
90 this.content.find('div.section_row').addClass('ui-helper-clearfix');
90 this.content.find('div.section_row').addClass('ui-helper-clearfix');
91 this.content.find('#new_open').buttonset();
91 this.content.find('#new_open').buttonset();
92 this.content.find('#new_notebook').attr('title', "Create a new notebook");
92 this.content.find('#new_notebook').attr('title', "Create a new notebook");
93 this.content.find('#open_notebook').attr('title', "Open an existing notebook");
93 this.content.find('#open_notebook').attr('title', "Open an existing notebook");
94 this.content.find('#download_notebook').button();
94 this.content.find('#download_notebook').button();
95 this.content.find('#download_notebook').attr('title',
95 this.content.find('#download_notebook').attr('title',
96 "Download the notebook in the specified format," +
96 "Download the notebook in the specified format," +
97 " either full ipynb notebook or as a Python script." +
97 " either full ipynb notebook or as a Python script." +
98 " Make sure to save before downloading, to ensure the file is up to date."
98 " Make sure to save before downloading, to ensure the file is up to date."
99 );
99 );
100 // upload notebook doesn't exist:
100 // upload notebook doesn't exist:
101 this.content.find('#upload_notebook').button();
101 this.content.find('#upload_notebook').button();
102 this.content.find('#download_format').addClass('ui-widget ui-widget-content');
102 this.content.find('#download_format').addClass('ui-widget ui-widget-content');
103 this.content.find('#download_format option').addClass('ui-widget ui-widget-content');
103 this.content.find('#download_format option').addClass('ui-widget ui-widget-content');
104 };
104 };
105
105
106
106
107 NotebookSection.prototype.bind_events = function () {
107 NotebookSection.prototype.bind_events = function () {
108 PanelSection.prototype.bind_events.apply(this);
108 PanelSection.prototype.bind_events.apply(this);
109 var that = this;
109 var that = this;
110 this.content.find('#new_notebook').click(function () {
110 this.content.find('#new_notebook').click(function () {
111 window.open($('body').data('baseProjectUrl')+'new');
111 window.open($('body').data('baseProjectUrl')+'new');
112 });
112 });
113 this.content.find('#open_notebook').click(function () {
113 this.content.find('#open_notebook').click(function () {
114 window.open($('body').data('baseProjectUrl'));
114 window.open($('body').data('baseProjectUrl'));
115 });
115 });
116 this.content.find('#download_notebook').click(function () {
116 this.content.find('#download_notebook').click(function () {
117 var format = that.content.find('#download_format').val();
117 var format = that.content.find('#download_format').val();
118 var notebook_id = IPython.save_widget.get_notebook_id();
118 var notebook_id = IPython.save_widget.get_notebook_id();
119 var url = $('body').data('baseProjectUrl') + 'notebooks/' + notebook_id + '?format=' + format;
119 var url = $('body').data('baseProjectUrl') + 'notebooks/' + notebook_id + '?format=' + format;
120 window.open(url,'_newtab');
120 window.open(url,'_newtab');
121 });
121 });
122 };
122 };
123
123
124 // ConfigSection
124 // ConfigSection
125
125
126 var ConfigSection = function () {
126 var ConfigSection = function () {
127 PanelSection.apply(this, arguments);
127 PanelSection.apply(this, arguments);
128 };
128 };
129
129
130 ConfigSection.prototype = new PanelSection();
130 ConfigSection.prototype = new PanelSection();
131
131
132 ConfigSection.prototype.style = function () {
132 ConfigSection.prototype.style = function () {
133 PanelSection.prototype.style.apply(this);
133 PanelSection.prototype.style.apply(this);
134 this.content.addClass('ui-helper-clearfix');
134 this.content.addClass('ui-helper-clearfix');
135 this.content.find('div.section_row').addClass('ui-helper-clearfix');
135 this.content.find('div.section_row').addClass('ui-helper-clearfix');
136
136
137 this.content.find('#tooltipontab').attr('title', 'Show tooltip if you press <Tab> after "(" or a white space');
137 this.content.find('#tooltipontab').attr('title', 'Show tooltip if you press <Tab> after "(" or a white space');
138 this.content.find('#tooltipontab_label').attr('title', 'Show Tooltip when pressing Tab');
138 this.content.find('#tooltipontab_label').attr('title', 'Show Tooltip when pressing Tab');
139
139
140 this.content.find('#timebeforetooltip').attr('title', 'Time before a tooltip auto-appear when "(" is pressed (negative value supress tooltip)');
140 this.content.find('#timebeforetooltip').attr('title', 'Time before a tooltip auto-appear when "(" is pressed (negative value supress tooltip)');
141 this.content.find('#timebeforetooltip_label').attr('title', 'Time before a tooltip auto-appear when "(" is pressed (negative value supress tooltip)');
141 this.content.find('#timebeforetooltip_label').attr('title', 'Time before a tooltip auto-appear when "(" is pressed (negative value supress tooltip)');
142
142
143 this.content.find('#smartcompleter').attr('title', 'When inside function call, completer try to propose kwargs first');
143 this.content.find('#smartcompleter').attr('title', 'When inside function call, completer try to propose kwargs first');
144 this.content.find('#smartcompleter_label').attr('title', 'When inside function call, completer try to propose kwargs first');
144 this.content.find('#smartcompleter_label').attr('title', 'When inside function call, completer try to propose kwargs first');
145 };
145 };
146
146
147
147
148 ConfigSection.prototype.bind_events = function () {
148 ConfigSection.prototype.bind_events = function () {
149 PanelSection.prototype.bind_events.apply(this);
149 PanelSection.prototype.bind_events.apply(this);
150 this.content.find('#tooltipontab').change(function () {
150 this.content.find('#tooltipontab').change(function () {
151 var state = $('#tooltipontab').prop('checked');
151 var state = $('#tooltipontab').prop('checked');
152 IPython.notebook.set_tooltipontab(state);
152 IPython.notebook.set_tooltipontab(state);
153 });
153 });
154 this.content.find('#timebeforetooltip').change(function () {
154 this.content.find('#timebeforetooltip').change(function () {
155 var state = $('#timebeforetooltip').prop('value');
155 var state = $('#timebeforetooltip').prop('value');
156 IPython.notebook.set_timebeforetooltip(state);
156 IPython.notebook.set_timebeforetooltip(state);
157 });
157 });
158 this.content.find('#smartcompleter').change(function () {
158 this.content.find('#smartcompleter').change(function () {
159 var state = $('#smartcompleter').prop('checked');
159 var state = $('#smartcompleter').prop('checked');
160 IPython.notebook.set_smartcompleter(state);
160 IPython.notebook.set_smartcompleter(state);
161 });
161 });
162 };
162 };
163
163
164 // CellSection
164 // CellSection
165
165
166 var CellSection = function () {
166 var CellSection = function () {
167 PanelSection.apply(this, arguments);
167 PanelSection.apply(this, arguments);
168 };
168 };
169
169
170 CellSection.prototype = new PanelSection();
170 CellSection.prototype = new PanelSection();
171
171
172
172
173 CellSection.prototype.style = function () {
173 CellSection.prototype.style = function () {
174 PanelSection.prototype.style.apply(this);
174 PanelSection.prototype.style.apply(this);
175 this.content.addClass('ui-helper-clearfix');
175 this.content.addClass('ui-helper-clearfix');
176 this.content.find('div.section_row').addClass('ui-helper-clearfix');
176 this.content.find('div.section_row').addClass('ui-helper-clearfix');
177 this.content.find('#delete_cell').button();
177 this.content.find('#delete_cell').button();
178 this.content.find('#delete_cell').attr('title', "Delete the selected cell");
178 this.content.find('#delete_cell').attr('title', "Delete the selected cell");
179
179
180 this.content.find('#insert').buttonset();
180 this.content.find('#insert').buttonset();
181 this.content.find('#insert_cell_above').attr('title', "Insert new cell above selected");
181 this.content.find('#insert_cell_above').attr('title', "Insert new cell above selected");
182 this.content.find('#insert_cell_below').attr('title', "Insert new cell below selected");
182 this.content.find('#insert_cell_below').attr('title', "Insert new cell below selected");
183
183
184 this.content.find('#move').buttonset();
184 this.content.find('#move').buttonset();
185 this.content.find('#move_cell_up').attr('title', "Move selected cell up one in the Notebook");
185 this.content.find('#move_cell_up').attr('title', "Move selected cell up one in the Notebook");
186 this.content.find('#move_cell_down').attr('title', "Move selected cell down one in the Notebook");
186 this.content.find('#move_cell_down').attr('title', "Move selected cell down one in the Notebook");
187
187
188 this.content.find('#cell_type').buttonset();
188 this.content.find('#cell_type').buttonset();
189 this.content.find('#to_markdown').attr('title', 'Change selected cell to markdown (for text)')
189 this.content.find('#to_markdown').attr('title', 'Change selected cell to markdown (for text)');
190 this.content.find('#to_code').attr('title', 'Change selected cell to code (for execution)')
190 this.content.find('#to_code').attr('title', 'Change selected cell to code (for execution)');
191
191
192 this.content.find('#cell_output').buttonset();
192 this.content.find('#cell_output').buttonset();
193 this.content.find('#toggle_output').attr('title', 'Toggle visibility of the output of code cells')
193 this.content.find('#toggle_output').attr('title', 'Toggle visibility of the output of code cells');
194 this.content.find('#clear_all_output').attr('title', 'Clear output of all code cells (actually removes the data, unlike toggle)')
194 this.content.find('#clear_all_output').attr('title', 'Clear output of all code cells (actually removes the data, unlike toggle)');
195
195
196 this.content.find('#run_cells').buttonset();
196 this.content.find('#run_cells').buttonset();
197 this.content.find('#run_selected_cell').attr('title', 'Submit the selected cell for execution')
197 this.content.find('#run_selected_cell').attr('title', 'Submit the selected cell for execution');
198 this.content.find('#run_all_cells').attr('title', 'Run *all* code cells in the notebook in order')
198 this.content.find('#run_all_cells').attr('title', 'Run *all* code cells in the notebook in order');
199 this.content.find('#autoindent').attr('title', 'Autoindent code as-you-type')
199 this.content.find('#autoindent').attr('title', 'Autoindent code as-you-type');
200 this.content.find('#autoindent_label').attr('title', 'Autoindent code as-you-type')
200 this.content.find('#autoindent_label').attr('title', 'Autoindent code as-you-type');
201 };
201 };
202
202
203
203
204 CellSection.prototype.bind_events = function () {
204 CellSection.prototype.bind_events = function () {
205 PanelSection.prototype.bind_events.apply(this);
205 PanelSection.prototype.bind_events.apply(this);
206 this.content.find('#toggle_output').click(function () {
206 this.content.find('#toggle_output').click(function () {
207 IPython.notebook.toggle_output();
207 IPython.notebook.toggle_output();
208 });
208 });
209 this.content.find('#clear_all_output').click(function () {
209 this.content.find('#clear_all_output').click(function () {
210 IPython.notebook.clear_all_output();
210 IPython.notebook.clear_all_output();
211 });
211 });
212 this.content.find('#delete_cell').click(function () {
212 this.content.find('#delete_cell').click(function () {
213 IPython.notebook.delete_cell();
213 IPython.notebook.delete_cell();
214 });
214 });
215 this.content.find('#insert_cell_above').click(function () {
215 this.content.find('#insert_cell_above').click(function () {
216 IPython.notebook.insert_code_cell_above();
216 IPython.notebook.insert_code_cell_above();
217 });
217 });
218 this.content.find('#insert_cell_below').click(function () {
218 this.content.find('#insert_cell_below').click(function () {
219 IPython.notebook.insert_code_cell_below();
219 IPython.notebook.insert_code_cell_below();
220 });
220 });
221 this.content.find('#move_cell_up').click(function () {
221 this.content.find('#move_cell_up').click(function () {
222 IPython.notebook.move_cell_up();
222 IPython.notebook.move_cell_up();
223 });
223 });
224 this.content.find('#move_cell_down').click(function () {
224 this.content.find('#move_cell_down').click(function () {
225 IPython.notebook.move_cell_down();
225 IPython.notebook.move_cell_down();
226 });
226 });
227 this.content.find('#to_code').click(function () {
227 this.content.find('#to_code').click(function () {
228 IPython.notebook.to_code();
228 IPython.notebook.to_code();
229 });
229 });
230 this.content.find('#to_markdown').click(function () {
230 this.content.find('#to_markdown').click(function () {
231 IPython.notebook.to_markdown();
231 IPython.notebook.to_markdown();
232 });
232 });
233 this.content.find('#run_selected_cell').click(function () {
233 this.content.find('#run_selected_cell').click(function () {
234 IPython.notebook.execute_selected_cell();
234 IPython.notebook.execute_selected_cell();
235 });
235 });
236 this.content.find('#run_all_cells').click(function () {
236 this.content.find('#run_all_cells').click(function () {
237 IPython.notebook.execute_all_cells();
237 IPython.notebook.execute_all_cells();
238 });
238 });
239 this.content.find('#autoindent').change(function () {
239 this.content.find('#autoindent').change(function () {
240 var state = $('#autoindent').prop('checked');
240 var state = $('#autoindent').prop('checked');
241 IPython.notebook.set_autoindent(state);
241 IPython.notebook.set_autoindent(state);
242 });
242 });
243 this.content.find('#tooltipontab').change(function () {
243 this.content.find('#tooltipontab').change(function () {
244 var state = $('#tooltipontab').prop('checked');
244 var state = $('#tooltipontab').prop('checked');
245 IPython.notebook.set_tooltipontab(state);
245 IPython.notebook.set_tooltipontab(state);
246 });
246 });
247 };
247 };
248
248
249
249
250 // KernelSection
250 // KernelSection
251
251
252 var KernelSection = function () {
252 var KernelSection = function () {
253 PanelSection.apply(this, arguments);
253 PanelSection.apply(this, arguments);
254 };
254 };
255
255
256
256
257 KernelSection.prototype = new PanelSection();
257 KernelSection.prototype = new PanelSection();
258
258
259
259
260 KernelSection.prototype.style = function () {
260 KernelSection.prototype.style = function () {
261 PanelSection.prototype.style.apply(this);
261 PanelSection.prototype.style.apply(this);
262 this.content.addClass('ui-helper-clearfix');
262 this.content.addClass('ui-helper-clearfix');
263 this.content.find('div.section_row').addClass('ui-helper-clearfix');
263 this.content.find('div.section_row').addClass('ui-helper-clearfix');
264 this.content.find('#int_restart').buttonset();
264 this.content.find('#int_restart').buttonset();
265 this.content.find("#int_kernel").attr('title', "Interrupt the kernel with SIGINT/Ctrl-C");
265 this.content.find("#int_kernel").attr('title', "Interrupt the kernel with SIGINT/Ctrl-C");
266 this.content.find("#restart_kernel").attr('title',
266 this.content.find("#restart_kernel").attr('title',
267 "Restart the kernel. This will shutdown the current kernel," +
267 "Restart the kernel. This will shutdown the current kernel," +
268 " and start a new, clean kernel in its place, connected to this Notebook." +
268 " and start a new, clean kernel in its place, connected to this Notebook." +
269 " This may break the connection of other clients connected to this kernel." );
269 " This may break the connection of other clients connected to this kernel." );
270 var kill_tip = "Kill the kernel on exit. If unchecked, the kernel will remain" +
270 var kill_tip = "Kill the kernel on exit. If unchecked, the kernel will remain" +
271 " active after closing the session, allowing you to reconnect and resume later.";
271 " active after closing the session, allowing you to reconnect and resume later.";
272 this.content.find('#kill_kernel').attr('title', kill_tip);
272 this.content.find('#kill_kernel').attr('title', kill_tip);
273 this.content.find('#kill_kernel_label').attr('title', kill_tip);
273 this.content.find('#kill_kernel_label').attr('title', kill_tip);
274
274
275 };
275 };
276
276
277
277
278 KernelSection.prototype.bind_events = function () {
278 KernelSection.prototype.bind_events = function () {
279 PanelSection.prototype.bind_events.apply(this);
279 PanelSection.prototype.bind_events.apply(this);
280 this.content.find('#restart_kernel').click(function () {
280 this.content.find('#restart_kernel').click(function () {
281 IPython.notebook.restart_kernel();
281 IPython.notebook.restart_kernel();
282 });
282 });
283 this.content.find('#int_kernel').click(function () {
283 this.content.find('#int_kernel').click(function () {
284 IPython.notebook.kernel.interrupt();
284 IPython.notebook.kernel.interrupt();
285 });
285 });
286 };
286 };
287
287
288
288
289 // HelpSection
289 // HelpSection
290
290
291 var HelpSection = function () {
291 var HelpSection = function () {
292 PanelSection.apply(this, arguments);
292 PanelSection.apply(this, arguments);
293 };
293 };
294
294
295
295
296 HelpSection.prototype = new PanelSection();
296 HelpSection.prototype = new PanelSection();
297
297
298
298
299 HelpSection.prototype.style = function () {
299 HelpSection.prototype.style = function () {
300 PanelSection.prototype.style.apply(this);
300 PanelSection.prototype.style.apply(this);
301 PanelSection.prototype.style.apply(this);
301 PanelSection.prototype.style.apply(this);
302 this.content.addClass('ui-helper-clearfix');
302 this.content.addClass('ui-helper-clearfix');
303 this.content.find('div.section_row').addClass('ui-helper-clearfix');
303 this.content.find('div.section_row').addClass('ui-helper-clearfix');
304 this.content.find('#help_buttons0').buttonset();
304 this.content.find('#help_buttons0').buttonset();
305 this.content.find('#help_buttons1').buttonset();
305 this.content.find('#help_buttons1').buttonset();
306 this.content.find('#help_buttons2').buttonset();
306 this.content.find('#help_buttons2').buttonset();
307 this.content.find('#python_help').attr('title', "Open the online Python documentation in a new tab")
307 this.content.find('#python_help').attr('title', "Open the online Python documentation in a new tab");
308 this.content.find('#ipython_help').attr('title', "Open the online IPython documentation in a new tab")
308 this.content.find('#ipython_help').attr('title', "Open the online IPython documentation in a new tab");
309 this.content.find('#numpy_help').attr('title', "Open the online NumPy documentation in a new tab")
309 this.content.find('#numpy_help').attr('title', "Open the online NumPy documentation in a new tab");
310 this.content.find('#scipy_help').attr('title', "Open the online SciPy documentation in a new tab")
310 this.content.find('#scipy_help').attr('title', "Open the online SciPy documentation in a new tab");
311 this.content.find('#matplotlib_help').attr('title', "Open the online Matplotlib documentation in a new tab")
311 this.content.find('#matplotlib_help').attr('title', "Open the online Matplotlib documentation in a new tab");
312 this.content.find('#sympy_help').attr('title', "Open the online SymPy documentation in a new tab")
312 this.content.find('#sympy_help').attr('title', "Open the online SymPy documentation in a new tab");
313 };
313 };
314
314
315
315
316 HelpSection.prototype.bind_events = function () {
316 HelpSection.prototype.bind_events = function () {
317 PanelSection.prototype.bind_events.apply(this);
317 PanelSection.prototype.bind_events.apply(this);
318 };
318 };
319
319
320
320
321 // Set module variables
321 // Set module variables
322
322
323 IPython.PanelSection = PanelSection;
323 IPython.PanelSection = PanelSection;
324 IPython.NotebookSection = NotebookSection;
324 IPython.NotebookSection = NotebookSection;
325 IPython.CellSection = CellSection;
325 IPython.CellSection = CellSection;
326 IPython.ConfigSection = ConfigSection;
326 IPython.ConfigSection = ConfigSection;
327 IPython.KernelSection = KernelSection;
327 IPython.KernelSection = KernelSection;
328 IPython.HelpSection = HelpSection;
328 IPython.HelpSection = HelpSection;
329
329
330 return IPython;
330 return IPython;
331
331
332 }(IPython));
332 }(IPython));
333
333
@@ -1,157 +1,157
1 //----------------------------------------------------------------------------
1 //----------------------------------------------------------------------------
2 // Copyright (C) 2008-2011 The IPython Development Team
2 // Copyright (C) 2008-2011 The IPython Development Team
3 //
3 //
4 // Distributed under the terms of the BSD License. The full license is in
4 // Distributed under the terms of the BSD License. The full license is in
5 // the file COPYING, distributed as part of this software.
5 // the file COPYING, distributed as part of this software.
6 //----------------------------------------------------------------------------
6 //----------------------------------------------------------------------------
7
7
8 //============================================================================
8 //============================================================================
9 // SaveWidget
9 // SaveWidget
10 //============================================================================
10 //============================================================================
11
11
12 var IPython = (function (IPython) {
12 var IPython = (function (IPython) {
13
13
14 var utils = IPython.utils;
14 var utils = IPython.utils;
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 = /[\/\\]/
18 this.notebook_name_blacklist_re = /[\/\\]/;
19 this.last_saved_name = '';
19 this.last_saved_name = '';
20 if (this.selector !== undefined) {
20 if (this.selector !== undefined) {
21 this.element = $(selector);
21 this.element = $(selector);
22 this.style();
22 this.style();
23 this.bind_events();
23 this.bind_events();
24 }
24 }
25 };
25 };
26
26
27
27
28 SaveWidget.prototype.style = function () {
28 SaveWidget.prototype.style = function () {
29 this.element.find('input#notebook_name').addClass('ui-widget ui-widget-content');
29 this.element.find('input#notebook_name').addClass('ui-widget ui-widget-content');
30 this.element.find('input#notebook_name').attr('tabindex','1');
30 this.element.find('input#notebook_name').attr('tabindex','1');
31 this.element.find('button#save_notebook').button();
31 this.element.find('button#save_notebook').button();
32 this.element.find('button#save_notebook').attr('title', 'Save the Notebook');
32 this.element.find('button#save_notebook').attr('title', 'Save the Notebook');
33 var left_panel_width = $('div#left_panel').outerWidth();
33 var left_panel_width = $('div#left_panel').outerWidth();
34 var left_panel_splitter_width = $('div#left_panel_splitter').outerWidth();
34 var left_panel_splitter_width = $('div#left_panel_splitter').outerWidth();
35 $('span#save_widget').css({marginLeft:left_panel_width+left_panel_splitter_width});
35 $('span#save_widget').css({marginLeft:left_panel_width+left_panel_splitter_width});
36
36
37 };
37 };
38
38
39
39
40 SaveWidget.prototype.bind_events = function () {
40 SaveWidget.prototype.bind_events = function () {
41 var that = this;
41 var that = this;
42 this.element.find('button#save_notebook').click(function () {
42 this.element.find('button#save_notebook').click(function () {
43 that.save_notebook();
43 that.save_notebook();
44 });
44 });
45 this.element.find('input#notebook_name').keyup(function () {
45 this.element.find('input#notebook_name').keyup(function () {
46 that.is_renaming();
46 that.is_renaming();
47 });
47 });
48 };
48 };
49
49
50
50
51 SaveWidget.prototype.save_notebook = function () {
51 SaveWidget.prototype.save_notebook = function () {
52 IPython.notebook.save_notebook();
52 IPython.notebook.save_notebook();
53 };
53 };
54
54
55
55
56 SaveWidget.prototype.notebook_saved = function () {
56 SaveWidget.prototype.notebook_saved = function () {
57 this.set_document_title();
57 this.set_document_title();
58 this.last_saved_name = this.get_notebook_name();
58 this.last_saved_name = this.get_notebook_name();
59 };
59 };
60
60
61
61
62 SaveWidget.prototype.is_renaming = function () {
62 SaveWidget.prototype.is_renaming = function () {
63 if (this.get_notebook_name() !== this.last_saved_name) {
63 if (this.get_notebook_name() !== this.last_saved_name) {
64 this.status_rename();
64 this.status_rename();
65 } else {
65 } else {
66 this.status_save();
66 this.status_save();
67 };
67 };
68 };
68 };
69
69
70
70
71 SaveWidget.prototype.get_notebook_name = function () {
71 SaveWidget.prototype.get_notebook_name = function () {
72 return this.element.find('input#notebook_name').attr('value');
72 return this.element.find('input#notebook_name').attr('value');
73 }
73 };
74
74
75
75
76 SaveWidget.prototype.set_notebook_name = function (nbname) {
76 SaveWidget.prototype.set_notebook_name = function (nbname) {
77 this.element.find('input#notebook_name').attr('value',nbname);
77 this.element.find('input#notebook_name').attr('value',nbname);
78 this.set_document_title();
78 this.set_document_title();
79 this.last_saved_name = nbname;
79 this.last_saved_name = nbname;
80 }
80 };
81
81
82
82
83 SaveWidget.prototype.set_document_title = function () {
83 SaveWidget.prototype.set_document_title = function () {
84 nbname = this.get_notebook_name();
84 nbname = this.get_notebook_name();
85 document.title = nbname;
85 document.title = nbname;
86 };
86 };
87
87
88
88
89 SaveWidget.prototype.get_notebook_id = function () {
89 SaveWidget.prototype.get_notebook_id = function () {
90 return $('body').data('notebookId');
90 return $('body').data('notebookId');
91 };
91 };
92
92
93
93
94 SaveWidget.prototype.update_url = function () {
94 SaveWidget.prototype.update_url = function () {
95 var notebook_id = this.get_notebook_id();
95 var notebook_id = this.get_notebook_id();
96 if (notebook_id !== '') {
96 if (notebook_id !== '') {
97 window.history.replaceState({}, '', notebook_id);
97 window.history.replaceState({}, '', notebook_id);
98 };
98 };
99 };
99 };
100
100
101
101
102 SaveWidget.prototype.test_notebook_name = function () {
102 SaveWidget.prototype.test_notebook_name = function () {
103 var nbname = this.get_notebook_name();
103 var nbname = this.get_notebook_name();
104 if (this.notebook_name_blacklist_re.test(nbname) == false) {
104 if (this.notebook_name_blacklist_re.test(nbname) == false) {
105 return true;
105 return true;
106 } else {
106 } else {
107 var bad_name = $('<div/>');
107 var bad_name = $('<div/>');
108 bad_name.html(
108 bad_name.html(
109 "The notebook name you entered (" +
109 "The notebook name you entered (" +
110 nbname +
110 nbname +
111 ") is not valid. Notebook names can contain any characters except / and \\."
111 ") is not valid. Notebook names can contain any characters except / and \\."
112 );
112 );
113 bad_name.dialog({title: 'Invalid name', modal: true});
113 bad_name.dialog({title: 'Invalid name', modal: true});
114 return false;
114 return false;
115 };
115 };
116 };
116 };
117
117
118
118
119 SaveWidget.prototype.reset_status = function () {
119 SaveWidget.prototype.reset_status = function () {
120 this.is_renaming();
120 this.is_renaming();
121 };
121 };
122
122
123
123
124 SaveWidget.prototype.status_save = function () {
124 SaveWidget.prototype.status_save = function () {
125 this.element.find('button#save_notebook').button('option', 'label', '<u>S</u>ave');
125 this.element.find('button#save_notebook').button('option', 'label', '<u>S</u>ave');
126 this.element.find('button#save_notebook').button('enable');
126 this.element.find('button#save_notebook').button('enable');
127 IPython.print_widget.enable();
127 IPython.print_widget.enable();
128 };
128 };
129
129
130
130
131 SaveWidget.prototype.status_saving = function () {
131 SaveWidget.prototype.status_saving = function () {
132 this.element.find('button#save_notebook').button('option', 'label', 'Saving');
132 this.element.find('button#save_notebook').button('option', 'label', 'Saving');
133 this.element.find('button#save_notebook').button('disable');
133 this.element.find('button#save_notebook').button('disable');
134 IPython.print_widget.disable();
134 IPython.print_widget.disable();
135 };
135 };
136
136
137
137
138 SaveWidget.prototype.status_loading = function () {
138 SaveWidget.prototype.status_loading = function () {
139 this.element.find('button#save_notebook').button('option', 'label', 'Loading');
139 this.element.find('button#save_notebook').button('option', 'label', 'Loading');
140 this.element.find('button#save_notebook').button('disable');
140 this.element.find('button#save_notebook').button('disable');
141 IPython.print_widget.disable();
141 IPython.print_widget.disable();
142 };
142 };
143
143
144
144
145 SaveWidget.prototype.status_rename = function () {
145 SaveWidget.prototype.status_rename = function () {
146 this.element.find('button#save_notebook').button('option', 'label', 'Rename');
146 this.element.find('button#save_notebook').button('option', 'label', 'Rename');
147 this.element.find('button#save_notebook').button('enable');
147 this.element.find('button#save_notebook').button('enable');
148 IPython.print_widget.enable();
148 IPython.print_widget.enable();
149 };
149 };
150
150
151
151
152 IPython.SaveWidget = SaveWidget;
152 IPython.SaveWidget = SaveWidget;
153
153
154 return IPython;
154 return IPython;
155
155
156 }(IPython));
156 }(IPython));
157
157
@@ -1,272 +1,272
1 //----------------------------------------------------------------------------
1 //----------------------------------------------------------------------------
2 // Copyright (C) 2008-2011 The IPython Development Team
2 // Copyright (C) 2008-2011 The IPython Development Team
3 //
3 //
4 // Distributed under the terms of the BSD License. The full license is in
4 // Distributed under the terms of the BSD License. The full license is in
5 // the file COPYING, distributed as part of this software.
5 // the file COPYING, distributed as part of this software.
6 //----------------------------------------------------------------------------
6 //----------------------------------------------------------------------------
7
7
8 //============================================================================
8 //============================================================================
9 // TextCell
9 // TextCell
10 //============================================================================
10 //============================================================================
11
11
12 var IPython = (function (IPython) {
12 var IPython = (function (IPython) {
13
13
14 // TextCell base class
14 // TextCell base class
15
15
16 var TextCell = function (notebook) {
16 var TextCell = function (notebook) {
17 this.code_mirror_mode = this.code_mirror_mode || 'htmlmixed';
17 this.code_mirror_mode = this.code_mirror_mode || 'htmlmixed';
18 this.placeholder = this.placeholder || '\u0000';
18 this.placeholder = this.placeholder || '\u0000';
19 IPython.Cell.apply(this, arguments);
19 IPython.Cell.apply(this, arguments);
20 this.rendered = false;
20 this.rendered = false;
21 this.cell_type = this.cell_type || 'text';
21 this.cell_type = this.cell_type || 'text';
22 };
22 };
23
23
24
24
25 TextCell.prototype = new IPython.Cell();
25 TextCell.prototype = new IPython.Cell();
26
26
27
27
28 TextCell.prototype.create_element = function () {
28 TextCell.prototype.create_element = function () {
29 var cell = $("<div>").addClass('cell text_cell border-box-sizing');
29 var cell = $("<div>").addClass('cell text_cell border-box-sizing');
30 cell.attr('tabindex','2');
30 cell.attr('tabindex','2');
31 var input_area = $('<div/>').addClass('text_cell_input');
31 var input_area = $('<div/>').addClass('text_cell_input');
32 this.code_mirror = CodeMirror(input_area.get(0), {
32 this.code_mirror = CodeMirror(input_area.get(0), {
33 indentUnit : 4,
33 indentUnit : 4,
34 mode: this.code_mirror_mode,
34 mode: this.code_mirror_mode,
35 theme: 'default',
35 theme: 'default',
36 value: this.placeholder,
36 value: this.placeholder,
37 readOnly: this.read_only,
37 readOnly: this.read_only
38 });
38 });
39 // The tabindex=-1 makes this div focusable.
39 // The tabindex=-1 makes this div focusable.
40 var render_area = $('<div/>').addClass('text_cell_render').
40 var render_area = $('<div/>').addClass('text_cell_render').
41 addClass('rendered_html').attr('tabindex','-1');
41 addClass('rendered_html').attr('tabindex','-1');
42 cell.append(input_area).append(render_area);
42 cell.append(input_area).append(render_area);
43 this.element = cell;
43 this.element = cell;
44 };
44 };
45
45
46
46
47 TextCell.prototype.bind_events = function () {
47 TextCell.prototype.bind_events = function () {
48 IPython.Cell.prototype.bind_events.apply(this);
48 IPython.Cell.prototype.bind_events.apply(this);
49 var that = this;
49 var that = this;
50 this.element.keydown(function (event) {
50 this.element.keydown(function (event) {
51 if (event.which === 13) {
51 if (event.which === 13) {
52 if (that.rendered) {
52 if (that.rendered) {
53 that.edit();
53 that.edit();
54 event.preventDefault();
54 event.preventDefault();
55 };
55 }
56 };
56 }
57 });
57 });
58 };
58 };
59
59
60
60
61 TextCell.prototype.select = function () {
61 TextCell.prototype.select = function () {
62 IPython.Cell.prototype.select.apply(this);
62 IPython.Cell.prototype.select.apply(this);
63 var output = this.element.find("div.text_cell_render");
63 var output = this.element.find("div.text_cell_render");
64 output.trigger('focus');
64 output.trigger('focus');
65 };
65 };
66
66
67
67
68 TextCell.prototype.edit = function () {
68 TextCell.prototype.edit = function () {
69 if ( this.read_only ) return;
69 if ( this.read_only ) return;
70 if (this.rendered === true) {
70 if (this.rendered === true) {
71 var text_cell = this.element;
71 var text_cell = this.element;
72 var output = text_cell.find("div.text_cell_render");
72 var output = text_cell.find("div.text_cell_render");
73 output.hide();
73 output.hide();
74 text_cell.find('div.text_cell_input').show();
74 text_cell.find('div.text_cell_input').show();
75 this.code_mirror.focus();
75 this.code_mirror.focus();
76 this.code_mirror.refresh();
76 this.code_mirror.refresh();
77 this.rendered = false;
77 this.rendered = false;
78 if (this.get_source() === this.placeholder) {
78 if (this.get_source() === this.placeholder) {
79 this.set_source('');
79 this.set_source('');
80 };
80 }
81 };
81 }
82 };
82 };
83
83
84
84
85 // Subclasses must define render.
85 // Subclasses must define render.
86 TextCell.prototype.render = function () {};
86 TextCell.prototype.render = function () {};
87
87
88
88
89 TextCell.prototype.config_mathjax = function () {
89 TextCell.prototype.config_mathjax = function () {
90 var text_cell = this.element;
90 var text_cell = this.element;
91 var that = this;
91 var that = this;
92 text_cell.click(function () {
92 text_cell.click(function () {
93 that.edit();
93 that.edit();
94 }).focusout(function () {
94 }).focusout(function () {
95 that.render();
95 that.render();
96 });
96 });
97
97
98 text_cell.trigger("focusout");
98 text_cell.trigger("focusout");
99 };
99 };
100
100
101
101
102 TextCell.prototype.get_source = function() {
102 TextCell.prototype.get_source = function() {
103 return this.code_mirror.getValue();
103 return this.code_mirror.getValue();
104 };
104 };
105
105
106
106
107 TextCell.prototype.set_source = function(text) {
107 TextCell.prototype.set_source = function(text) {
108 this.code_mirror.setValue(text);
108 this.code_mirror.setValue(text);
109 this.code_mirror.refresh();
109 this.code_mirror.refresh();
110 };
110 };
111
111
112
112
113 TextCell.prototype.get_rendered = function() {
113 TextCell.prototype.get_rendered = function() {
114 return this.element.find('div.text_cell_render').html();
114 return this.element.find('div.text_cell_render').html();
115 };
115 };
116
116
117
117
118 TextCell.prototype.set_rendered = function(text) {
118 TextCell.prototype.set_rendered = function(text) {
119 this.element.find('div.text_cell_render').html(text);
119 this.element.find('div.text_cell_render').html(text);
120 };
120 };
121
121
122
122
123 TextCell.prototype.at_top = function () {
123 TextCell.prototype.at_top = function () {
124 if (this.rendered) {
124 if (this.rendered) {
125 return true;
125 return true;
126 } else {
126 } else {
127 return false;
127 return false;
128 }
128 }
129 };
129 };
130
130
131
131
132 TextCell.prototype.at_bottom = function () {
132 TextCell.prototype.at_bottom = function () {
133 if (this.rendered) {
133 if (this.rendered) {
134 return true;
134 return true;
135 } else {
135 } else {
136 return false;
136 return false;
137 }
137 }
138 };
138 };
139
139
140
140
141 TextCell.prototype.fromJSON = function (data) {
141 TextCell.prototype.fromJSON = function (data) {
142 if (data.cell_type === this.cell_type) {
142 if (data.cell_type === this.cell_type) {
143 if (data.source !== undefined) {
143 if (data.source !== undefined) {
144 this.set_source(data.source);
144 this.set_source(data.source);
145 this.set_rendered(data.rendered || '');
145 this.set_rendered(data.rendered || '');
146 this.rendered = false;
146 this.rendered = false;
147 this.render();
147 this.render();
148 };
148 }
149 };
149 }
150 };
150 };
151
151
152
152
153 TextCell.prototype.toJSON = function () {
153 TextCell.prototype.toJSON = function () {
154 var data = {}
154 var data = {};
155 data.cell_type = this.cell_type;
155 data.cell_type = this.cell_type;
156 data.source = this.get_source();
156 data.source = this.get_source();
157 return data;
157 return data;
158 };
158 };
159
159
160
160
161 // HTMLCell
161 // HTMLCell
162
162
163 var HTMLCell = function (notebook) {
163 var HTMLCell = function (notebook) {
164 this.placeholder = "\u0000Type <strong>HTML</strong> and LaTeX: $\\alpha^2$";
164 this.placeholder = "\u0000Type <strong>HTML</strong> and LaTeX: $\\alpha^2$";
165 IPython.TextCell.apply(this, arguments);
165 IPython.TextCell.apply(this, arguments);
166 this.cell_type = 'html';
166 this.cell_type = 'html';
167 };
167 };
168
168
169
169
170 HTMLCell.prototype = new TextCell();
170 HTMLCell.prototype = new TextCell();
171
171
172
172
173 HTMLCell.prototype.render = function () {
173 HTMLCell.prototype.render = function () {
174 if (this.rendered === false) {
174 if (this.rendered === false) {
175 var text = this.get_source();
175 var text = this.get_source();
176 if (text === "") {text = this.placeholder;};
176 if (text === "") { text = this.placeholder; }
177 this.set_rendered(text);
177 this.set_rendered(text);
178 MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
178 MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
179 this.element.find('div.text_cell_input').hide();
179 this.element.find('div.text_cell_input').hide();
180 this.element.find("div.text_cell_render").show();
180 this.element.find("div.text_cell_render").show();
181 this.rendered = true;
181 this.rendered = true;
182 };
182 }
183 };
183 };
184
184
185
185
186 // MarkdownCell
186 // MarkdownCell
187
187
188 var MarkdownCell = function (notebook) {
188 var MarkdownCell = function (notebook) {
189 this.placeholder = "\u0000Type *Markdown* and LaTeX: $\\alpha^2$";
189 this.placeholder = "\u0000Type *Markdown* and LaTeX: $\\alpha^2$";
190 IPython.TextCell.apply(this, arguments);
190 IPython.TextCell.apply(this, arguments);
191 this.cell_type = 'markdown';
191 this.cell_type = 'markdown';
192 };
192 };
193
193
194
194
195 MarkdownCell.prototype = new TextCell();
195 MarkdownCell.prototype = new TextCell();
196
196
197
197
198 MarkdownCell.prototype.render = function () {
198 MarkdownCell.prototype.render = function () {
199 if (this.rendered === false) {
199 if (this.rendered === false) {
200 var text = this.get_source();
200 var text = this.get_source();
201 if (text === "") {text = this.placeholder;};
201 if (text === "") { text = this.placeholder; }
202 var html = IPython.markdown_converter.makeHtml(text);
202 var html = IPython.markdown_converter.makeHtml(text);
203 this.set_rendered(html);
203 this.set_rendered(html);
204 MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
204 MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
205 this.element.find('div.text_cell_input').hide();
205 this.element.find('div.text_cell_input').hide();
206 this.element.find("div.text_cell_render").show();
206 this.element.find("div.text_cell_render").show();
207 var code_snippets = this.element.find("pre > code");
207 var code_snippets = this.element.find("pre > code");
208 code_snippets.replaceWith(function () {
208 code_snippets.replaceWith(function () {
209 var code = $(this).html();
209 var code = $(this).html();
210 /* Substitute br for newlines and &nbsp; for spaces
210 /* Substitute br for newlines and &nbsp; for spaces
211 before highlighting, since prettify doesn't
211 before highlighting, since prettify doesn't
212 preserve those on all browsers */
212 preserve those on all browsers */
213 code = code.replace(/(\r\n|\n|\r)/gm, "<br/>");
213 code = code.replace(/(\r\n|\n|\r)/gm, "<br/>");
214 code = code.replace(/ /gm, '&nbsp;');
214 code = code.replace(/ /gm, '&nbsp;');
215 code = prettyPrintOne(code);
215 code = prettyPrintOne(code);
216
216
217 return '<code class="prettyprint">' + code + '</code>';
217 return '<code class="prettyprint">' + code + '</code>';
218 });
218 });
219 this.rendered = true;
219 this.rendered = true;
220 };
220 }
221 };
221 };
222
222
223
223
224 // RSTCell
224 // RSTCell
225
225
226 var RSTCell = function (notebook) {
226 var RSTCell = function (notebook) {
227 this.placeholder = "\u0000Type *ReStructured Text* and LaTeX: $\\alpha^2$";
227 this.placeholder = "\u0000Type *ReStructured Text* and LaTeX: $\\alpha^2$";
228 IPython.TextCell.apply(this, arguments);
228 IPython.TextCell.apply(this, arguments);
229 this.cell_type = 'rst';
229 this.cell_type = 'rst';
230 };
230 };
231
231
232
232
233 RSTCell.prototype = new TextCell();
233 RSTCell.prototype = new TextCell();
234
234
235
235
236 RSTCell.prototype.render = function () {
236 RSTCell.prototype.render = function () {
237 if (this.rendered === false) {
237 if (this.rendered === false) {
238 var text = this.get_source();
238 var text = this.get_source();
239 if (text === "") {text = this.placeholder;};
239 if (text === "") { text = this.placeholder; }
240 var settings = {
240 var settings = {
241 processData : false,
241 processData : false,
242 cache : false,
242 cache : false,
243 type : "POST",
243 type : "POST",
244 data : text,
244 data : text,
245 headers : {'Content-Type': 'application/x-rst'},
245 headers : {'Content-Type': 'application/x-rst'},
246 success : $.proxy(this.handle_render,this)
246 success : $.proxy(this.handle_render,this)
247 };
247 };
248 $.ajax("/rstservice/render", settings);
248 $.ajax("/rstservice/render", settings);
249 this.element.find('div.text_cell_input').hide();
249 this.element.find('div.text_cell_input').hide();
250 this.element.find("div.text_cell_render").show();
250 this.element.find("div.text_cell_render").show();
251 this.set_rendered("Rendering...");
251 this.set_rendered("Rendering...");
252 };
252 }
253 };
253 };
254
254
255
255
256 RSTCell.prototype.handle_render = function (data, status, xhr) {
256 RSTCell.prototype.handle_render = function (data, status, xhr) {
257 this.set_rendered(data);
257 this.set_rendered(data);
258 MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
258 MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
259 this.rendered = true;
259 this.rendered = true;
260 };
260 };
261
261
262
262
263 IPython.TextCell = TextCell;
263 IPython.TextCell = TextCell;
264 IPython.HTMLCell = HTMLCell;
264 IPython.HTMLCell = HTMLCell;
265 IPython.MarkdownCell = MarkdownCell;
265 IPython.MarkdownCell = MarkdownCell;
266 IPython.RSTCell = RSTCell;
266 IPython.RSTCell = RSTCell;
267
267
268
268
269 return IPython;
269 return IPython;
270
270
271 }(IPython));
271 }(IPython));
272
272
@@ -1,101 +1,101
1 //----------------------------------------------------------------------------
1 //----------------------------------------------------------------------------
2 // Copyright (C) 2008-2011 The IPython Development Team
2 // Copyright (C) 2008-2011 The IPython Development Team
3 //
3 //
4 // Distributed under the terms of the BSD License. The full license is in
4 // Distributed under the terms of the BSD License. The full license is in
5 // the file COPYING, distributed as part of this software.
5 // the file COPYING, distributed as part of this software.
6 //----------------------------------------------------------------------------
6 //----------------------------------------------------------------------------
7
7
8 //============================================================================
8 //============================================================================
9 // Utilities
9 // Utilities
10 //============================================================================
10 //============================================================================
11
11
12 IPython.namespace('IPython.utils')
12 IPython.namespace('IPython.utils');
13
13
14 IPython.utils = (function (IPython) {
14 IPython.utils = (function (IPython) {
15
15
16 var uuid = function () {
16 var uuid = function () {
17 // http://www.ietf.org/rfc/rfc4122.txt
17 // http://www.ietf.org/rfc/rfc4122.txt
18 var s = [];
18 var s = [];
19 var hexDigits = "0123456789ABCDEF";
19 var hexDigits = "0123456789ABCDEF";
20 for (var i = 0; i < 32; i++) {
20 for (var i = 0; i < 32; i++) {
21 s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
21 s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
22 }
22 }
23 s[12] = "4"; // bits 12-15 of the time_hi_and_version field to 0010
23 s[12] = "4"; // bits 12-15 of the time_hi_and_version field to 0010
24 s[16] = hexDigits.substr((s[16] & 0x3) | 0x8, 1); // bits 6-7 of the clock_seq_hi_and_reserved to 01
24 s[16] = hexDigits.substr((s[16] & 0x3) | 0x8, 1); // bits 6-7 of the clock_seq_hi_and_reserved to 01
25
25
26 var uuid = s.join("");
26 var uuid = s.join("");
27 return uuid;
27 return uuid;
28 };
28 };
29
29
30
30
31 //Fix raw text to parse correctly in crazy XML
31 //Fix raw text to parse correctly in crazy XML
32 function xmlencode(string) {
32 function xmlencode(string) {
33 return string.replace(/\&/g,'&'+'amp;')
33 return string.replace(/\&/g,'&'+'amp;')
34 .replace(/</g,'&'+'lt;')
34 .replace(/</g,'&'+'lt;')
35 .replace(/>/g,'&'+'gt;')
35 .replace(/>/g,'&'+'gt;')
36 .replace(/\'/g,'&'+'apos;')
36 .replace(/\'/g,'&'+'apos;')
37 .replace(/\"/g,'&'+'quot;')
37 .replace(/\"/g,'&'+'quot;')
38 .replace(/`/g,'&'+'#96;')
38 .replace(/`/g,'&'+'#96;');
39 }
39 }
40
40
41
41
42 //Map from terminal commands to CSS classes
42 //Map from terminal commands to CSS classes
43 ansi_colormap = {
43 ansi_colormap = {
44 "30":"ansiblack", "31":"ansired",
44 "30":"ansiblack", "31":"ansired",
45 "32":"ansigreen", "33":"ansiyellow",
45 "32":"ansigreen", "33":"ansiyellow",
46 "34":"ansiblue", "35":"ansipurple","36":"ansicyan",
46 "34":"ansiblue", "35":"ansipurple","36":"ansicyan",
47 "37":"ansigrey", "01":"ansibold"
47 "37":"ansigrey", "01":"ansibold"
48 }
48 };
49
49
50 // Transform ANI color escape codes into HTML <span> tags with css
50 // Transform ANI color escape codes into HTML <span> tags with css
51 // classes listed in the above ansi_colormap object. The actual color used
51 // classes listed in the above ansi_colormap object. The actual color used
52 // are set in the css file.
52 // are set in the css file.
53 function fixConsole(txt) {
53 function fixConsole(txt) {
54 txt = xmlencode(txt)
54 txt = xmlencode(txt);
55 var re = /\033\[([\d;]*?)m/
55 var re = /\033\[([\d;]*?)m/;
56 var opened = false
56 var opened = false;
57 var cmds = []
57 var cmds = [];
58 var opener = ""
58 var opener = "";
59 var closer = ""
59 var closer = "";
60
60
61 while (re.test(txt)) {
61 while (re.test(txt)) {
62 var cmds = txt.match(re)[1].split(";")
62 var cmds = txt.match(re)[1].split(";");
63 closer = opened?"</span>":""
63 closer = opened?"</span>":"";
64 opened = cmds.length > 1 || cmds[0] != 0
64 opened = cmds.length > 1 || cmds[0] != 0;
65 var rep = []
65 var rep = [];
66 for (var i in cmds)
66 for (var i in cmds)
67 if (typeof(ansi_colormap[cmds[i]]) != "undefined")
67 if (typeof(ansi_colormap[cmds[i]]) != "undefined")
68 rep.push(ansi_colormap[cmds[i]])
68 rep.push(ansi_colormap[cmds[i]]);
69 opener = rep.length > 0?"<span class=\""+rep.join(" ")+"\">":""
69 opener = rep.length > 0?"<span class=\""+rep.join(" ")+"\">":"";
70 txt = txt.replace(re, closer + opener)
70 txt = txt.replace(re, closer + opener);
71 }
71 }
72 if (opened) txt += "</span>"
72 if (opened) txt += "</span>";
73 return txt
73 return txt;
74 }
74 }
75
75
76
76
77 grow = function(element) {
77 grow = function(element) {
78 // Grow the cell by hand. This is used upon reloading from JSON, when the
78 // Grow the cell by hand. This is used upon reloading from JSON, when the
79 // autogrow handler is not called.
79 // autogrow handler is not called.
80 var dom = element.get(0);
80 var dom = element.get(0);
81 var lines_count = 0;
81 var lines_count = 0;
82 // modified split rule from
82 // modified split rule from
83 // http://stackoverflow.com/questions/2035910/how-to-get-the-number-of-lines-in-a-textarea/2036424#2036424
83 // http://stackoverflow.com/questions/2035910/how-to-get-the-number-of-lines-in-a-textarea/2036424#2036424
84 var lines = dom.value.split(/\r|\r\n|\n/);
84 var lines = dom.value.split(/\r|\r\n|\n/);
85 lines_count = lines.length;
85 lines_count = lines.length;
86 if (lines_count >= 1) {
86 if (lines_count >= 1) {
87 dom.rows = lines_count;
87 dom.rows = lines_count;
88 } else {
88 } else {
89 dom.rows = 1;
89 dom.rows = 1;
90 }
90 }
91 };
91 };
92
92
93
93
94 return {
94 return {
95 uuid : uuid,
95 uuid : uuid,
96 fixConsole : fixConsole,
96 fixConsole : fixConsole,
97 grow : grow
97 grow : grow
98 }
98 };
99
99
100 }(IPython));
100 }(IPython));
101
101
General Comments 0
You need to be logged in to leave comments. Login now