##// END OF EJS Templates
tabs fast forward user tab
Matthias BUSSONNIER -
Show More
@@ -1,750 +1,771 b''
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 return false;
146 };
146 };
147
147
148 CodeCell.prototype.remove_and_cancell_tooltip = function(timeout)
148 CodeCell.prototype.remove_and_cancell_tooltip = function(timeout)
149 {
149 {
150 // note that we don't handle closing directly inside the calltip
150 // note that we don't handle closing directly inside the calltip
151 // 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
152 // get the event.
152 // get the event.
153 clearTimeout(timeout);
153 clearTimeout(timeout);
154 $('#tooltip').remove();
154 $('#tooltip').remove();
155 }
155 }
156
156
157 CodeCell.prototype.finish_tooltip = function (reply) {
157 CodeCell.prototype.finish_tooltip = function (reply) {
158 defstring=reply.definition;
158 defstring=reply.definition;
159 docstring=reply.docstring;
159 docstring=reply.docstring;
160 if(docstring == null){docstring="<empty docstring>"};
160 if(docstring == null){docstring="<empty docstring>"};
161 name=reply.name;
161 name=reply.name;
162
162
163 var that = this;
163 var that = this;
164 var tooltip = $('<div/>').attr('id', 'tooltip').addClass('tooltip');
164 var tooltip = $('<div/>').attr('id', 'tooltip').addClass('tooltip');
165 // remove to have the tooltip not Limited in X and Y
165 // remove to have the tooltip not Limited in X and Y
166 tooltip.addClass('smalltooltip');
166 tooltip.addClass('smalltooltip');
167 var pre=$('<pre/>').html(utils.fixConsole(docstring));
167 var pre=$('<pre/>').html(utils.fixConsole(docstring));
168 var expandlink=$('<a/>').attr('href',"#");
168 var expandlink=$('<a/>').attr('href',"#");
169 expandlink.addClass("ui-corner-all"); //rounded corner
169 expandlink.addClass("ui-corner-all"); //rounded corner
170 expandlink.attr('role',"button");
170 expandlink.attr('role',"button");
171 //expandlink.addClass('ui-button');
171 //expandlink.addClass('ui-button');
172 //expandlink.addClass('ui-state-default');
172 //expandlink.addClass('ui-state-default');
173 var expandspan=$('<span/>').text('Expand');
173 var expandspan=$('<span/>').text('Expand');
174 expandspan.addClass('ui-icon');
174 expandspan.addClass('ui-icon');
175 expandspan.addClass('ui-icon-plus');
175 expandspan.addClass('ui-icon-plus');
176 expandlink.append(expandspan);
176 expandlink.append(expandspan);
177 expandlink.attr('id','expanbutton');
177 expandlink.attr('id','expanbutton');
178 expandlink.click(function(){
178 expandlink.click(function(){
179 tooltip.removeClass('smalltooltip');
179 tooltip.removeClass('smalltooltip');
180 tooltip.addClass('bigtooltip');
180 tooltip.addClass('bigtooltip');
181 $('#expanbutton').remove();
181 $('#expanbutton').remove();
182 setTimeout(function(){that.code_mirror.focus();}, 50);
182 setTimeout(function(){that.code_mirror.focus();}, 50);
183 });
183 });
184 var morelink=$('<a/>').attr('href',"#");
184 var morelink=$('<a/>').attr('href',"#");
185 morelink.attr('role',"button");
185 morelink.attr('role',"button");
186 morelink.addClass('ui-button');
186 morelink.addClass('ui-button');
187 //morelink.addClass("ui-corner-all"); //rounded corner
187 //morelink.addClass("ui-corner-all"); //rounded corner
188 //morelink.addClass('ui-state-default');
188 //morelink.addClass('ui-state-default');
189 var morespan=$('<span/>').text('Open in Pager');
189 var morespan=$('<span/>').text('Open in Pager');
190 morespan.addClass('ui-icon');
190 morespan.addClass('ui-icon');
191 morespan.addClass('ui-icon-arrowstop-l-n');
191 morespan.addClass('ui-icon-arrowstop-l-n');
192 morelink.append(morespan);
192 morelink.append(morespan);
193 morelink.click(function(){
193 morelink.click(function(){
194 var msg_id = IPython.notebook.kernel.execute(name+"?");
194 var msg_id = IPython.notebook.kernel.execute(name+"?");
195 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;
196 CodeCell.prototype.remove_and_cancell_tooltip(that.tooltip_timeout);
196 CodeCell.prototype.remove_and_cancell_tooltip(that.tooltip_timeout);
197 setTimeout(function(){that.code_mirror.focus();}, 50);
197 setTimeout(function(){that.code_mirror.focus();}, 50);
198 });
198 });
199
199
200 var closelink=$('<a/>').attr('href',"#");
200 var closelink=$('<a/>').attr('href',"#");
201 closelink.attr('role',"button");
201 closelink.attr('role',"button");
202 closelink.addClass('ui-button');
202 closelink.addClass('ui-button');
203 //closelink.addClass("ui-corner-all"); //rounded corner
203 //closelink.addClass("ui-corner-all"); //rounded corner
204 //closelink.adClass('ui-state-default'); // grey background and blue cross
204 //closelink.adClass('ui-state-default'); // grey background and blue cross
205 var closespan=$('<span/>').text('Close');
205 var closespan=$('<span/>').text('Close');
206 closespan.addClass('ui-icon');
206 closespan.addClass('ui-icon');
207 closespan.addClass('ui-icon-close');
207 closespan.addClass('ui-icon-close');
208 closelink.append(closespan);
208 closelink.append(closespan);
209 closelink.click(function(){
209 closelink.click(function(){
210 CodeCell.prototype.remove_and_cancell_tooltip(that.tooltip_timeout);
210 CodeCell.prototype.remove_and_cancell_tooltip(that.tooltip_timeout);
211 setTimeout(function(){that.code_mirror.focus();}, 50);
211 setTimeout(function(){that.code_mirror.focus();}, 50);
212 });
212 });
213 //construct the tooltip
213 //construct the tooltip
214 tooltip.append(closelink);
214 tooltip.append(closelink);
215 tooltip.append(expandlink);
215 tooltip.append(expandlink);
216 tooltip.append(morelink);
216 tooltip.append(morelink);
217 if(defstring){
217 if(defstring){
218 defstring_html= $('<pre/>').html(utils.fixConsole(defstring));
218 defstring_html= $('<pre/>').html(utils.fixConsole(defstring));
219 tooltip.append(defstring_html);
219 tooltip.append(defstring_html);
220 }
220 }
221 tooltip.append(pre);
221 tooltip.append(pre);
222 var pos = this.code_mirror.cursorCoords();
222 var pos = this.code_mirror.cursorCoords();
223 tooltip.css('left',pos.x+'px');
223 tooltip.css('left',pos.x+'px');
224 tooltip.css('top',pos.yBot+'px');
224 tooltip.css('top',pos.yBot+'px');
225 $('body').append(tooltip);
225 $('body').append(tooltip);
226
226
227 // issues with cross-closing if multiple tooltip in less than 5sec
227 // issues with cross-closing if multiple tooltip in less than 5sec
228 // keep it comented for now
228 // keep it comented for now
229 // setTimeout(CodeCell.prototype.remove_and_cancell_tooltip, 5000);
229 // setTimeout(CodeCell.prototype.remove_and_cancell_tooltip, 5000);
230 };
230 };
231
231
232 // As you type completer
232 // As you type completer
233 CodeCell.prototype.finish_completing = function (matched_text, matches) {
233 CodeCell.prototype.finish_completing = function (matched_text, matches) {
234
234
235 // smart completion, sort kwarg ending with '='
235 // smart completion, sort kwarg ending with '='
236 var newm = new Array();
236 var newm = new Array();
237 if(this.notebook.smart_completer)
237 if(this.notebook.smart_completer)
238 {
238 {
239 kwargs = new Array();
239 kwargs = new Array();
240 other = new Array();
240 other = new Array();
241 for(var i=0;i<matches.length; ++i){
241 for(var i=0;i<matches.length; ++i){
242 if(matches[i].substr(-1) === '='){
242 if(matches[i].substr(-1) === '='){
243 kwargs.push(matches[i]);
243 kwargs.push(matches[i]);
244 }else{other.push(matches[i]);}
244 }else{other.push(matches[i]);}
245 }
245 }
246 newm = kwargs.concat(other);
246 newm = kwargs.concat(other);
247 matches=newm;
247 matches=newm;
248 }
248 }
249 // end sort kwargs
249 // end sort kwargs
250
250
251 function sharedStart(A){
252 if(A.length > 1 ){
253 var tem1, tem2, s, A= A.slice(0).sort();
254 tem1= A[0];
255 s= tem1.length;
256 tem2= A.pop();
257 while(s && tem2.indexOf(tem1)== -1){
258 tem1= tem1.substring(0, --s);
259 }
260 return tem1;
261 }
262 return "";
263 }
264
251 if (!this.is_completing || matches.length === 0) {return;}
265 if (!this.is_completing || matches.length === 0) {return;}
252
266
253 //try to check if the user is typing tab at least twice after a word
267 //try to check if the user is typing tab at least twice after a word
254 // and completion is "done"
268 // and completion is "done"
255 fallback_on_tooltip_after=2
269 fallback_on_tooltip_after=2
256 if(matches.length==1 && matched_text === matches[0])
270 if(matches.length==1 && matched_text === matches[0])
257 {
271 {
258 if(this.npressed >fallback_on_tooltip_after && this.prevmatch==matched_text)
272 if(this.npressed >fallback_on_tooltip_after && this.prevmatch==matched_text)
259 {
273 {
260 console.log('Ok, you really want to complete after pressing tab '+this.npressed+' times !');
274 console.log('Ok, you really want to complete after pressing tab '+this.npressed+' times !');
261 console.log('You should understand that there is no (more) completion for that !');
275 console.log('You should understand that there is no (more) completion for that !');
262 console.log("I'll show you the tooltip, will you stop bothering me ?");
276 console.log("I'll show you the tooltip, will you stop bothering me ?");
263 this.request_tooltip_after_time(matched_text+'(',0,this);
277 this.request_tooltip_after_time(matched_text+'(',0,this);
264 return;
278 return;
265 }
279 }
266 this.prevmatch=matched_text
280 this.prevmatch=matched_text
267 this.npressed=this.npressed+1;
281 this.npressed=this.npressed+1;
268 }
282 }
269 else
283 else
270 {
284 {
271 this.prevmatch="";
285 this.prevmatch="";
272 this.npressed=0;
286 this.npressed=0;
273 }
287 }
274 // end fallback on tooltip
288 // end fallback on tooltip
275
289
276 // Real completion logic start here
290 // Real completion logic start here
277 var that = this;
291 var that = this;
278 var cur = this.completion_cursor;
292 var cur = this.completion_cursor;
279 var done = false;
293 var done = false;
280
294
281 // call to dismmiss the completer
295 // call to dismmiss the completer
282 var close = function () {
296 var close = function () {
283 if (done) return;
297 if (done) return;
284 done = true;
298 done = true;
285 if (complete!=undefined)
299 if (complete!=undefined)
286 {complete.remove();}
300 {complete.remove();}
287 that.is_completing = false;
301 that.is_completing = false;
288 that.completion_cursor = null;
302 that.completion_cursor = null;
289 };
303 };
290
304
291 // insert the given text and exit the completer
305 // insert the given text and exit the completer
292 var insert = function (selected_text) {
306 var insert = function (selected_text) {
293 that.code_mirror.replaceRange(
307 that.code_mirror.replaceRange(
294 selected_text,
308 selected_text,
295 {line: cur.line, ch: (cur.ch-matched_text.length)},
309 {line: cur.line, ch: (cur.ch-matched_text.length)},
296 {line: cur.line, ch: cur.ch}
310 {line: cur.line, ch: cur.ch}
297 );
311 );
298 event.stopPropagation();
312 event.stopPropagation();
299 event.preventDefault();
313 event.preventDefault();
300 close();
314 close();
301 setTimeout(function(){that.code_mirror.focus();}, 50);
315 setTimeout(function(){that.code_mirror.focus();}, 50);
302 };
316 };
303
317
304 // insert the curent highlited selection and exit
318 // insert the curent highlited selection and exit
305 var pick = function () {
319 var pick = function () {
306 insert(select.val()[0]);
320 insert(select.val()[0]);
307 };
321 };
308
322
309 // if only one match, complete to it, don't ask user
323 // if only one match, complete to it, don't ask user
310 if (matches.length === 1) {
324 if (matches.length === 1) {
311 insert(matches[0]);
325 insert(matches[0]);
312 return;
326 return;
313 };
327 };
314
328
315
329
316 // Define function to clear the completer, refill it with the new
330 // Define function to clear the completer, refill it with the new
317 // matches, update the pseuso typing field. Note that this is case
331 // matches, update the pseuso typing field. Note that this is case
318 // insensitive for now
332 // insensitive for now
319 var complete_with = function(matches,typed_text)
333 var complete_with = function(matches,typed_text)
320 {
334 {
321 //clear the previous completion if any
335 //clear the previous completion if any
322 if (matches.length < 1) {
336 if (matches.length < 1) {
323 insert(typed_text);
337 insert(typed_text);
324 }
338 }
325 complete.children().children().remove();
339 complete.children().children().remove();
326 $('#asyoutype').text(typed_text);
340 $('#asyoutype').text(typed_text);
327 select=$('#asyoutypeselect');
341 select=$('#asyoutypeselect');
328 for (var i=0; i<matches.length; ++i) {
342 for (var i=0; i<matches.length; ++i) {
329 select.append($('<option/>').html(matches[i]));
343 select.append($('<option/>').html(matches[i]));
330 }
344 }
331 select.children().first().attr('selected','true');
345 select.children().first().attr('selected','true');
332 }
346 }
333
347
334 // create html for completer
348 // create html for completer
335 var complete = $('<div/>').addClass('completions');
349 var complete = $('<div/>').addClass('completions');
336 complete.attr('id','complete');
350 complete.attr('id','complete');
337 complete.append($('<p/>').attr('id', 'asyoutype').html(matched_text));//pseudo input field
351 complete.append($('<p/>').attr('id', 'asyoutype').html(matched_text));//pseudo input field
338
352
339 var select = $('<select/>').attr('multiple','true');
353 var select = $('<select/>').attr('multiple','true');
340 select.attr('id', 'asyoutypeselect')
354 select.attr('id', 'asyoutypeselect')
341 select.attr('size',Math.min(10,matches.length));
355 select.attr('size',Math.min(10,matches.length));
342 var pos = this.code_mirror.cursorCoords();
356 var pos = this.code_mirror.cursorCoords();
343
357
344 // TODO: I propose to remove enough horizontal pixel
358 // TODO: I propose to remove enough horizontal pixel
345 // to align the text later
359 // to align the text later
346 complete.css('left',pos.x+'px');
360 complete.css('left',pos.x+'px');
347 complete.css('top',pos.yBot+'px');
361 complete.css('top',pos.yBot+'px');
348 complete.append(select);
362 complete.append(select);
349
363
350 $('body').append(complete);
364 $('body').append(complete);
351
365
352 //do a first actual completion
366 //do a first actual completion
353 complete_with(matches,matched_text);
367 complete_with(matches,matched_text);
354
368
355 // Give focus to select, and make it filter the match as the user type
369 // Give focus to select, and make it filter the match as the user type
356 // by filtering the previous matches
370 // by filtering the previous matches
357 typed_characters = "";
371 typed_characters = "";
358 var downandpress = function (event,press_or_down) {
372 var downandpress = function (event,press_or_down) {
359 if (press_or_down === 0){
373 if (press_or_down === 0){
360 press=true;
374 press=true;
361 down=false;
375 down=false;
362 } else if (press_or_down == 1){
376 } else if (press_or_down == 1){
363 press=false;
377 press=false;
364 down=true;
378 down=true;
365 }
379 }
366 var code = event.which;
380 var code = event.which;
367 if (code === 16) {
381 if (code === 16) {
368 // nothing on Shift
382 // nothing on Shift
369 return;
383 return;
370 }
384 }
371 if (code === 13 || code === 32) {
385 if (code === 13 || code === 32) {
372 // Pressing SPACE or ENTER will cause a pick
386 // Pressing SPACE or ENTER will cause a pick
373 event.stopPropagation();
387 event.stopPropagation();
374 event.preventDefault();
388 event.preventDefault();
375 pick();
389 pick();
376 } else if (code === 38 || code === 40) {
390 } else if (code === 38 || code === 40) {
377 // We don't want the document keydown handler to handle UP/DOWN,
391 // We don't want the document keydown handler to handle UP/DOWN,
378 // but we want the default action.
392 // but we want the default action.
379 event.stopPropagation();
393 event.stopPropagation();
380 } else if ((code>64 && code <=122)|| (code==8 && down)){
394 } else if ((code>64 && code <=122)|| (code==8 && down)||(code==9 && down)){
381 // issues with _-.. on chrome at least
395 // issues with _-.. on chrome at least
382 if(code != 8 && press)
396 if(code != 8 && press)
383 {
397 {
384 var newchar = String.fromCharCode(code);
398 var newchar = String.fromCharCode(code);
385 typed_characters=typed_characters+newchar;
399 typed_characters=typed_characters+newchar;
400 } else if (code == 9) {
401 fastForward = sharedStart(filterd)
402 ffsub = fastForward.substr(matched_text.length+typed_characters.length);
403 typed_characters=typed_characters+ffsub;
404 console.log("Fast forded by :"+ffsub);
405 event.stopPropagation();
406 event.preventDefault();
386 } else if (code == 8) {
407 } else if (code == 8) {
387 // 8 is backspace remove 1 char cancel if
408 // 8 is backspace remove 1 char cancel if
388 // user have erase everything, otherwise
409 // user have erase everything, otherwise
389 // decrease what we filter with
410 // decrease what we filter with
390 if (typed_characters.length <= 0)
411 if (typed_characters.length <= 0)
391 {
412 {
392 insert(matched_text)
413 insert(matched_text)
393 }
414 }
394 typed_characters=typed_characters.substr(0,typed_characters.length-1);
415 typed_characters=typed_characters.substr(0,typed_characters.length-1);
395 }
416 }
396 re = new RegExp("^"+"\%?"+matched_text+typed_characters,"");
417 re = new RegExp("^"+"\%?"+matched_text+typed_characters,"");
397 filterd= matches.filter(function(x){return re.test(x)});
418 filterd= matches.filter(function(x){return re.test(x)});
398 complete_with(filterd,matched_text+typed_characters);
419 complete_with(filterd,matched_text+typed_characters);
399 } else if(down){ // abort only on press
420 } else if(down){ // abort only on press
400 // abort with what the user have pressed until now
421 // abort with what the user have pressed until now
401 console.log('aborting with keycode : '+code);
422 console.log('aborting with keycode : '+code);
402 insert(matched_text+typed_characters);
423 insert(matched_text+typed_characters);
403 }
424 }
404 }
425 }
405 select.keydown(function (event) {
426 select.keydown(function (event) {
406 downandpress(event,1)
427 downandpress(event,1)
407 });
428 });
408 select.keypress(function (event) {
429 select.keypress(function (event) {
409 downandpress(event,0)
430 downandpress(event,0)
410 });
431 });
411 // Double click also causes a pick.
432 // Double click also causes a pick.
412 // and bind the last actions.
433 // and bind the last actions.
413 select.dblclick(pick);
434 select.dblclick(pick);
414 select.blur(close);
435 select.blur(close);
415 select.focus();
436 select.focus();
416 };
437 };
417
438
418 CodeCell.prototype.toggle_line_numbers = function () {
439 CodeCell.prototype.toggle_line_numbers = function () {
419 if (this.code_mirror.getOption('lineNumbers') == false) {
440 if (this.code_mirror.getOption('lineNumbers') == false) {
420 this.code_mirror.setOption('lineNumbers', true);
441 this.code_mirror.setOption('lineNumbers', true);
421 } else {
442 } else {
422 this.code_mirror.setOption('lineNumbers', false);
443 this.code_mirror.setOption('lineNumbers', false);
423 }
444 }
424 this.code_mirror.refresh();
445 this.code_mirror.refresh();
425 };
446 };
426
447
427 CodeCell.prototype.select = function () {
448 CodeCell.prototype.select = function () {
428 IPython.Cell.prototype.select.apply(this);
449 IPython.Cell.prototype.select.apply(this);
429 // Todo: this dance is needed because as of CodeMirror 2.12, focus is
450 // Todo: this dance is needed because as of CodeMirror 2.12, focus is
430 // not causing the cursor to blink if the editor is empty initially.
451 // not causing the cursor to blink if the editor is empty initially.
431 // While this seems to fix the issue, this should be fixed
452 // While this seems to fix the issue, this should be fixed
432 // in CodeMirror proper.
453 // in CodeMirror proper.
433 var s = this.code_mirror.getValue();
454 var s = this.code_mirror.getValue();
434 this.code_mirror.focus();
455 this.code_mirror.focus();
435 if (s === '') this.code_mirror.setValue('');
456 if (s === '') this.code_mirror.setValue('');
436 };
457 };
437
458
438
459
439 CodeCell.prototype.select_all = function () {
460 CodeCell.prototype.select_all = function () {
440 var start = {line: 0, ch: 0};
461 var start = {line: 0, ch: 0};
441 var nlines = this.code_mirror.lineCount();
462 var nlines = this.code_mirror.lineCount();
442 var last_line = this.code_mirror.getLine(nlines-1);
463 var last_line = this.code_mirror.getLine(nlines-1);
443 var end = {line: nlines-1, ch: last_line.length};
464 var end = {line: nlines-1, ch: last_line.length};
444 this.code_mirror.setSelection(start, end);
465 this.code_mirror.setSelection(start, end);
445 };
466 };
446
467
447
468
448 CodeCell.prototype.append_output = function (json) {
469 CodeCell.prototype.append_output = function (json) {
449 this.expand();
470 this.expand();
450 if (json.output_type === 'pyout') {
471 if (json.output_type === 'pyout') {
451 this.append_pyout(json);
472 this.append_pyout(json);
452 } else if (json.output_type === 'pyerr') {
473 } else if (json.output_type === 'pyerr') {
453 this.append_pyerr(json);
474 this.append_pyerr(json);
454 } else if (json.output_type === 'display_data') {
475 } else if (json.output_type === 'display_data') {
455 this.append_display_data(json);
476 this.append_display_data(json);
456 } else if (json.output_type === 'stream') {
477 } else if (json.output_type === 'stream') {
457 this.append_stream(json);
478 this.append_stream(json);
458 };
479 };
459 this.outputs.push(json);
480 this.outputs.push(json);
460 };
481 };
461
482
462
483
463 CodeCell.prototype.create_output_area = function () {
484 CodeCell.prototype.create_output_area = function () {
464 var oa = $("<div/>").addClass("hbox output_area");
485 var oa = $("<div/>").addClass("hbox output_area");
465 oa.append($('<div/>').addClass('prompt'));
486 oa.append($('<div/>').addClass('prompt'));
466 return oa;
487 return oa;
467 };
488 };
468
489
469
490
470 CodeCell.prototype.append_pyout = function (json) {
491 CodeCell.prototype.append_pyout = function (json) {
471 n = json.prompt_number || ' ';
492 n = json.prompt_number || ' ';
472 var toinsert = this.create_output_area();
493 var toinsert = this.create_output_area();
473 toinsert.find('div.prompt').addClass('output_prompt').html('Out[' + n + ']:');
494 toinsert.find('div.prompt').addClass('output_prompt').html('Out[' + n + ']:');
474 this.append_mime_type(json, toinsert);
495 this.append_mime_type(json, toinsert);
475 this.element.find('div.output').append(toinsert);
496 this.element.find('div.output').append(toinsert);
476 // If we just output latex, typeset it.
497 // If we just output latex, typeset it.
477 if ((json.latex !== undefined) || (json.html !== undefined)) {
498 if ((json.latex !== undefined) || (json.html !== undefined)) {
478 MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
499 MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
479 };
500 };
480 };
501 };
481
502
482
503
483 CodeCell.prototype.append_pyerr = function (json) {
504 CodeCell.prototype.append_pyerr = function (json) {
484 var tb = json.traceback;
505 var tb = json.traceback;
485 if (tb !== undefined && tb.length > 0) {
506 if (tb !== undefined && tb.length > 0) {
486 var s = '';
507 var s = '';
487 var len = tb.length;
508 var len = tb.length;
488 for (var i=0; i<len; i++) {
509 for (var i=0; i<len; i++) {
489 s = s + tb[i] + '\n';
510 s = s + tb[i] + '\n';
490 }
511 }
491 s = s + '\n';
512 s = s + '\n';
492 var toinsert = this.create_output_area();
513 var toinsert = this.create_output_area();
493 this.append_text(s, toinsert);
514 this.append_text(s, toinsert);
494 this.element.find('div.output').append(toinsert);
515 this.element.find('div.output').append(toinsert);
495 };
516 };
496 };
517 };
497
518
498
519
499 CodeCell.prototype.append_stream = function (json) {
520 CodeCell.prototype.append_stream = function (json) {
500 // temporary fix: if stream undefined (json file written prior to this patch),
521 // temporary fix: if stream undefined (json file written prior to this patch),
501 // default to most likely stdout:
522 // default to most likely stdout:
502 if (json.stream == undefined){
523 if (json.stream == undefined){
503 json.stream = 'stdout';
524 json.stream = 'stdout';
504 }
525 }
505 var subclass = "output_"+json.stream;
526 var subclass = "output_"+json.stream;
506 if (this.outputs.length > 0){
527 if (this.outputs.length > 0){
507 // have at least one output to consider
528 // have at least one output to consider
508 var last = this.outputs[this.outputs.length-1];
529 var last = this.outputs[this.outputs.length-1];
509 if (last.output_type == 'stream' && json.stream == last.stream){
530 if (last.output_type == 'stream' && json.stream == last.stream){
510 // latest output was in the same stream,
531 // latest output was in the same stream,
511 // so append directly into its pre tag
532 // so append directly into its pre tag
512 this.element.find('div.'+subclass).last().find('pre').append(json.text);
533 this.element.find('div.'+subclass).last().find('pre').append(json.text);
513 return;
534 return;
514 }
535 }
515 }
536 }
516
537
517 // If we got here, attach a new div
538 // If we got here, attach a new div
518 var toinsert = this.create_output_area();
539 var toinsert = this.create_output_area();
519 this.append_text(json.text, toinsert, "output_stream "+subclass);
540 this.append_text(json.text, toinsert, "output_stream "+subclass);
520 this.element.find('div.output').append(toinsert);
541 this.element.find('div.output').append(toinsert);
521 };
542 };
522
543
523
544
524 CodeCell.prototype.append_display_data = function (json) {
545 CodeCell.prototype.append_display_data = function (json) {
525 var toinsert = this.create_output_area();
546 var toinsert = this.create_output_area();
526 this.append_mime_type(json, toinsert);
547 this.append_mime_type(json, toinsert);
527 this.element.find('div.output').append(toinsert);
548 this.element.find('div.output').append(toinsert);
528 // If we just output latex, typeset it.
549 // If we just output latex, typeset it.
529 if ( (json.latex !== undefined) || (json.html !== undefined) ) {
550 if ( (json.latex !== undefined) || (json.html !== undefined) ) {
530 MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
551 MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
531 };
552 };
532 };
553 };
533
554
534
555
535 CodeCell.prototype.append_mime_type = function (json, element) {
556 CodeCell.prototype.append_mime_type = function (json, element) {
536 if (json.html !== undefined) {
557 if (json.html !== undefined) {
537 this.append_html(json.html, element);
558 this.append_html(json.html, element);
538 } else if (json.latex !== undefined) {
559 } else if (json.latex !== undefined) {
539 this.append_latex(json.latex, element);
560 this.append_latex(json.latex, element);
540 } else if (json.svg !== undefined) {
561 } else if (json.svg !== undefined) {
541 this.append_svg(json.svg, element);
562 this.append_svg(json.svg, element);
542 } else if (json.png !== undefined) {
563 } else if (json.png !== undefined) {
543 this.append_png(json.png, element);
564 this.append_png(json.png, element);
544 } else if (json.jpeg !== undefined) {
565 } else if (json.jpeg !== undefined) {
545 this.append_jpeg(json.jpeg, element);
566 this.append_jpeg(json.jpeg, element);
546 } else if (json.text !== undefined) {
567 } else if (json.text !== undefined) {
547 this.append_text(json.text, element);
568 this.append_text(json.text, element);
548 };
569 };
549 };
570 };
550
571
551
572
552 CodeCell.prototype.append_html = function (html, element) {
573 CodeCell.prototype.append_html = function (html, element) {
553 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_html rendered_html");
574 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_html rendered_html");
554 toinsert.append(html);
575 toinsert.append(html);
555 element.append(toinsert);
576 element.append(toinsert);
556 };
577 };
557
578
558
579
559 CodeCell.prototype.append_text = function (data, element, extra_class) {
580 CodeCell.prototype.append_text = function (data, element, extra_class) {
560 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_text");
581 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_text");
561 if (extra_class){
582 if (extra_class){
562 toinsert.addClass(extra_class);
583 toinsert.addClass(extra_class);
563 }
584 }
564 toinsert.append($("<pre/>").html(data));
585 toinsert.append($("<pre/>").html(data));
565 element.append(toinsert);
586 element.append(toinsert);
566 };
587 };
567
588
568
589
569 CodeCell.prototype.append_svg = function (svg, element) {
590 CodeCell.prototype.append_svg = function (svg, element) {
570 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_svg");
591 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_svg");
571 toinsert.append(svg);
592 toinsert.append(svg);
572 element.append(toinsert);
593 element.append(toinsert);
573 };
594 };
574
595
575
596
576 CodeCell.prototype.append_png = function (png, element) {
597 CodeCell.prototype.append_png = function (png, element) {
577 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_png");
598 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_png");
578 toinsert.append($("<img/>").attr('src','data:image/png;base64,'+png));
599 toinsert.append($("<img/>").attr('src','data:image/png;base64,'+png));
579 element.append(toinsert);
600 element.append(toinsert);
580 };
601 };
581
602
582
603
583 CodeCell.prototype.append_jpeg = function (jpeg, element) {
604 CodeCell.prototype.append_jpeg = function (jpeg, element) {
584 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_jpeg");
605 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_jpeg");
585 toinsert.append($("<img/>").attr('src','data:image/jpeg;base64,'+jpeg));
606 toinsert.append($("<img/>").attr('src','data:image/jpeg;base64,'+jpeg));
586 element.append(toinsert);
607 element.append(toinsert);
587 };
608 };
588
609
589
610
590 CodeCell.prototype.append_latex = function (latex, element) {
611 CodeCell.prototype.append_latex = function (latex, element) {
591 // This method cannot do the typesetting because the latex first has to
612 // This method cannot do the typesetting because the latex first has to
592 // be on the page.
613 // be on the page.
593 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_latex");
614 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_latex");
594 toinsert.append(latex);
615 toinsert.append(latex);
595 element.append(toinsert);
616 element.append(toinsert);
596 };
617 };
597
618
598
619
599 CodeCell.prototype.clear_output = function (stdout, stderr, other) {
620 CodeCell.prototype.clear_output = function (stdout, stderr, other) {
600 var output_div = this.element.find("div.output");
621 var output_div = this.element.find("div.output");
601 if (stdout && stderr && other){
622 if (stdout && stderr && other){
602 // clear all, no need for logic
623 // clear all, no need for logic
603 output_div.html("");
624 output_div.html("");
604 this.outputs = [];
625 this.outputs = [];
605 return;
626 return;
606 }
627 }
607 // remove html output
628 // remove html output
608 // each output_subarea that has an identifying class is in an output_area
629 // each output_subarea that has an identifying class is in an output_area
609 // which is the element to be removed.
630 // which is the element to be removed.
610 if (stdout){
631 if (stdout){
611 output_div.find("div.output_stdout").parent().remove();
632 output_div.find("div.output_stdout").parent().remove();
612 }
633 }
613 if (stderr){
634 if (stderr){
614 output_div.find("div.output_stderr").parent().remove();
635 output_div.find("div.output_stderr").parent().remove();
615 }
636 }
616 if (other){
637 if (other){
617 output_div.find("div.output_subarea").not("div.output_stderr").not("div.output_stdout").parent().remove();
638 output_div.find("div.output_subarea").not("div.output_stderr").not("div.output_stdout").parent().remove();
618 }
639 }
619
640
620 // remove cleared outputs from JSON list:
641 // remove cleared outputs from JSON list:
621 for (var i = this.outputs.length - 1; i >= 0; i--){
642 for (var i = this.outputs.length - 1; i >= 0; i--){
622 var out = this.outputs[i];
643 var out = this.outputs[i];
623 var output_type = out.output_type;
644 var output_type = out.output_type;
624 if (output_type == "display_data" && other){
645 if (output_type == "display_data" && other){
625 this.outputs.splice(i,1);
646 this.outputs.splice(i,1);
626 }else if (output_type == "stream"){
647 }else if (output_type == "stream"){
627 if (stdout && out.stream == "stdout"){
648 if (stdout && out.stream == "stdout"){
628 this.outputs.splice(i,1);
649 this.outputs.splice(i,1);
629 }else if (stderr && out.stream == "stderr"){
650 }else if (stderr && out.stream == "stderr"){
630 this.outputs.splice(i,1);
651 this.outputs.splice(i,1);
631 }
652 }
632 }
653 }
633 }
654 }
634 };
655 };
635
656
636
657
637 CodeCell.prototype.clear_input = function () {
658 CodeCell.prototype.clear_input = function () {
638 this.code_mirror.setValue('');
659 this.code_mirror.setValue('');
639 };
660 };
640
661
641
662
642 CodeCell.prototype.collapse = function () {
663 CodeCell.prototype.collapse = function () {
643 if (!this.collapsed) {
664 if (!this.collapsed) {
644 this.element.find('div.output').hide();
665 this.element.find('div.output').hide();
645 this.collapsed = true;
666 this.collapsed = true;
646 };
667 };
647 };
668 };
648
669
649
670
650 CodeCell.prototype.expand = function () {
671 CodeCell.prototype.expand = function () {
651 if (this.collapsed) {
672 if (this.collapsed) {
652 this.element.find('div.output').show();
673 this.element.find('div.output').show();
653 this.collapsed = false;
674 this.collapsed = false;
654 };
675 };
655 };
676 };
656
677
657
678
658 CodeCell.prototype.toggle_output = function () {
679 CodeCell.prototype.toggle_output = function () {
659 if (this.collapsed) {
680 if (this.collapsed) {
660 this.expand();
681 this.expand();
661 } else {
682 } else {
662 this.collapse();
683 this.collapse();
663 };
684 };
664 };
685 };
665
686
666 CodeCell.prototype.set_input_prompt = function (number) {
687 CodeCell.prototype.set_input_prompt = function (number) {
667 var n = number || '&nbsp;';
688 var n = number || '&nbsp;';
668 this.input_prompt_number = n;
689 this.input_prompt_number = n;
669 this.element.find('div.input_prompt').html('In&nbsp;[' + n + ']:');
690 this.element.find('div.input_prompt').html('In&nbsp;[' + n + ']:');
670 };
691 };
671
692
672
693
673 CodeCell.prototype.get_code = function () {
694 CodeCell.prototype.get_code = function () {
674 return this.code_mirror.getValue();
695 return this.code_mirror.getValue();
675 };
696 };
676
697
677
698
678 CodeCell.prototype.set_code = function (code) {
699 CodeCell.prototype.set_code = function (code) {
679 return this.code_mirror.setValue(code);
700 return this.code_mirror.setValue(code);
680 };
701 };
681
702
682
703
683 CodeCell.prototype.at_top = function () {
704 CodeCell.prototype.at_top = function () {
684 var cursor = this.code_mirror.getCursor();
705 var cursor = this.code_mirror.getCursor();
685 if (cursor.line === 0) {
706 if (cursor.line === 0) {
686 return true;
707 return true;
687 } else {
708 } else {
688 return false;
709 return false;
689 }
710 }
690 };
711 };
691
712
692
713
693 CodeCell.prototype.at_bottom = function () {
714 CodeCell.prototype.at_bottom = function () {
694 var cursor = this.code_mirror.getCursor();
715 var cursor = this.code_mirror.getCursor();
695 if (cursor.line === (this.code_mirror.lineCount()-1)) {
716 if (cursor.line === (this.code_mirror.lineCount()-1)) {
696 return true;
717 return true;
697 } else {
718 } else {
698 return false;
719 return false;
699 }
720 }
700 };
721 };
701
722
702
723
703 CodeCell.prototype.fromJSON = function (data) {
724 CodeCell.prototype.fromJSON = function (data) {
704 console.log('Import from JSON:', data);
725 console.log('Import from JSON:', data);
705 if (data.cell_type === 'code') {
726 if (data.cell_type === 'code') {
706 if (data.input !== undefined) {
727 if (data.input !== undefined) {
707 this.set_code(data.input);
728 this.set_code(data.input);
708 }
729 }
709 if (data.prompt_number !== undefined) {
730 if (data.prompt_number !== undefined) {
710 this.set_input_prompt(data.prompt_number);
731 this.set_input_prompt(data.prompt_number);
711 } else {
732 } else {
712 this.set_input_prompt();
733 this.set_input_prompt();
713 };
734 };
714 var len = data.outputs.length;
735 var len = data.outputs.length;
715 for (var i=0; i<len; i++) {
736 for (var i=0; i<len; i++) {
716 this.append_output(data.outputs[i]);
737 this.append_output(data.outputs[i]);
717 };
738 };
718 if (data.collapsed !== undefined) {
739 if (data.collapsed !== undefined) {
719 if (data.collapsed) {
740 if (data.collapsed) {
720 this.collapse();
741 this.collapse();
721 };
742 };
722 };
743 };
723 };
744 };
724 };
745 };
725
746
726
747
727 CodeCell.prototype.toJSON = function () {
748 CodeCell.prototype.toJSON = function () {
728 var data = {};
749 var data = {};
729 data.input = this.get_code();
750 data.input = this.get_code();
730 data.cell_type = 'code';
751 data.cell_type = 'code';
731 if (this.input_prompt_number !== ' ') {
752 if (this.input_prompt_number !== ' ') {
732 data.prompt_number = this.input_prompt_number;
753 data.prompt_number = this.input_prompt_number;
733 };
754 };
734 var outputs = [];
755 var outputs = [];
735 var len = this.outputs.length;
756 var len = this.outputs.length;
736 for (var i=0; i<len; i++) {
757 for (var i=0; i<len; i++) {
737 outputs[i] = this.outputs[i];
758 outputs[i] = this.outputs[i];
738 };
759 };
739 data.outputs = outputs;
760 data.outputs = outputs;
740 data.language = 'python';
761 data.language = 'python';
741 data.collapsed = this.collapsed;
762 data.collapsed = this.collapsed;
742 // console.log('Export to JSON:',data);
763 // console.log('Export to JSON:',data);
743 return data;
764 return data;
744 };
765 };
745
766
746
767
747 IPython.CodeCell = CodeCell;
768 IPython.CodeCell = CodeCell;
748
769
749 return IPython;
770 return IPython;
750 }(IPython));
771 }(IPython));
General Comments 0
You need to be logged in to leave comments. Login now