##// END OF EJS Templates
multiple tooltip action...
Matthias BUSSONNIER -
Show More
@@ -1,552 +1,532
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 "use strict";
13 "use strict";
14
14
15 var utils = IPython.utils;
15 var utils = IPython.utils;
16 var key = IPython.utils.keycodes;
16 var key = IPython.utils.keycodes;
17
17
18 var CodeCell = function (notebook) {
18 var CodeCell = function (notebook) {
19 this.code_mirror = null;
19 this.code_mirror = null;
20 this.input_prompt_number = null;
20 this.input_prompt_number = null;
21 this.outputs = [];
21 this.outputs = [];
22 this.collapsed = false;
22 this.collapsed = false;
23 this.tooltip_timeout = null;
24 this.clear_out_timeout = null;
23 this.clear_out_timeout = null;
25 IPython.Cell.apply(this, arguments);
24 IPython.Cell.apply(this, arguments);
26 };
25 };
27
26
28
27
29 CodeCell.prototype = new IPython.Cell();
28 CodeCell.prototype = new IPython.Cell();
30
29
31
30
32 CodeCell.prototype.create_element = function () {
31 CodeCell.prototype.create_element = function () {
33 var cell = $('<div></div>').addClass('cell border-box-sizing code_cell vbox');
32 var cell = $('<div></div>').addClass('cell border-box-sizing code_cell vbox');
34 cell.attr('tabindex','2');
33 cell.attr('tabindex','2');
35 var input = $('<div></div>').addClass('input hbox');
34 var input = $('<div></div>').addClass('input hbox');
36 input.append($('<div/>').addClass('prompt input_prompt'));
35 input.append($('<div/>').addClass('prompt input_prompt'));
37 var input_area = $('<div/>').addClass('input_area box-flex1');
36 var input_area = $('<div/>').addClass('input_area box-flex1');
38 this.code_mirror = CodeMirror(input_area.get(0), {
37 this.code_mirror = CodeMirror(input_area.get(0), {
39 indentUnit : 4,
38 indentUnit : 4,
40 mode: 'python',
39 mode: 'python',
41 theme: 'ipython',
40 theme: 'ipython',
42 readOnly: this.read_only,
41 readOnly: this.read_only,
43 onKeyEvent: $.proxy(this.handle_codemirror_keyevent,this)
42 onKeyEvent: $.proxy(this.handle_codemirror_keyevent,this)
44 });
43 });
45 input.append(input_area);
44 input.append(input_area);
46 var output = $('<div></div>').addClass('output vbox');
45 var output = $('<div></div>').addClass('output vbox');
47 cell.append(input).append(output);
46 cell.append(input).append(output);
48 this.element = cell;
47 this.element = cell;
49 this.collapse();
48 this.collapse();
50
49
51 // construct a completer
50 // construct a completer
52 this.completer = new IPython.Completer(this);
51 this.completer = new IPython.Completer(this);
53 };
52 };
54
53
55 //TODO, try to diminish the number of parameters.
56 CodeCell.prototype.request_tooltip_after_time = function (pre_cursor,time){
57 var that = this;
58 if (pre_cursor === "" || pre_cursor === "(" ) {
59 // don't do anything if line beggin with '(' or is empty
60 } else {
61 if(time ==0)
62 { IPython.tooltip.request(that, pre_cursor) }
63 else
64 { IPython.tooltip.pending(that, pre_cursor) }
65 }
66 };
67
68 CodeCell.prototype.handle_codemirror_keyevent = function (editor, event) {
54 CodeCell.prototype.handle_codemirror_keyevent = function (editor, event) {
69 // This method gets called in CodeMirror's onKeyDown/onKeyPress
55 // This method gets called in CodeMirror's onKeyDown/onKeyPress
70 // handlers and is used to provide custom key handling. Its return
56 // handlers and is used to provide custom key handling. Its return
71 // value is used to determine if CodeMirror should ignore the event:
57 // value is used to determine if CodeMirror should ignore the event:
72 // true = ignore, false = don't ignore.
58 // true = ignore, false = don't ignore.
73
59
74 if (this.read_only){
60 if (this.read_only){
75 return false;
61 return false;
76 }
62 }
77
63
78 // note that we are comparing and setting the time to wait at each key press.
79 // a better way might be to generate a new function on each time change and
80 // assign it to CodeCell.prototype.request_tooltip_after_time
81 var tooltip_wait_time = this.notebook.time_before_tooltip;
82 var tooltip_on_tab = this.notebook.tooltip_on_tab;
64 var tooltip_on_tab = this.notebook.tooltip_on_tab;
83 var that = this;
65 var that = this;
84 // whatever key is pressed, first, cancel the tooltip request before
66 // whatever key is pressed, first, cancel the tooltip request before
85 // they are sent, and remove tooltip if any
67 // they are sent, and remove tooltip if any, except for tab again
86 if(event.type === 'keydown' ) {
68 if(event.type === 'keydown' && event.which != key.tab ) {
87 IPython.tooltip.remove_and_cancel_tooltip();
69 IPython.tooltip.remove_and_cancel_tooltip();
88 };
70 };
89
71
90
72
91 if (event.keyCode === key.enter && (event.shiftKey || event.ctrlKey)) {
73 if (event.keyCode === key.enter && (event.shiftKey || event.ctrlKey)) {
92 // Always ignore shift-enter in CodeMirror as we handle it.
74 // Always ignore shift-enter in CodeMirror as we handle it.
93 return true;
75 return true;
94 } else if (event.which === 40 && event.type === 'keypress' && tooltip_wait_time >= 0) {
76 } else if (event.which === 40 && event.type === 'keypress' && this.notebook.time_before_tooltip >= 0) {
95 // triger aon keypress (!) otherwise inconsistent event.which depending on plateform
77 // triger on keypress (!) otherwise inconsistent event.which depending on plateform
96 // browser and keyboard layout !
78 // browser and keyboard layout !
97 // Pressing '(' , request tooltip, don't forget to reappend it
79 // Pressing '(' , request tooltip, don't forget to reappend it
98 var cursor = editor.getCursor();
80 IPython.tooltip.pending(that);
99 var pre_cursor = editor.getRange({line:cursor.line,ch:0},cursor).trim()+'(';
100 that.request_tooltip_after_time(pre_cursor,tooltip_wait_time);
101 } else if (event.which === key.upArrow) {
81 } else if (event.which === key.upArrow) {
102 // If we are not at the top, let CM handle the up arrow and
82 // If we are not at the top, let CM handle the up arrow and
103 // prevent the global keydown handler from handling it.
83 // prevent the global keydown handler from handling it.
104 if (!that.at_top()) {
84 if (!that.at_top()) {
105 event.stop();
85 event.stop();
106 return false;
86 return false;
107 } else {
87 } else {
108 return true;
88 return true;
109 };
89 };
110 } else if (event.which === key.downArrow) {
90 } else if (event.which === key.downArrow) {
111 // If we are not at the bottom, let CM handle the down arrow and
91 // If we are not at the bottom, let CM handle the down arrow and
112 // prevent the global keydown handler from handling it.
92 // prevent the global keydown handler from handling it.
113 if (!that.at_bottom()) {
93 if (!that.at_bottom()) {
114 event.stop();
94 event.stop();
115 return false;
95 return false;
116 } else {
96 } else {
117 return true;
97 return true;
118 };
98 };
119 } else if (event.keyCode === key.tab && event.type == 'keydown') {
99 } else if (event.keyCode === key.tab && event.type == 'keydown') {
120 // Tab completion.
100 // Tab completion.
121 var cur = editor.getCursor();
101 var cur = editor.getCursor();
122 //Do not trim here because of tooltip
102 //Do not trim here because of tooltip
123 var pre_cursor = editor.getRange({line:cur.line,ch:0},cur);
103 var pre_cursor = editor.getRange({line:cur.line,ch:0},cur);
124 if (pre_cursor.trim() === "") {
104 if (pre_cursor.trim() === "") {
125 // Don't autocomplete if the part of the line before the cursor
105 // Don't autocomplete if the part of the line before the cursor
126 // is empty. In this case, let CodeMirror handle indentation.
106 // is empty. In this case, let CodeMirror handle indentation.
127 return false;
107 return false;
128 } else if ((pre_cursor.substr(-1) === "("|| pre_cursor.substr(-1) === " ") && tooltip_on_tab ) {
108 } else if ((pre_cursor.substr(-1) === "("|| pre_cursor.substr(-1) === " ") && tooltip_on_tab ) {
129 that.request_tooltip_after_time(pre_cursor,0);
109 IPython.tooltip.request(that);
130 // Prevent the event from bubbling up.
110 // Prevent the event from bubbling up.
131 event.stop();
111 event.stop();
132 // Prevent CodeMirror from handling the tab.
112 // Prevent CodeMirror from handling the tab.
133 return true;
113 return true;
134 } else {
114 } else {
135 event.stop();
115 event.stop();
136 this.completer.startCompletion();
116 this.completer.startCompletion();
137 return true;
117 return true;
138 };
118 };
139 } else if (event.keyCode === key.backspace && event.type == 'keydown') {
119 } else if (event.keyCode === key.backspace && event.type == 'keydown') {
140 // If backspace and the line ends with 4 spaces, remove them.
120 // If backspace and the line ends with 4 spaces, remove them.
141 var cur = editor.getCursor();
121 var cur = editor.getCursor();
142 var line = editor.getLine(cur.line);
122 var line = editor.getLine(cur.line);
143 var ending = line.slice(-4);
123 var ending = line.slice(-4);
144 if (ending === ' ') {
124 if (ending === ' ') {
145 editor.replaceRange('',
125 editor.replaceRange('',
146 {line: cur.line, ch: cur.ch-4},
126 {line: cur.line, ch: cur.ch-4},
147 {line: cur.line, ch: cur.ch}
127 {line: cur.line, ch: cur.ch}
148 );
128 );
149 event.stop();
129 event.stop();
150 return true;
130 return true;
151 } else {
131 } else {
152 return false;
132 return false;
153 };
133 };
154 } else {
134 } else {
155 // keypress/keyup also trigger on TAB press, and we don't want to
135 // keypress/keyup also trigger on TAB press, and we don't want to
156 // use those to disable tab completion.
136 // use those to disable tab completion.
157 return false;
137 return false;
158 };
138 };
159 return false;
139 return false;
160 };
140 };
161
141
162 CodeCell.prototype.finish_tooltip = function (reply) {
142 CodeCell.prototype.finish_tooltip = function (reply) {
163 IPython.tooltip.show(reply, this);
143 IPython.tooltip.show(reply, this);
164 };
144 };
165
145
166
146
167 // called when completion came back from the kernel. just forward
147 // called when completion came back from the kernel. just forward
168 CodeCell.prototype.finish_completing = function (matched_text, matches) {
148 CodeCell.prototype.finish_completing = function (matched_text, matches) {
169 this.completer.finish_completing(matched_text,matches);
149 this.completer.finish_completing(matched_text,matches);
170 }
150 }
171
151
172
152
173 CodeCell.prototype.select = function () {
153 CodeCell.prototype.select = function () {
174 IPython.Cell.prototype.select.apply(this);
154 IPython.Cell.prototype.select.apply(this);
175 this.code_mirror.refresh();
155 this.code_mirror.refresh();
176 this.code_mirror.focus();
156 this.code_mirror.focus();
177 // We used to need an additional refresh() after the focus, but
157 // We used to need an additional refresh() after the focus, but
178 // it appears that this has been fixed in CM. This bug would show
158 // it appears that this has been fixed in CM. This bug would show
179 // up on FF when a newly loaded markdown cell was edited.
159 // up on FF when a newly loaded markdown cell was edited.
180 };
160 };
181
161
182
162
183 CodeCell.prototype.select_all = function () {
163 CodeCell.prototype.select_all = function () {
184 var start = {line: 0, ch: 0};
164 var start = {line: 0, ch: 0};
185 var nlines = this.code_mirror.lineCount();
165 var nlines = this.code_mirror.lineCount();
186 var last_line = this.code_mirror.getLine(nlines-1);
166 var last_line = this.code_mirror.getLine(nlines-1);
187 var end = {line: nlines-1, ch: last_line.length};
167 var end = {line: nlines-1, ch: last_line.length};
188 this.code_mirror.setSelection(start, end);
168 this.code_mirror.setSelection(start, end);
189 };
169 };
190
170
191
171
192 CodeCell.prototype.append_output = function (json, dynamic) {
172 CodeCell.prototype.append_output = function (json, dynamic) {
193 // If dynamic is true, javascript output will be eval'd.
173 // If dynamic is true, javascript output will be eval'd.
194 this.expand();
174 this.expand();
195 this.flush_clear_timeout();
175 this.flush_clear_timeout();
196 if (json.output_type === 'pyout') {
176 if (json.output_type === 'pyout') {
197 this.append_pyout(json, dynamic);
177 this.append_pyout(json, dynamic);
198 } else if (json.output_type === 'pyerr') {
178 } else if (json.output_type === 'pyerr') {
199 this.append_pyerr(json);
179 this.append_pyerr(json);
200 } else if (json.output_type === 'display_data') {
180 } else if (json.output_type === 'display_data') {
201 this.append_display_data(json, dynamic);
181 this.append_display_data(json, dynamic);
202 } else if (json.output_type === 'stream') {
182 } else if (json.output_type === 'stream') {
203 this.append_stream(json);
183 this.append_stream(json);
204 };
184 };
205 this.outputs.push(json);
185 this.outputs.push(json);
206 };
186 };
207
187
208
188
209 CodeCell.prototype.create_output_area = function () {
189 CodeCell.prototype.create_output_area = function () {
210 var oa = $("<div/>").addClass("hbox output_area");
190 var oa = $("<div/>").addClass("hbox output_area");
211 oa.append($('<div/>').addClass('prompt'));
191 oa.append($('<div/>').addClass('prompt'));
212 return oa;
192 return oa;
213 };
193 };
214
194
215
195
216 CodeCell.prototype.append_pyout = function (json, dynamic) {
196 CodeCell.prototype.append_pyout = function (json, dynamic) {
217 var n = json.prompt_number || ' ';
197 var n = json.prompt_number || ' ';
218 var toinsert = this.create_output_area();
198 var toinsert = this.create_output_area();
219 toinsert.find('div.prompt').addClass('output_prompt').html('Out[' + n + ']:');
199 toinsert.find('div.prompt').addClass('output_prompt').html('Out[' + n + ']:');
220 this.append_mime_type(json, toinsert, dynamic);
200 this.append_mime_type(json, toinsert, dynamic);
221 this.element.find('div.output').append(toinsert);
201 this.element.find('div.output').append(toinsert);
222 // If we just output latex, typeset it.
202 // If we just output latex, typeset it.
223 if ((json.latex !== undefined) || (json.html !== undefined)) {
203 if ((json.latex !== undefined) || (json.html !== undefined)) {
224 this.typeset();
204 this.typeset();
225 };
205 };
226 };
206 };
227
207
228
208
229 CodeCell.prototype.append_pyerr = function (json) {
209 CodeCell.prototype.append_pyerr = function (json) {
230 var tb = json.traceback;
210 var tb = json.traceback;
231 if (tb !== undefined && tb.length > 0) {
211 if (tb !== undefined && tb.length > 0) {
232 var s = '';
212 var s = '';
233 var len = tb.length;
213 var len = tb.length;
234 for (var i=0; i<len; i++) {
214 for (var i=0; i<len; i++) {
235 s = s + tb[i] + '\n';
215 s = s + tb[i] + '\n';
236 }
216 }
237 s = s + '\n';
217 s = s + '\n';
238 var toinsert = this.create_output_area();
218 var toinsert = this.create_output_area();
239 this.append_text(s, toinsert);
219 this.append_text(s, toinsert);
240 this.element.find('div.output').append(toinsert);
220 this.element.find('div.output').append(toinsert);
241 };
221 };
242 };
222 };
243
223
244
224
245 CodeCell.prototype.append_stream = function (json) {
225 CodeCell.prototype.append_stream = function (json) {
246 // temporary fix: if stream undefined (json file written prior to this patch),
226 // temporary fix: if stream undefined (json file written prior to this patch),
247 // default to most likely stdout:
227 // default to most likely stdout:
248 if (json.stream == undefined){
228 if (json.stream == undefined){
249 json.stream = 'stdout';
229 json.stream = 'stdout';
250 }
230 }
251 if (!utils.fixConsole(json.text)){
231 if (!utils.fixConsole(json.text)){
252 // fixConsole gives nothing (empty string, \r, etc.)
232 // fixConsole gives nothing (empty string, \r, etc.)
253 // so don't append any elements, which might add undesirable space
233 // so don't append any elements, which might add undesirable space
254 return;
234 return;
255 }
235 }
256 var subclass = "output_"+json.stream;
236 var subclass = "output_"+json.stream;
257 if (this.outputs.length > 0){
237 if (this.outputs.length > 0){
258 // have at least one output to consider
238 // have at least one output to consider
259 var last = this.outputs[this.outputs.length-1];
239 var last = this.outputs[this.outputs.length-1];
260 if (last.output_type == 'stream' && json.stream == last.stream){
240 if (last.output_type == 'stream' && json.stream == last.stream){
261 // latest output was in the same stream,
241 // latest output was in the same stream,
262 // so append directly into its pre tag
242 // so append directly into its pre tag
263 // escape ANSI & HTML specials:
243 // escape ANSI & HTML specials:
264 var text = utils.fixConsole(json.text);
244 var text = utils.fixConsole(json.text);
265 this.element.find('div.'+subclass).last().find('pre').append(text);
245 this.element.find('div.'+subclass).last().find('pre').append(text);
266 return;
246 return;
267 }
247 }
268 }
248 }
269
249
270 // If we got here, attach a new div
250 // If we got here, attach a new div
271 var toinsert = this.create_output_area();
251 var toinsert = this.create_output_area();
272 this.append_text(json.text, toinsert, "output_stream "+subclass);
252 this.append_text(json.text, toinsert, "output_stream "+subclass);
273 this.element.find('div.output').append(toinsert);
253 this.element.find('div.output').append(toinsert);
274 };
254 };
275
255
276
256
277 CodeCell.prototype.append_display_data = function (json, dynamic) {
257 CodeCell.prototype.append_display_data = function (json, dynamic) {
278 var toinsert = this.create_output_area();
258 var toinsert = this.create_output_area();
279 this.append_mime_type(json, toinsert, dynamic);
259 this.append_mime_type(json, toinsert, dynamic);
280 this.element.find('div.output').append(toinsert);
260 this.element.find('div.output').append(toinsert);
281 // If we just output latex, typeset it.
261 // If we just output latex, typeset it.
282 if ( (json.latex !== undefined) || (json.html !== undefined) ) {
262 if ( (json.latex !== undefined) || (json.html !== undefined) ) {
283 this.typeset();
263 this.typeset();
284 };
264 };
285 };
265 };
286
266
287
267
288 CodeCell.prototype.append_mime_type = function (json, element, dynamic) {
268 CodeCell.prototype.append_mime_type = function (json, element, dynamic) {
289 if (json.javascript !== undefined && dynamic) {
269 if (json.javascript !== undefined && dynamic) {
290 this.append_javascript(json.javascript, element, dynamic);
270 this.append_javascript(json.javascript, element, dynamic);
291 } else if (json.html !== undefined) {
271 } else if (json.html !== undefined) {
292 this.append_html(json.html, element);
272 this.append_html(json.html, element);
293 } else if (json.latex !== undefined) {
273 } else if (json.latex !== undefined) {
294 this.append_latex(json.latex, element);
274 this.append_latex(json.latex, element);
295 } else if (json.svg !== undefined) {
275 } else if (json.svg !== undefined) {
296 this.append_svg(json.svg, element);
276 this.append_svg(json.svg, element);
297 } else if (json.png !== undefined) {
277 } else if (json.png !== undefined) {
298 this.append_png(json.png, element);
278 this.append_png(json.png, element);
299 } else if (json.jpeg !== undefined) {
279 } else if (json.jpeg !== undefined) {
300 this.append_jpeg(json.jpeg, element);
280 this.append_jpeg(json.jpeg, element);
301 } else if (json.text !== undefined) {
281 } else if (json.text !== undefined) {
302 this.append_text(json.text, element);
282 this.append_text(json.text, element);
303 };
283 };
304 };
284 };
305
285
306
286
307 CodeCell.prototype.append_html = function (html, element) {
287 CodeCell.prototype.append_html = function (html, element) {
308 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_html rendered_html");
288 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_html rendered_html");
309 toinsert.append(html);
289 toinsert.append(html);
310 element.append(toinsert);
290 element.append(toinsert);
311 };
291 };
312
292
313
293
314 CodeCell.prototype.append_javascript = function (js, container) {
294 CodeCell.prototype.append_javascript = function (js, container) {
315 // We just eval the JS code, element appears in the local scope.
295 // We just eval the JS code, element appears in the local scope.
316 var element = $("<div/>").addClass("box_flex1 output_subarea");
296 var element = $("<div/>").addClass("box_flex1 output_subarea");
317 container.append(element);
297 container.append(element);
318 // Div for js shouldn't be drawn, as it will add empty height to the area.
298 // Div for js shouldn't be drawn, as it will add empty height to the area.
319 container.hide();
299 container.hide();
320 // If the Javascript appends content to `element` that should be drawn, then
300 // If the Javascript appends content to `element` that should be drawn, then
321 // it must also call `container.show()`.
301 // it must also call `container.show()`.
322 eval(js);
302 eval(js);
323 }
303 }
324
304
325
305
326 CodeCell.prototype.append_text = function (data, element, extra_class) {
306 CodeCell.prototype.append_text = function (data, element, extra_class) {
327 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_text");
307 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_text");
328 // escape ANSI & HTML specials in plaintext:
308 // escape ANSI & HTML specials in plaintext:
329 data = utils.fixConsole(data);
309 data = utils.fixConsole(data);
330 if (extra_class){
310 if (extra_class){
331 toinsert.addClass(extra_class);
311 toinsert.addClass(extra_class);
332 }
312 }
333 toinsert.append($("<pre/>").html(data));
313 toinsert.append($("<pre/>").html(data));
334 element.append(toinsert);
314 element.append(toinsert);
335 };
315 };
336
316
337
317
338 CodeCell.prototype.append_svg = function (svg, element) {
318 CodeCell.prototype.append_svg = function (svg, element) {
339 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_svg");
319 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_svg");
340 toinsert.append(svg);
320 toinsert.append(svg);
341 element.append(toinsert);
321 element.append(toinsert);
342 };
322 };
343
323
344
324
345 CodeCell.prototype.append_png = function (png, element) {
325 CodeCell.prototype.append_png = function (png, element) {
346 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_png");
326 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_png");
347 toinsert.append($("<img/>").attr('src','data:image/png;base64,'+png));
327 toinsert.append($("<img/>").attr('src','data:image/png;base64,'+png));
348 element.append(toinsert);
328 element.append(toinsert);
349 };
329 };
350
330
351
331
352 CodeCell.prototype.append_jpeg = function (jpeg, element) {
332 CodeCell.prototype.append_jpeg = function (jpeg, element) {
353 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_jpeg");
333 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_jpeg");
354 toinsert.append($("<img/>").attr('src','data:image/jpeg;base64,'+jpeg));
334 toinsert.append($("<img/>").attr('src','data:image/jpeg;base64,'+jpeg));
355 element.append(toinsert);
335 element.append(toinsert);
356 };
336 };
357
337
358
338
359 CodeCell.prototype.append_latex = function (latex, element) {
339 CodeCell.prototype.append_latex = function (latex, element) {
360 // This method cannot do the typesetting because the latex first has to
340 // This method cannot do the typesetting because the latex first has to
361 // be on the page.
341 // be on the page.
362 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_latex");
342 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_latex");
363 toinsert.append(latex);
343 toinsert.append(latex);
364 element.append(toinsert);
344 element.append(toinsert);
365 };
345 };
366
346
367
347
368 CodeCell.prototype.clear_output = function (stdout, stderr, other) {
348 CodeCell.prototype.clear_output = function (stdout, stderr, other) {
369 var that = this;
349 var that = this;
370 if (this.clear_out_timeout != null){
350 if (this.clear_out_timeout != null){
371 // fire previous pending clear *immediately*
351 // fire previous pending clear *immediately*
372 clearTimeout(this.clear_out_timeout);
352 clearTimeout(this.clear_out_timeout);
373 this.clear_out_timeout = null;
353 this.clear_out_timeout = null;
374 this.clear_output_callback(this._clear_stdout, this._clear_stderr, this._clear_other);
354 this.clear_output_callback(this._clear_stdout, this._clear_stderr, this._clear_other);
375 }
355 }
376 // store flags for flushing the timeout
356 // store flags for flushing the timeout
377 this._clear_stdout = stdout;
357 this._clear_stdout = stdout;
378 this._clear_stderr = stderr;
358 this._clear_stderr = stderr;
379 this._clear_other = other;
359 this._clear_other = other;
380 this.clear_out_timeout = setTimeout(function(){
360 this.clear_out_timeout = setTimeout(function(){
381 // really clear timeout only after a short delay
361 // really clear timeout only after a short delay
382 // this reduces flicker in 'clear_output; print' cases
362 // this reduces flicker in 'clear_output; print' cases
383 that.clear_out_timeout = null;
363 that.clear_out_timeout = null;
384 that._clear_stdout = that._clear_stderr = that._clear_other = null;
364 that._clear_stdout = that._clear_stderr = that._clear_other = null;
385 that.clear_output_callback(stdout, stderr, other);
365 that.clear_output_callback(stdout, stderr, other);
386 }, 500
366 }, 500
387 );
367 );
388 };
368 };
389
369
390 CodeCell.prototype.clear_output_callback = function (stdout, stderr, other) {
370 CodeCell.prototype.clear_output_callback = function (stdout, stderr, other) {
391 var output_div = this.element.find("div.output");
371 var output_div = this.element.find("div.output");
392
372
393 if (stdout && stderr && other){
373 if (stdout && stderr && other){
394 // clear all, no need for logic
374 // clear all, no need for logic
395 output_div.html("");
375 output_div.html("");
396 this.outputs = [];
376 this.outputs = [];
397 return;
377 return;
398 }
378 }
399 // remove html output
379 // remove html output
400 // each output_subarea that has an identifying class is in an output_area
380 // each output_subarea that has an identifying class is in an output_area
401 // which is the element to be removed.
381 // which is the element to be removed.
402 if (stdout){
382 if (stdout){
403 output_div.find("div.output_stdout").parent().remove();
383 output_div.find("div.output_stdout").parent().remove();
404 }
384 }
405 if (stderr){
385 if (stderr){
406 output_div.find("div.output_stderr").parent().remove();
386 output_div.find("div.output_stderr").parent().remove();
407 }
387 }
408 if (other){
388 if (other){
409 output_div.find("div.output_subarea").not("div.output_stderr").not("div.output_stdout").parent().remove();
389 output_div.find("div.output_subarea").not("div.output_stderr").not("div.output_stdout").parent().remove();
410 }
390 }
411
391
412 // remove cleared outputs from JSON list:
392 // remove cleared outputs from JSON list:
413 for (var i = this.outputs.length - 1; i >= 0; i--){
393 for (var i = this.outputs.length - 1; i >= 0; i--){
414 var out = this.outputs[i];
394 var out = this.outputs[i];
415 var output_type = out.output_type;
395 var output_type = out.output_type;
416 if (output_type == "display_data" && other){
396 if (output_type == "display_data" && other){
417 this.outputs.splice(i,1);
397 this.outputs.splice(i,1);
418 }else if (output_type == "stream"){
398 }else if (output_type == "stream"){
419 if (stdout && out.stream == "stdout"){
399 if (stdout && out.stream == "stdout"){
420 this.outputs.splice(i,1);
400 this.outputs.splice(i,1);
421 }else if (stderr && out.stream == "stderr"){
401 }else if (stderr && out.stream == "stderr"){
422 this.outputs.splice(i,1);
402 this.outputs.splice(i,1);
423 }
403 }
424 }
404 }
425 }
405 }
426 };
406 };
427
407
428
408
429 CodeCell.prototype.clear_input = function () {
409 CodeCell.prototype.clear_input = function () {
430 this.code_mirror.setValue('');
410 this.code_mirror.setValue('');
431 };
411 };
432
412
433 CodeCell.prototype.flush_clear_timeout = function() {
413 CodeCell.prototype.flush_clear_timeout = function() {
434 var output_div = this.element.find('div.output');
414 var output_div = this.element.find('div.output');
435 if (this.clear_out_timeout){
415 if (this.clear_out_timeout){
436 clearTimeout(this.clear_out_timeout);
416 clearTimeout(this.clear_out_timeout);
437 this.clear_out_timeout = null;
417 this.clear_out_timeout = null;
438 this.clear_output_callback(this._clear_stdout, this._clear_stderr, this._clear_other);
418 this.clear_output_callback(this._clear_stdout, this._clear_stderr, this._clear_other);
439 };
419 };
440 }
420 }
441
421
442
422
443 CodeCell.prototype.collapse = function () {
423 CodeCell.prototype.collapse = function () {
444 if (!this.collapsed) {
424 if (!this.collapsed) {
445 this.element.find('div.output').hide();
425 this.element.find('div.output').hide();
446 this.collapsed = true;
426 this.collapsed = true;
447 };
427 };
448 };
428 };
449
429
450
430
451 CodeCell.prototype.expand = function () {
431 CodeCell.prototype.expand = function () {
452 if (this.collapsed) {
432 if (this.collapsed) {
453 this.element.find('div.output').show();
433 this.element.find('div.output').show();
454 this.collapsed = false;
434 this.collapsed = false;
455 };
435 };
456 };
436 };
457
437
458
438
459 CodeCell.prototype.toggle_output = function () {
439 CodeCell.prototype.toggle_output = function () {
460 if (this.collapsed) {
440 if (this.collapsed) {
461 this.expand();
441 this.expand();
462 } else {
442 } else {
463 this.collapse();
443 this.collapse();
464 };
444 };
465 };
445 };
466
446
467 CodeCell.prototype.set_input_prompt = function (number) {
447 CodeCell.prototype.set_input_prompt = function (number) {
468 this.input_prompt_number = number;
448 this.input_prompt_number = number;
469 var ns = number || "&nbsp;";
449 var ns = number || "&nbsp;";
470 this.element.find('div.input_prompt').html('In&nbsp;[' + ns + ']:');
450 this.element.find('div.input_prompt').html('In&nbsp;[' + ns + ']:');
471 };
451 };
472
452
473
453
474 CodeCell.prototype.get_text = function () {
454 CodeCell.prototype.get_text = function () {
475 return this.code_mirror.getValue();
455 return this.code_mirror.getValue();
476 };
456 };
477
457
478
458
479 CodeCell.prototype.set_text = function (code) {
459 CodeCell.prototype.set_text = function (code) {
480 return this.code_mirror.setValue(code);
460 return this.code_mirror.setValue(code);
481 };
461 };
482
462
483
463
484 CodeCell.prototype.at_top = function () {
464 CodeCell.prototype.at_top = function () {
485 var cursor = this.code_mirror.getCursor();
465 var cursor = this.code_mirror.getCursor();
486 if (cursor.line === 0) {
466 if (cursor.line === 0) {
487 return true;
467 return true;
488 } else {
468 } else {
489 return false;
469 return false;
490 }
470 }
491 };
471 };
492
472
493
473
494 CodeCell.prototype.at_bottom = function () {
474 CodeCell.prototype.at_bottom = function () {
495 var cursor = this.code_mirror.getCursor();
475 var cursor = this.code_mirror.getCursor();
496 if (cursor.line === (this.code_mirror.lineCount()-1)) {
476 if (cursor.line === (this.code_mirror.lineCount()-1)) {
497 return true;
477 return true;
498 } else {
478 } else {
499 return false;
479 return false;
500 }
480 }
501 };
481 };
502
482
503
483
504 CodeCell.prototype.fromJSON = function (data) {
484 CodeCell.prototype.fromJSON = function (data) {
505 if (data.cell_type === 'code') {
485 if (data.cell_type === 'code') {
506 if (data.input !== undefined) {
486 if (data.input !== undefined) {
507 this.set_text(data.input);
487 this.set_text(data.input);
508 }
488 }
509 if (data.prompt_number !== undefined) {
489 if (data.prompt_number !== undefined) {
510 this.set_input_prompt(data.prompt_number);
490 this.set_input_prompt(data.prompt_number);
511 } else {
491 } else {
512 this.set_input_prompt();
492 this.set_input_prompt();
513 };
493 };
514 var len = data.outputs.length;
494 var len = data.outputs.length;
515 for (var i=0; i<len; i++) {
495 for (var i=0; i<len; i++) {
516 // append with dynamic=false.
496 // append with dynamic=false.
517 this.append_output(data.outputs[i], false);
497 this.append_output(data.outputs[i], false);
518 };
498 };
519 if (data.collapsed !== undefined) {
499 if (data.collapsed !== undefined) {
520 if (data.collapsed) {
500 if (data.collapsed) {
521 this.collapse();
501 this.collapse();
522 } else {
502 } else {
523 this.expand();
503 this.expand();
524 };
504 };
525 };
505 };
526 };
506 };
527 };
507 };
528
508
529
509
530 CodeCell.prototype.toJSON = function () {
510 CodeCell.prototype.toJSON = function () {
531 var data = {};
511 var data = {};
532 data.input = this.get_text();
512 data.input = this.get_text();
533 data.cell_type = 'code';
513 data.cell_type = 'code';
534 if (this.input_prompt_number) {
514 if (this.input_prompt_number) {
535 data.prompt_number = this.input_prompt_number;
515 data.prompt_number = this.input_prompt_number;
536 };
516 };
537 var outputs = [];
517 var outputs = [];
538 var len = this.outputs.length;
518 var len = this.outputs.length;
539 for (var i=0; i<len; i++) {
519 for (var i=0; i<len; i++) {
540 outputs[i] = this.outputs[i];
520 outputs[i] = this.outputs[i];
541 };
521 };
542 data.outputs = outputs;
522 data.outputs = outputs;
543 data.language = 'python';
523 data.language = 'python';
544 data.collapsed = this.collapsed;
524 data.collapsed = this.collapsed;
545 return data;
525 return data;
546 };
526 };
547
527
548
528
549 IPython.CodeCell = CodeCell;
529 IPython.CodeCell = CodeCell;
550
530
551 return IPython;
531 return IPython;
552 }(IPython));
532 }(IPython));
@@ -1,205 +1,301
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 // Tooltip
9 // Tooltip
10 //============================================================================
10 //============================================================================
11
11
12 // Todo :
12 // Todo :
13 // use codemirror highlight example to
13 // use codemirror highlight example to
14 // highlight the introspection request and introspect on mouse hove ...
14 // highlight the introspection request and introspect on mouse hove ...
15 //
15 //
16 //
16 //
17 var IPython = (function (IPython) {
17 var IPython = (function (IPython) {
18
18
19 var utils = IPython.utils;
19 var utils = IPython.utils;
20
20
21 var Tooltip = function (notebook) {
21 var Tooltip = function (notebook) {
22 this.tooltip = $('#tooltip');
22 this.tooltip = $('#tooltip');
23 var that = this;
23 var that = this;
24 this._hidden = true;
24 this._hidden = true;
25
25
26 // variable for consecutive call
27 this._old_cell = null ;
28 this._old_request = null ;
29 this._consecutive_conter = 0;
30
31 // 'sticky ?'
32 this._sticky = false;
33
26 // contain the button in the upper right corner
34 // contain the button in the upper right corner
27 this.buttons = $('<div/>')
35 this.buttons = $('<div/>')
28 .addClass('tooltipbuttons');
36 .addClass('tooltipbuttons');
29
37
30 // will contain the docstring
38 // will contain the docstring
31 this.text = $('<div/>')
39 this.text = $('<div/>')
32 .addClass('tooltiptext')
40 .addClass('tooltiptext')
33 .addClass('smalltooltip');
41 .addClass('smalltooltip');
34
42
35 var tooltip = this.tooltip;
43 var tooltip = this.tooltip;
36 var text = this.text;
37
44
38 // build the buttons menu on the upper right
45 // build the buttons menu on the upper right
39
46
40 // expand the tooltip to see more
47 // expand the tooltip to see more
41 var expandlink=$('<a/>').attr('href',"#")
48 var expandlink=$('<a/>').attr('href',"#")
42 .addClass("ui-corner-all") //rounded corner
49 .addClass("ui-corner-all") //rounded corner
43 .attr('role',"button")
50 .attr('role',"button")
44 .attr('id','expanbutton')
51 .attr('id','expanbutton')
45 .click(function(){
52 .click(function(){that.expand()})
46 text.removeClass('smalltooltip');
47 text.addClass('bigtooltip');
48 $('#expanbutton').addClass('hidden');
49 that._cmfocus();
50 })
51 .append(
53 .append(
52 $('<span/>').text('Expand')
54 $('<span/>').text('Expand')
53 .addClass('ui-icon')
55 .addClass('ui-icon')
54 .addClass('ui-icon-plus')
56 .addClass('ui-icon-plus')
55 );
57 );
56
58
57 // open in pager
59 // open in pager
58 var morelink=$('<a/>').attr('href',"#")
60 var morelink=$('<a/>').attr('href',"#")
59 .attr('role',"button")
61 .attr('role',"button")
60 .addClass('ui-button');
62 .addClass('ui-button');
61 var morespan=$('<span/>').text('Open in Pager')
63 var morespan=$('<span/>').text('Open in Pager')
62 .addClass('ui-icon')
64 .addClass('ui-icon')
63 .addClass('ui-icon-arrowstop-l-n');
65 .addClass('ui-icon-arrowstop-l-n');
64 morelink.append(morespan);
66 morelink.append(morespan);
65 morelink.click(function(){
67 morelink.click(function(){
66 var msg_id = IPython.notebook.kernel.execute(that.name+"?");
68 that.showInPager();
67 IPython.notebook.msg_cell_map[msg_id] = IPython.notebook.get_selected_cell().cell_id;
68 that.remove_and_cancel_tooltip();
69 that._cmfocus();
70 });
69 });
71
70
72 // close the tooltip
71 // close the tooltip
73 var closelink=$('<a/>').attr('href',"#");
72 var closelink=$('<a/>').attr('href',"#");
74 closelink.attr('role',"button");
73 closelink.attr('role',"button");
75 closelink.addClass('ui-button');
74 closelink.addClass('ui-button');
76 var closespan=$('<span/>').text('Close');
75 var closespan=$('<span/>').text('Close');
77 closespan.addClass('ui-icon');
76 closespan.addClass('ui-icon');
78 closespan.addClass('ui-icon-close');
77 closespan.addClass('ui-icon-close');
79 closelink.append(closespan);
78 closelink.append(closespan);
80 closelink.click(function(){
79 closelink.click(function(){
81 that.hide();
80 that.hide();
82 });
81 });
83
82
84 //construct the tooltip
83 //construct the tooltip
85 // add in the reverse order you want them to appear
84 // add in the reverse order you want them to appear
86 this.buttons.append(closelink);
85 this.buttons.append(closelink);
87 this.buttons.append(expandlink);
86 this.buttons.append(expandlink);
88 this.buttons.append(morelink);
87 this.buttons.append(morelink);
89
88
90 // we need a phony element to make the small arrow
89 // we need a phony element to make the small arrow
91 // of the tooltip in css
90 // of the tooltip in css
92 // we could try to move the arrow later
91 // we could try to move the arrow later
93 this.arrow = $('<div/>').addClass('pretooltiparrow');
92 this.arrow = $('<div/>').addClass('pretooltiparrow');
94 this.tooltip.append(this.buttons);
93 this.tooltip.append(this.buttons);
95 this.tooltip.append(this.arrow);
94 this.tooltip.append(this.arrow);
96 this.tooltip.append(this.text);
95 this.tooltip.append(this.text);
97 };
96 };
98
97
98 Tooltip.prototype.showInPager = function()
99 {
100 var msg_id = IPython.notebook.kernel.execute(that.name+"?");
101 IPython.notebook.msg_cell_map[msg_id] = IPython.notebook.get_selected_cell().cell_id;
102 this.remove_and_cancel_tooltip();
103 this._cmfocus();
104 }
105
106
107 Tooltip.prototype.expand = function(){
108 this.text.removeClass('smalltooltip');
109 this.text.addClass('bigtooltip');
110 $('#expanbutton').addClass('hidden');
111 this._cmfocus();
112 }
113
99 // deal with all the logic of hiding the tooltip
114 // deal with all the logic of hiding the tooltip
100 // and reset it's status
115 // and reset it's status
101 Tooltip.prototype.hide = function()
116 Tooltip.prototype.hide = function()
102 {
117 {
103 this.tooltip.addClass('hide');
118 this.tooltip.addClass('hide');
104 $('#expanbutton').removeClass('hidden');
119 $('#expanbutton').removeClass('hidden');
105 this.text.removeClass('bigtooltip');
120 this.text.removeClass('bigtooltip');
106 this.text.addClass('smalltooltip');
121 this.text.addClass('smalltooltip');
107 // keep scroll top to be sure to always see the first line
122 // keep scroll top to be sure to always see the first line
108 this.text.scrollTop(0);
123 this.text.scrollTop(0);
109 this._hidden = true;
124 this._hidden = true;
110 }
125 }
111
126
112 //TODO, try to diminish the number of parameters.
127 //TODO, try to diminish the number of parameters.
113 Tooltip.prototype.request_tooltip_after_time = function (pre_cursor,time){
128 Tooltip.prototype.request_tooltip_after_time = function (pre_cursor,time){
114 };
129 };
115
130
116
131
117 Tooltip.prototype.remove_and_cancel_tooltip = function() {
132 Tooltip.prototype.remove_and_cancel_tooltip = function(force) {
118 // note that we don't handle closing directly inside the calltip
133 // note that we don't handle closing directly inside the calltip
119 // as in the completer, because it is not focusable, so won't
134 // as in the completer, because it is not focusable, so won't
120 // get the event.
135 // get the event.
121 this.hide();
136 if(this._sticky == false || force == true)
137 {
138 this.hide();
139 }
140 this.cancel_pending();
141 this._old_cell = null ;
142 this._old_request = null ;
143 this._consecutive_conter = 0;
144 }
145
146 Tooltip.prototype.cancel_pending = function(){
122 if (this.tooltip_timeout != null){
147 if (this.tooltip_timeout != null){
123 clearTimeout(this.tooltip_timeout);
148 clearTimeout(this.tooltip_timeout);
124 this.tooltip_timeout = null;
149 this.tooltip_timeout = null;
125 }
150 }
126 }
151 }
127
152
128 Tooltip.prototype.pending = function(cell,text)
153 Tooltip.prototype.pending = function(cell,text)
129 {
154 {
130 var that = this;
155 var that = this;
131 this.tooltip_timeout = setTimeout(function(){that.request(cell, text)} , IPython.notebook.time_before_tooltip);
156 this.tooltip_timeout = setTimeout(function(){that.request(cell)} , IPython.notebook.time_before_tooltip);
132 }
157 }
133 Tooltip.prototype.request = function(cell,text)
158 Tooltip.prototype.request = function(cell)
134 {
159 {
135 IPython.notebook.request_tool_tip(cell, text);
160 this.cancel_pending();
161 var editor = cell.code_mirror;
162 this.code_mirror = editor;
163 var cursor = editor.getCursor();
164 var text = editor.getRange({line:cursor.line,ch:0},cursor).trim();
165
166 if( this._old_cell == cell && this._old_request == text && this._hidden == false)
167 {
168 this._consecutive_conter = this._consecutive_conter +1;
169 } else {
170 this._old_cell = cell ;
171 this._old_request = text ;
172 this._consecutive_conter =0;
173 this.cancel_stick();
174 }
175
176 if( this._consecutive_conter == 1 )
177 {
178 this.expand()
179 return;
180 }
181 else if( this._consecutive_conter == 2)
182 {
183 this.stick();
184 return;
185 }
186 else if( this._consecutive_conter == 3)
187 {
188 console.log('should open in pager');
189 this._old_cell = null ;
190 this._cancel_stick
191 this._old_request = null ;
192 this._consecutive_conter = 0;
193 this.showInPager();
194 this._cmfocus();
195 return;
196 }
197 else if( this._consecutive_conter == 4)
198 {
199
200 }
201
202 if (text === "" || text === "(" ) {
203 return;
204 // don't do anything if line beggin with '(' or is empty
205 }
206 IPython.notebook.request_tool_tip(cell, text);
207 }
208 Tooltip.prototype.cancel_stick = function()
209 {
210 clearTimeout(this._stick_timeout);
211 this._sticky = false;
212 }
213
214 Tooltip.prototype.stick = function()
215 {
216 console.log('tooltip will stick for at least 10 sec');
217 var that = this;
218 this._sticky = true;
219 this._stick_timeout = setTimeout( function(){
220 that._sticky = false;
221 console.log('tooltip will not stick anymore');
222 }, 10*1000
223 );
224
225
136 }
226 }
137
227
138 Tooltip.prototype.show = function(reply, codecell)
228 Tooltip.prototype.show = function(reply, codecell)
139 {
229 {
140 // move the bubble if it is not hidden
230 // move the bubble if it is not hidden
141 // otherwise fade it
231 // otherwise fade it
142 var editor = codecell.code_mirror;
232 var editor = codecell.code_mirror;
143 this.name = reply.name;
233 this.name = reply.name;
144 this.code_mirror = editor;
234 this.code_mirror = editor;
235
236 // do some math to have the tooltip arrow on more or less on left or right
237 // width of the editor
238 var w= $(this.code_mirror.getScrollerElement()).width();
239 // ofset of the editor
240 var o= $(this.code_mirror.getScrollerElement()).offset();
145 var pos = editor.cursorCoords();
241 var pos = editor.cursorCoords();
146 var xinit = pos.x;
242 var xinit = pos.x;
147 var xinter = xinit/1000*600;
243 var xinter = o.left + (xinit-o.left)/w*(w-450);
148 var posarrowleft = xinit - xinter;
244 var posarrowleft = xinit - xinter;
149
245
150
246
151 if( this._hidden == false)
247 if( this._hidden == false)
152 {
248 {
153 this.tooltip.animate({'left' : xinter-30+'px','top' :(pos.yBot+10)+'px'});
249 this.tooltip.animate({'left' : xinter-30+'px','top' :(pos.yBot+10)+'px'});
154 } else
250 } else
155 {
251 {
156 this.tooltip.css({'left' : xinter-30+'px'});
252 this.tooltip.css({'left' : xinter-30+'px'});
157 this.tooltip.css({'top' :(pos.yBot+10)+'px'});
253 this.tooltip.css({'top' :(pos.yBot+10)+'px'});
158 }
254 }
159 this.arrow.animate({'left' : posarrowleft+'px'});
255 this.arrow.animate({'left' : posarrowleft+'px'});
160 this.tooltip.removeClass('hidden')
256 this.tooltip.removeClass('hidden')
161 this.tooltip.removeClass('hide');
257 this.tooltip.removeClass('hide');
162 this._hidden = false;
258 this._hidden = false;
163
259
164 // build docstring
260 // build docstring
165 defstring = reply.call_def;
261 defstring = reply.call_def;
166 if (defstring == null) { defstring = reply.init_definition; }
262 if (defstring == null) { defstring = reply.init_definition; }
167 if (defstring == null) { defstring = reply.definition; }
263 if (defstring == null) { defstring = reply.definition; }
168
264
169 docstring = reply.call_docstring;
265 docstring = reply.call_docstring;
170 if (docstring == null) { docstring = reply.init_docstring; }
266 if (docstring == null) { docstring = reply.init_docstring; }
171 if (docstring == null) { docstring = reply.docstring; }
267 if (docstring == null) { docstring = reply.docstring; }
172 if (docstring == null) { docstring = "<empty docstring>"; }
268 if (docstring == null) { docstring = "<empty docstring>"; }
173
269
174 this.text.children().remove();
270 this.text.children().remove();
175
271
176 var pre=$('<pre/>').html(utils.fixConsole(docstring));
272 var pre=$('<pre/>').html(utils.fixConsole(docstring));
177 if(defstring){
273 if(defstring){
178 var defstring_html = $('<pre/>').html(utils.fixConsole(defstring));
274 var defstring_html = $('<pre/>').html(utils.fixConsole(defstring));
179 this.text.append(defstring_html);
275 this.text.append(defstring_html);
180 }
276 }
181 this.text.append(pre);
277 this.text.append(pre);
182 // keep scroll top to be sure to always see the first line
278 // keep scroll top to be sure to always see the first line
183 this.text.scrollTop(0);
279 this.text.scrollTop(0);
184
280
185
281
186 }
282 }
187
283
188 Tooltip.prototype.showInPager = function(){
284 Tooltip.prototype.showInPager = function(text){
189 var msg_id = IPython.notebook.kernel.execute(name+"?");
285 var msg_id = IPython.notebook.kernel.execute(this.name+"?");
190 IPython.notebook.msg_cell_map[msg_id] = IPython.notebook.get_selected_cell().cell_id;
286 IPython.notebook.msg_cell_map[msg_id] = IPython.notebook.get_selected_cell().cell_id;
191 that.remove_and_cancel_tooltip();
287 this.remove_and_cancel_tooltip(true);
192 setTimeout(function(){that.code_mirror.focus();}, 50);
288 this._cmfocus();
193 }
289 }
194
290
195 Tooltip.prototype._cmfocus = function()
291 Tooltip.prototype._cmfocus = function()
196 {
292 {
197 var cm = this.code_mirror;
293 var cm = this.code_mirror;
198 setTimeout(function(){cm.focus();}, 50);
294 setTimeout(function(){cm.focus();}, 50);
199 }
295 }
200
296
201
297
202 IPython.Tooltip = Tooltip;
298 IPython.Tooltip = Tooltip;
203
299
204 return IPython;
300 return IPython;
205 }(IPython));
301 }(IPython));
@@ -1,242 +1,242
1 {% extends page.html %}
1 {% extends page.html %}
2 {% block stylesheet %}
2 {% block stylesheet %}
3
3
4 {% if mathjax_url %}
4 {% if mathjax_url %}
5 <script type="text/javascript" src="{{mathjax_url}}?config=TeX-AMS_HTML" charset="utf-8"></script>
5 <script type="text/javascript" src="{{mathjax_url}}?config=TeX-AMS_HTML" charset="utf-8"></script>
6 {% end %}
6 {% end %}
7 <script type="text/javascript">
7 <script type="text/javascript">
8 // MathJax disabled, set as null to distingish from *missing* MathJax,
8 // MathJax disabled, set as null to distingish from *missing* MathJax,
9 // where it will be undefined, and should prompt a dialog later.
9 // where it will be undefined, and should prompt a dialog later.
10 window.mathjax_url = "{{mathjax_url}}";
10 window.mathjax_url = "{{mathjax_url}}";
11 </script>
11 </script>
12
12
13 <link rel="stylesheet" href="{{ static_url("codemirror/lib/codemirror.css") }}">
13 <link rel="stylesheet" href="{{ static_url("codemirror/lib/codemirror.css") }}">
14 <link rel="stylesheet" href="{{ static_url("codemirror/theme/ipython.css") }}">
14 <link rel="stylesheet" href="{{ static_url("codemirror/theme/ipython.css") }}">
15
15
16 <link rel="stylesheet" href="{{ static_url("prettify/prettify.css") }}"/>
16 <link rel="stylesheet" href="{{ static_url("prettify/prettify.css") }}"/>
17
17
18 <link rel="stylesheet" href="{{ static_url("css/notebook.css") }}" type="text/css" />
18 <link rel="stylesheet" href="{{ static_url("css/notebook.css") }}" type="text/css" />
19 <link rel="stylesheet" href="{{ static_url("css/tooltip.css") }}" type="text/css" />
19 <link rel="stylesheet" href="{{ static_url("css/tooltip.css") }}" type="text/css" />
20 <link rel="stylesheet" href="{{ static_url("css/renderedhtml.css") }}" type="text/css" />
20 <link rel="stylesheet" href="{{ static_url("css/renderedhtml.css") }}" type="text/css" />
21
21
22 {% end %}
22 {% end %}
23
23
24
24
25 {% block params %}
25 {% block params %}
26
26
27 data-project={{project}}
27 data-project={{project}}
28 data-base-project-url={{base_project_url}}
28 data-base-project-url={{base_project_url}}
29 data-base-kernel-url={{base_kernel_url}}
29 data-base-kernel-url={{base_kernel_url}}
30 data-read-only={{read_only and not logged_in}}
30 data-read-only={{read_only and not logged_in}}
31 data-notebook-id={{notebook_id}}
31 data-notebook-id={{notebook_id}}
32
32
33 {% end %}
33 {% end %}
34
34
35
35
36 {% block header %}
36 {% block header %}
37
37
38 <span id="save_widget">
38 <span id="save_widget">
39 <span id="notebook_name"></span>
39 <span id="notebook_name"></span>
40 <span id="save_status"></span>
40 <span id="save_status"></span>
41 </span>
41 </span>
42
42
43 {% end %}
43 {% end %}
44
44
45
45
46 {% block site %}
46 {% block site %}
47
47
48 <div id="menubar_container">
48 <div id="menubar_container">
49 <div id="menubar">
49 <div id="menubar">
50 <ul id="menus">
50 <ul id="menus">
51 <li><a href="#">File</a>
51 <li><a href="#">File</a>
52 <ul>
52 <ul>
53 <li id="new_notebook"><a href="#">New</a></li>
53 <li id="new_notebook"><a href="#">New</a></li>
54 <li id="open_notebook"><a href="#">Open...</a></li>
54 <li id="open_notebook"><a href="#">Open...</a></li>
55 <hr/>
55 <hr/>
56 <li id="copy_notebook"><a href="#">Make a Copy...</a></li>
56 <li id="copy_notebook"><a href="#">Make a Copy...</a></li>
57 <li id="rename_notebook"><a href="#">Rename...</a></li>
57 <li id="rename_notebook"><a href="#">Rename...</a></li>
58 <li id="save_notebook"><a href="#">Save</a></li>
58 <li id="save_notebook"><a href="#">Save</a></li>
59 <hr/>
59 <hr/>
60 <li><a href="#">Download as</a>
60 <li><a href="#">Download as</a>
61 <ul>
61 <ul>
62 <li id="download_ipynb"><a href="#">IPython (.ipynb)</a></li>
62 <li id="download_ipynb"><a href="#">IPython (.ipynb)</a></li>
63 <li id="download_py"><a href="#">Python (.py)</a></li>
63 <li id="download_py"><a href="#">Python (.py)</a></li>
64 </ul>
64 </ul>
65 </li>
65 </li>
66 <hr/>
66 <hr/>
67 <li id="print_notebook"><a href="/{{notebook_id}}/print" target="_blank">Print View</a></li>
67 <li id="print_notebook"><a href="/{{notebook_id}}/print" target="_blank">Print View</a></li>
68 <hr/>
68 <hr/>
69 <li id="kill_and_exit"><a href="#" >Close and halt</a></li>
69 <li id="kill_and_exit"><a href="#" >Close and halt</a></li>
70 </ul>
70 </ul>
71 </li>
71 </li>
72 <li><a href="#">Edit</a>
72 <li><a href="#">Edit</a>
73 <ul>
73 <ul>
74 <li id="cut_cell"><a href="#">Cut Cell</a></li>
74 <li id="cut_cell"><a href="#">Cut Cell</a></li>
75 <li id="copy_cell"><a href="#">Copy Cell</a></li>
75 <li id="copy_cell"><a href="#">Copy Cell</a></li>
76 <li id="paste_cell" class="ui-state-disabled"><a href="#">Paste Cell</a></li>
76 <li id="paste_cell" class="ui-state-disabled"><a href="#">Paste Cell</a></li>
77 <li id="paste_cell_above" class="ui-state-disabled"><a href="#">Paste Cell Above</a></li>
77 <li id="paste_cell_above" class="ui-state-disabled"><a href="#">Paste Cell Above</a></li>
78 <li id="paste_cell_below" class="ui-state-disabled"><a href="#">Paste Cell Below</a></li>
78 <li id="paste_cell_below" class="ui-state-disabled"><a href="#">Paste Cell Below</a></li>
79 <li id="delete_cell"><a href="#">Delete</a></li>
79 <li id="delete_cell"><a href="#">Delete</a></li>
80 <hr/>
80 <hr/>
81 <li id="split_cell"><a href="#">Split Cell</a></li>
81 <li id="split_cell"><a href="#">Split Cell</a></li>
82 <li id="merge_cell_above"><a href="#">Merge Cell Above</a></li>
82 <li id="merge_cell_above"><a href="#">Merge Cell Above</a></li>
83 <li id="merge_cell_below"><a href="#">Merge Cell Below</a></li>
83 <li id="merge_cell_below"><a href="#">Merge Cell Below</a></li>
84 <hr/>
84 <hr/>
85 <li id="move_cell_up"><a href="#">Move Cell Up</a></li>
85 <li id="move_cell_up"><a href="#">Move Cell Up</a></li>
86 <li id="move_cell_down"><a href="#">Move Cell Down</a></li>
86 <li id="move_cell_down"><a href="#">Move Cell Down</a></li>
87 <hr/>
87 <hr/>
88 <li id="select_previous"><a href="#">Select Previous Cell</a></li>
88 <li id="select_previous"><a href="#">Select Previous Cell</a></li>
89 <li id="select_next"><a href="#">Select Next Cell</a></li>
89 <li id="select_next"><a href="#">Select Next Cell</a></li>
90 </ul>
90 </ul>
91 </li>
91 </li>
92 <li><a href="#">View</a>
92 <li><a href="#">View</a>
93 <ul>
93 <ul>
94 <li id="toggle_header"><a href="#">Toggle Header</a></li>
94 <li id="toggle_header"><a href="#">Toggle Header</a></li>
95 <li id="toggle_toolbar"><a href="#">Toggle Toolbar</a></li>
95 <li id="toggle_toolbar"><a href="#">Toggle Toolbar</a></li>
96 </ul>
96 </ul>
97 </li>
97 </li>
98 <li><a href="#">Insert</a>
98 <li><a href="#">Insert</a>
99 <ul>
99 <ul>
100 <li id="insert_cell_above"><a href="#">Insert Cell Above</a></li>
100 <li id="insert_cell_above"><a href="#">Insert Cell Above</a></li>
101 <li id="insert_cell_below"><a href="#">Insert Cell Below</a></li>
101 <li id="insert_cell_below"><a href="#">Insert Cell Below</a></li>
102 </ul>
102 </ul>
103 </li>
103 </li>
104 <li><a href="#">Cell</a>
104 <li><a href="#">Cell</a>
105 <ul>
105 <ul>
106 <li id="run_cell"><a href="#">Run</a></li>
106 <li id="run_cell"><a href="#">Run</a></li>
107 <li id="run_cell_in_place"><a href="#">Run in Place</a></li>
107 <li id="run_cell_in_place"><a href="#">Run in Place</a></li>
108 <li id="run_all_cells"><a href="#">Run All</a></li>
108 <li id="run_all_cells"><a href="#">Run All</a></li>
109 <hr/>
109 <hr/>
110 <li id="to_code"><a href="#">Code</a></li>
110 <li id="to_code"><a href="#">Code</a></li>
111 <li id="to_markdown"><a href="#">Markdown </a></li>
111 <li id="to_markdown"><a href="#">Markdown </a></li>
112 <li id="to_raw"><a href="#">Raw Text</a></li>
112 <li id="to_raw"><a href="#">Raw Text</a></li>
113 <li id="to_heading1"><a href="#">Heading 1</a></li>
113 <li id="to_heading1"><a href="#">Heading 1</a></li>
114 <li id="to_heading2"><a href="#">Heading 2</a></li>
114 <li id="to_heading2"><a href="#">Heading 2</a></li>
115 <li id="to_heading3"><a href="#">Heading 3</a></li>
115 <li id="to_heading3"><a href="#">Heading 3</a></li>
116 <li id="to_heading4"><a href="#">Heading 4</a></li>
116 <li id="to_heading4"><a href="#">Heading 4</a></li>
117 <li id="to_heading5"><a href="#">Heading 5</a></li>
117 <li id="to_heading5"><a href="#">Heading 5</a></li>
118 <li id="to_heading6"><a href="#">Heading 6</a></li>
118 <li id="to_heading6"><a href="#">Heading 6</a></li>
119 <hr/>
119 <hr/>
120 <li id="toggle_output"><a href="#">Toggle Output</a></li>
120 <li id="toggle_output"><a href="#">Toggle Output</a></li>
121 <li id="clear_all_output"><a href="#">Clear All Output</a></li>
121 <li id="clear_all_output"><a href="#">Clear All Output</a></li>
122 </ul>
122 </ul>
123 </li>
123 </li>
124 <li><a href="#">Kernel</a>
124 <li><a href="#">Kernel</a>
125 <ul>
125 <ul>
126 <li id="int_kernel"><a href="#">Interrupt</a></li>
126 <li id="int_kernel"><a href="#">Interrupt</a></li>
127 <li id="restart_kernel"><a href="#">Restart</a></li>
127 <li id="restart_kernel"><a href="#">Restart</a></li>
128 </ul>
128 </ul>
129 </li>
129 </li>
130 <li><a href="#">Help</a>
130 <li><a href="#">Help</a>
131 <ul>
131 <ul>
132 <li><a href="http://ipython.org/documentation.html" target="_blank">IPython Help</a></li>
132 <li><a href="http://ipython.org/documentation.html" target="_blank">IPython Help</a></li>
133 <li><a href="http://ipython.org/ipython-doc/stable/interactive/htmlnotebook.html" target="_blank">Notebook Help</a></li>
133 <li><a href="http://ipython.org/ipython-doc/stable/interactive/htmlnotebook.html" target="_blank">Notebook Help</a></li>
134 <li id="keyboard_shortcuts"><a href="#">Keyboard Shortcuts</a></li>
134 <li id="keyboard_shortcuts"><a href="#">Keyboard Shortcuts</a></li>
135 <hr/>
135 <hr/>
136 <li><a href="http://docs.python.org" target="_blank">Python</a></li>
136 <li><a href="http://docs.python.org" target="_blank">Python</a></li>
137 <li><a href="http://docs.scipy.org/doc/numpy/reference/" target="_blank">NumPy</a></li>
137 <li><a href="http://docs.scipy.org/doc/numpy/reference/" target="_blank">NumPy</a></li>
138 <li><a href="http://docs.scipy.org/doc/scipy/reference/" target="_blank">SciPy</a></li>
138 <li><a href="http://docs.scipy.org/doc/scipy/reference/" target="_blank">SciPy</a></li>
139 <li><a href="http://docs.sympy.org/dev/index.html" target="_blank">SymPy</a></li>
139 <li><a href="http://docs.sympy.org/dev/index.html" target="_blank">SymPy</a></li>
140 <li><a href="http://matplotlib.sourceforge.net/" target="_blank">Matplotlib</a></li>
140 <li><a href="http://matplotlib.sourceforge.net/" target="_blank">Matplotlib</a></li>
141 </ul>
141 </ul>
142 </li>
142 </li>
143 </ul>
143 </ul>
144
144
145 </div>
145 </div>
146 <div id="notification"></div>
146 <div id="notification"></div>
147 </div>
147 </div>
148
148
149
149
150 <div id="toolbar">
150 <div id="toolbar">
151
151
152 <span>
152 <span>
153 <button id="save_b">Save</button>
153 <button id="save_b">Save</button>
154 </span>
154 </span>
155 <span id="cut_copy_paste">
155 <span id="cut_copy_paste">
156 <button id="cut_b" title="Cut Cell">Cut Cell</button>
156 <button id="cut_b" title="Cut Cell">Cut Cell</button>
157 <button id="copy_b" title="Copy Cell">Copy Cell</button>
157 <button id="copy_b" title="Copy Cell">Copy Cell</button>
158 <button id="paste_b" title="Paste Cell">Paste Cell</button>
158 <button id="paste_b" title="Paste Cell">Paste Cell</button>
159 </span>
159 </span>
160 <span id="move_up_down">
160 <span id="move_up_down">
161 <button id="move_up_b" title="Move Cell Up">Move Cell Up</button>
161 <button id="move_up_b" title="Move Cell Up">Move Cell Up</button>
162 <button id="move_down_b" title="Move Cell Down">Move Down</button>
162 <button id="move_down_b" title="Move Cell Down">Move Down</button>
163 </span>
163 </span>
164 <span id="insert_above_below">
164 <span id="insert_above_below">
165 <button id="insert_above_b" title="Insert Cell Above">Insert Cell Above</button>
165 <button id="insert_above_b" title="Insert Cell Above">Insert Cell Above</button>
166 <button id="insert_below_b" title="Insert Cell Below">Insert Cell Below</button>
166 <button id="insert_below_b" title="Insert Cell Below">Insert Cell Below</button>
167 </span>
167 </span>
168 <span id="run_int">
168 <span id="run_int">
169 <button id="run_b" title="Run Cell">Run Cell</button>
169 <button id="run_b" title="Run Cell">Run Cell</button>
170 <button id="interrupt_b" title="Interrupt">Interrupt</button>
170 <button id="interrupt_b" title="Interrupt">Interrupt</button>
171 </span>
171 </span>
172 <span>
172 <span>
173 <select id="cell_type">
173 <select id="cell_type">
174 <option value="code">Code</option>
174 <option value="code">Code</option>
175 <option value="markdown">Markdown</option>
175 <option value="markdown">Markdown</option>
176 <option value="raw">Raw Text</option>
176 <option value="raw">Raw Text</option>
177 <option value="heading1">Heading 1</option>
177 <option value="heading1">Heading 1</option>
178 <option value="heading2">Heading 2</option>
178 <option value="heading2">Heading 2</option>
179 <option value="heading3">Heading 3</option>
179 <option value="heading3">Heading 3</option>
180 <option value="heading4">Heading 4</option>
180 <option value="heading4">Heading 4</option>
181 <option value="heading5">Heading 5</option>
181 <option value="heading5">Heading 5</option>
182 <option value="heading6">Heading 6</option>
182 <option value="heading6">Heading 6</option>
183 </select>
183 </select>
184 </span>
184 </span>
185
185
186 </div>
186 </div>
187
187
188 <div id="main_app">
188 <div id="main_app">
189
189
190 <div id="notebook_panel">
190 <div id="notebook_panel">
191 <div id="notebook"></div>
191 <div id="notebook"></div>
192 <div id="pager_splitter"></div>
192 <div id="pager_splitter"></div>
193 <div id="pager"></div>
193 <div id="pager"></div>
194 </div>
194 </div>
195
195
196 </div>
196 </div>
197 <div id='tooltip' class='tooltip ui-corner-all hidden'></div>
197 <div id='tooltip' class='tooltip ui-corner-all hidden hide'></div>
198
198
199
199
200 {% end %}
200 {% end %}
201
201
202
202
203 {% block script %}
203 {% block script %}
204
204
205 <script src="{{ static_url("codemirror/lib/codemirror.js") }}" charset="utf-8"></script>
205 <script src="{{ static_url("codemirror/lib/codemirror.js") }}" charset="utf-8"></script>
206 <script src="{{ static_url("codemirror/mode/python/python.js") }}" charset="utf-8"></script>
206 <script src="{{ static_url("codemirror/mode/python/python.js") }}" charset="utf-8"></script>
207 <script src="{{ static_url("codemirror/mode/htmlmixed/htmlmixed.js") }}" charset="utf-8"></script>
207 <script src="{{ static_url("codemirror/mode/htmlmixed/htmlmixed.js") }}" charset="utf-8"></script>
208 <script src="{{ static_url("codemirror/mode/xml/xml.js") }}" charset="utf-8"></script>
208 <script src="{{ static_url("codemirror/mode/xml/xml.js") }}" charset="utf-8"></script>
209 <script src="{{ static_url("codemirror/mode/javascript/javascript.js") }}" charset="utf-8"></script>
209 <script src="{{ static_url("codemirror/mode/javascript/javascript.js") }}" charset="utf-8"></script>
210 <script src="{{ static_url("codemirror/mode/css/css.js") }}" charset="utf-8"></script>
210 <script src="{{ static_url("codemirror/mode/css/css.js") }}" charset="utf-8"></script>
211 <script src="{{ static_url("codemirror/mode/rst/rst.js") }}" charset="utf-8"></script>
211 <script src="{{ static_url("codemirror/mode/rst/rst.js") }}" charset="utf-8"></script>
212 <script src="{{ static_url("codemirror/mode/markdown/markdown.js") }}" charset="utf-8"></script>
212 <script src="{{ static_url("codemirror/mode/markdown/markdown.js") }}" charset="utf-8"></script>
213
213
214 <script src="{{ static_url("pagedown/Markdown.Converter.js") }}" charset="utf-8"></script>
214 <script src="{{ static_url("pagedown/Markdown.Converter.js") }}" charset="utf-8"></script>
215
215
216 <script src="{{ static_url("prettify/prettify.js") }}" charset="utf-8"></script>
216 <script src="{{ static_url("prettify/prettify.js") }}" charset="utf-8"></script>
217 <script src="{{ static_url("dateformat/date.format.js") }}" charset="utf-8"></script>
217 <script src="{{ static_url("dateformat/date.format.js") }}" charset="utf-8"></script>
218
218
219 <script src="{{ static_url("js/events.js") }}" type="text/javascript" charset="utf-8"></script>
219 <script src="{{ static_url("js/events.js") }}" type="text/javascript" charset="utf-8"></script>
220 <script src="{{ static_url("js/utils.js") }}" type="text/javascript" charset="utf-8"></script>
220 <script src="{{ static_url("js/utils.js") }}" type="text/javascript" charset="utf-8"></script>
221 <script src="{{ static_url("js/layoutmanager.js") }}" type="text/javascript" charset="utf-8"></script>
221 <script src="{{ static_url("js/layoutmanager.js") }}" type="text/javascript" charset="utf-8"></script>
222 <script src="{{ static_url("js/initmathjax.js") }}" type="text/javascript" charset="utf-8"></script>
222 <script src="{{ static_url("js/initmathjax.js") }}" type="text/javascript" charset="utf-8"></script>
223 <script src="{{ static_url("js/cell.js") }}" type="text/javascript" charset="utf-8"></script>
223 <script src="{{ static_url("js/cell.js") }}" type="text/javascript" charset="utf-8"></script>
224 <script src="{{ static_url("js/codecell.js") }}" type="text/javascript" charset="utf-8"></script>
224 <script src="{{ static_url("js/codecell.js") }}" type="text/javascript" charset="utf-8"></script>
225 <script src="{{ static_url("js/completer.js") }}" type="text/javascript" charset="utf-8"></script>
225 <script src="{{ static_url("js/completer.js") }}" type="text/javascript" charset="utf-8"></script>
226 <script src="{{ static_url("js/context-hint.js") }} charset="utf-8"></script>
226 <script src="{{ static_url("js/context-hint.js") }} charset="utf-8"></script>
227 <script src="{{ static_url("js/textcell.js") }}" type="text/javascript" charset="utf-8"></script>
227 <script src="{{ static_url("js/textcell.js") }}" type="text/javascript" charset="utf-8"></script>
228 <script src="{{ static_url("js/kernel.js") }}" type="text/javascript" charset="utf-8"></script>
228 <script src="{{ static_url("js/kernel.js") }}" type="text/javascript" charset="utf-8"></script>
229 <script src="{{ static_url("js/savewidget.js") }}" type="text/javascript" charset="utf-8"></script>
229 <script src="{{ static_url("js/savewidget.js") }}" type="text/javascript" charset="utf-8"></script>
230 <script src="{{ static_url("js/quickhelp.js") }}" type="text/javascript" charset="utf-8"></script>
230 <script src="{{ static_url("js/quickhelp.js") }}" type="text/javascript" charset="utf-8"></script>
231 <script src="{{ static_url("js/pager.js") }}" type="text/javascript" charset="utf-8"></script>
231 <script src="{{ static_url("js/pager.js") }}" type="text/javascript" charset="utf-8"></script>
232 <script src="{{ static_url("js/menubar.js") }}" type="text/javascript" charset="utf-8"></script>
232 <script src="{{ static_url("js/menubar.js") }}" type="text/javascript" charset="utf-8"></script>
233 <script src="{{ static_url("js/toolbar.js") }}" type="text/javascript" charset="utf-8"></script>
233 <script src="{{ static_url("js/toolbar.js") }}" type="text/javascript" charset="utf-8"></script>
234 <script src="{{ static_url("js/notebook.js") }}" type="text/javascript" charset="utf-8"></script>
234 <script src="{{ static_url("js/notebook.js") }}" type="text/javascript" charset="utf-8"></script>
235 <script src="{{ static_url("js/notificationwidget.js") }}" type="text/javascript" charset="utf-8"></script>
235 <script src="{{ static_url("js/notificationwidget.js") }}" type="text/javascript" charset="utf-8"></script>
236 <script src="{{ static_url("js/tooltip.js") }}" type="text/javascript" charset="utf-8"></script>
236 <script src="{{ static_url("js/tooltip.js") }}" type="text/javascript" charset="utf-8"></script>
237 <script src="{{ static_url("js/notebookmain.js") }}" type="text/javascript" charset="utf-8"></script>
237 <script src="{{ static_url("js/notebookmain.js") }}" type="text/javascript" charset="utf-8"></script>
238
238
239 <script src="{{ static_url("js/context-hint.js") }} charset="utf-8"></script>
239 <script src="{{ static_url("js/context-hint.js") }} charset="utf-8"></script>
240 <script src="{{ static_url("codemirror/lib/util/simple-hint.js") }} charset="utf-8"></script>
240 <script src="{{ static_url("codemirror/lib/util/simple-hint.js") }} charset="utf-8"></script>
241
241
242 {% end %}
242 {% end %}
General Comments 0
You need to be logged in to leave comments. Login now