##// END OF EJS Templates
Clean code, retab and minor fix...
Matthias BUSSONNIER -
Show More
@@ -1,232 +1,231 b''
1 // function completer.
1 // function completer.
2 //
2 //
3 // completer should be a class that take an cell instance
3 // completer should be a class that take an cell instance
4
4
5 var IPython = (function(IPython ) {
5 var IPython = (function(IPython ) {
6 // that will prevent us from misspelling
6 // that will prevent us from misspelling
7 "use strict";
7 "use strict";
8
8
9 // easyier key mapping
9 // easyier key mapping
10 var key = IPython.utils.keycodes;
10 var key = IPython.utils.keycodes;
11
11
12 // what is the common start of all completions
12 // what is the common start of all completions
13 function sharedStart(B){
13 function sharedStart(B){
14 if(B.length == 1){return B[0]}
14 if(B.length == 1){return B[0];}
15 var A = new Array()
15 var A = new Array();
16 for(var i=0; i< B.length; i++)
16 for(var i=0; i< B.length; i++)
17 {
17 {
18 A.push(B[i].str);
18 A.push(B[i].str);
19 }
19 }
20 if(A.length > 1 ){
20 if(A.length > 1 ){
21 var tem1, tem2, s, A = A.slice(0).sort();
21 var tem1, tem2, s;
22 A = A.slice(0).sort();
22 tem1 = A[0];
23 tem1 = A[0];
23 s = tem1.length;
24 s = tem1.length;
24 tem2 = A.pop();
25 tem2 = A.pop();
25 while(s && tem2.indexOf(tem1) == -1){
26 while(s && tem2.indexOf(tem1) == -1){
26 tem1 = tem1.substring(0, --s);
27 tem1 = tem1.substring(0, --s);
27 }
28 }
28 if (tem1 == "" || tem2.indexOf(tem1) != 0){return null;}
29 if (tem1 == "" || tem2.indexOf(tem1) != 0){return null;}
29 return { str : tem1,
30 return { str : tem1,
30 type : "computed",
31 type : "computed",
31 from : B[0].from,
32 from : B[0].from,
32 to : B[0].to
33 to : B[0].to
33 };
34 };
34 }
35 }
35 return null;
36 return null;
36 }
37 }
37
38
38
39
39 var Completer = function(cell) {
40 var Completer = function(cell) {
40 this.editor = cell.code_mirror;
41 this.editor = cell.code_mirror;
41 // if last caractere before cursor is not in this, we stop completing
42 // if last caractere before cursor is not in this, we stop completing
42 this.reg = /[0-9a-z.]/i; // casse insensitive
43 this.reg = /[0-9a-z.]/i; // casse insensitive
43 }
44 };
44
45
45 Completer.prototype.kernelCompletionRequest = function(){
46 Completer.prototype.kernelCompletionRequest = function(){
46 var cur = this.editor.getCursor();
47 var cur = this.editor.getCursor();
47 var line = this.editor.getLine(cur.line);
48 var line = this.editor.getLine(cur.line);
48 // one could fork here and directly call finish completing if kernel is busy
49 // one could fork here and directly call finish completing if kernel is busy
49 var callbacks = {'complete_reply': $.proxy(this.finish_completing,this)};
50 var callbacks = {'complete_reply': $.proxy(this.finish_completing,this)};
50 IPython.notebook.kernel.complete(line, cur.ch, callbacks);
51 IPython.notebook.kernel.complete(line, cur.ch, callbacks);
51 }
52 };
52
53
53
54
54 Completer.prototype.startCompletion = function()
55 Completer.prototype.startCompletion = function()
55 {
56 {
56 // call for a 'first' completion, that will set the editor and do some
57 // call for a 'first' completion, that will set the editor and do some
57 // special behaviour like autopicking if only one completion availlable
58 // special behaviour like autopicking if only one completion availlable
58 //
59 //
59 if (this.editor.somethingSelected()) return;
60 if (this.editor.somethingSelected()) return;
60 this.done = false;
61 this.done = false;
61 // use to get focus back on opera
62 // use to get focus back on opera
62 this.carryOnCompletion(true);
63 this.carryOnCompletion(true);
63 }
64 };
64
65
65 Completer.prototype.carryOnCompletion = function(ff) {
66 Completer.prototype.carryOnCompletion = function(ff) {
66 // Pass true as parameter if you want the commpleter to autopick when
67 // Pass true as parameter if you want the commpleter to autopick when
67 // only one completion. This function is automatically reinvoked at
68 // only one completion. This function is automatically reinvoked at
68 // each keystroke with ff = false
69 // each keystroke with ff = false
69
70
70 var cur = this.editor.getCursor();
71 var cur = this.editor.getCursor();
71 var pre_cursor = this.editor.getRange({line:cur.line,ch:cur.ch-1},cur);
72 var pre_cursor = this.editor.getRange({line:cur.line,ch:cur.ch-1},cur);
72
73
73 // we need to check that we are still on a word boundary
74 // we need to check that we are still on a word boundary
74 // because while typing the completer is still reinvoking itself
75 // because while typing the completer is still reinvoking itself
75 if(!this.reg.test(pre_cursor)){ this.close(); return;}
76 if(!this.reg.test(pre_cursor)){ this.close(); return;}
76
77
77 this.autopick = false;
78 this.autopick = false;
78 if( ff != 'undefined' && ff==true)
79 if( ff != 'undefined' && ff==true)
79 { this.autopick=true; }
80 { this.autopick=true; }
80
81
81 // We want a single cursor position.
82 // We want a single cursor position.
82 if (this.editor.somethingSelected()) return;
83 if (this.editor.somethingSelected()) return;
83
84
84 //one kernel completion came back, finish_completing will be called with the results
85 //one kernel completion came back, finish_completing will be called with the results
85 this.kernelCompletionRequest();
86 this.kernelCompletionRequest();
86 }
87 };
87
88
88 Completer.prototype.finish_completing =function (content) {
89 Completer.prototype.finish_completing =function (content) {
89 // let's build a function that wrap all that stuff into what is needed
90 // let's build a function that wrap all that stuff into what is needed
90 // for the new completer:
91 // for the new completer:
91 var matched_text = content.matched_text;
92 var matched_text = content.matched_text;
92 var matches = content.matches;
93 var matches = content.matches;
93
94
94 var cur = this.editor.getCursor();
95 var cur = this.editor.getCursor();
95 var results = CodeMirror.contextHint(this.editor);
96 var results = CodeMirror.contextHint(this.editor);
96
97
97 // append the introspection result, in order, at at the beginning of
98 // append the introspection result, in order, at at the beginning of
98 // the table and compute the replacement range from current cursor
99 // the table and compute the replacement range from current cursor
99 // positon and matched_text length.
100 // positon and matched_text length.
100 for(var i= matches.length-1; i>=0 ;--i)
101 for(var i= matches.length-1; i>=0 ;--i)
101 {
102 {
102 results.unshift(
103 results.unshift(
103 { str : matches[i],
104 { str : matches[i],
104 type : "introspection",
105 type : "introspection",
105 from : {line: cur.line, ch: cur.ch-matched_text.length},
106 from : {line: cur.line, ch: cur.ch-matched_text.length},
106 to : {line: cur.line, ch: cur.ch}
107 to : {line: cur.line, ch: cur.ch}
107 })
108 });
108 }
109 }
109
110
110 // one the 2 sources results have been merge, deal with it
111 // one the 2 sources results have been merge, deal with it
111 this.raw_result = results;
112 this.raw_result = results;
112
113
113 // if empty result return
114 // if empty result return
114 if (!this.raw_result || !this.raw_result.length) return;
115 if (!this.raw_result || !this.raw_result.length) return;
115
116
116 // When there is only one completion, use it directly.
117 // When there is only one completion, use it directly.
117 if (this.autopick == true && this.raw_result.length == 1)
118 if (this.autopick == true && this.raw_result.length == 1)
118 {
119 {
119 this.insert(this.raw_result[0]);
120 this.insert(this.raw_result[0]);
120 return true;
121 return;
121 }
122 }
122
123
123 if (this.raw_result.length == 1)
124 if (this.raw_result.length == 1)
124 {
125 {
125 // test if first and only completion totally matches
126 // test if first and only completion totally matches
126 // what is typed, in this case dismiss
127 // what is typed, in this case dismiss
127 var str = this.raw_result[0].str
128 var str = this.raw_result[0].str;
128 var cur = this.editor.getCursor();
129 var pre_cursor = this.editor.getRange({line:cur.line,ch:cur.ch-str.length},cur);
129 var pre_cursor = this.editor.getRange({line:cur.line,ch:cur.ch-str.length},cur);
130 if(pre_cursor == str)
130 if(pre_cursor == str)
131 { this.close(); return ; }
131 { this.close(); return ; }
132 }
132 }
133
133
134 this.complete = $('<div/>').addClass('completions');
134 this.complete = $('<div/>').addClass('completions');
135 this.complete.attr('id','complete');
135 this.complete.attr('id','complete');
136
136
137 this.sel = $('<select/>')
137 this.sel = $('<select/>')
138 .attr('multiple','true')
138 .attr('multiple','true')
139 .attr('size',Math.min(10,this.raw_result.length));
139 .attr('size',Math.min(10,this.raw_result.length));
140 var pos = this.editor.cursorCoords();
140 var pos = this.editor.cursorCoords();
141
141
142 // TODO: I propose to remove enough horizontal pixel
142 // TODO: I propose to remove enough horizontal pixel
143 // to align the text later
143 // to align the text later
144 this.complete.css('left',pos.x+'px');
144 this.complete.css('left',pos.x+'px');
145 this.complete.css('top',pos.yBot+'px');
145 this.complete.css('top',pos.yBot+'px');
146 this.complete.append(this.sel);
146 this.complete.append(this.sel);
147
147
148 $('body').append(this.complete);
148 $('body').append(this.complete);
149 //build the container
149 //build the container
150 var that = this;
150 var that = this;
151 this.sel.dblclick(function(){that.pick()});
151 this.sel.dblclick(function(){that.pick();});
152 this.sel.blur(this.close);
152 this.sel.blur(this.close);
153 this.sel.keydown(function(event){that.keydown(event)});
153 this.sel.keydown(function(event){that.keydown(event);});
154
154
155 this.build_gui_list(this.raw_result);
155 this.build_gui_list(this.raw_result);
156
156
157 this.sel.focus();
157 this.sel.focus();
158 // Opera sometimes ignores focusing a freshly created node
158 // Opera sometimes ignores focusing a freshly created node
159 if (window.opera) setTimeout(function(){if (!this.done) this.sel.focus();}, 100);
159 if (window.opera) setTimeout(function(){if (!this.done) this.sel.focus();}, 100);
160 return true;
160 return true;
161 }
161 }
162
162
163 Completer.prototype.insert = function(completion) {
163 Completer.prototype.insert = function(completion) {
164 this.editor.replaceRange(completion.str, completion.from, completion.to);
164 this.editor.replaceRange(completion.str, completion.from, completion.to);
165 }
165 }
166
166
167 Completer.prototype.build_gui_list = function(completions){
167 Completer.prototype.build_gui_list = function(completions){
168 // Need to clear the all list
168 // Need to clear the all list
169 for (var i = 0; i < completions.length; ++i) {
169 for (var i = 0; i < completions.length; ++i) {
170 var opt = $('<option/>')
170 var opt = $('<option/>')
171 .text(completions[i].str)
171 .text(completions[i].str)
172 .addClass(completions[i].type);
172 .addClass(completions[i].type);
173 this.sel.append(opt);
173 this.sel.append(opt);
174 }
174 }
175 this.sel.children().first().attr('selected','true');
175 this.sel.children().first().attr('selected','true');
176 }
176 }
177
177
178 Completer.prototype.close = function() {
178 Completer.prototype.close = function() {
179 if (this.done) return;
179 if (this.done) return;
180 this.done = true;
180 this.done = true;
181 $('.completions').remove();
181 $('.completions').remove();
182 }
182 }
183
183
184 Completer.prototype.pick = function(){
184 Completer.prototype.pick = function(){
185 this.insert(this.raw_result[this.sel[0].selectedIndex]);
185 this.insert(this.raw_result[this.sel[0].selectedIndex]);
186 this.close();
186 this.close();
187 var that = this;
187 var that = this;
188 setTimeout(function(){that.editor.focus();}, 50);
188 setTimeout(function(){that.editor.focus();}, 50);
189 }
189 }
190
190
191
191
192 Completer.prototype.keydown = function(event) {
192 Completer.prototype.keydown = function(event) {
193 var code = event.keyCode;
193 var code = event.keyCode;
194 var that = this;
194 // Enter
195 // Enter
195 if (code == key.enter) {CodeMirror.e_stop(event); this.pick();}
196 if (code == key.enter) {CodeMirror.e_stop(event); this.pick();}
196 // Escape or backspace
197 // Escape or backspace
197 else if (code == key.esc ) {CodeMirror.e_stop(event); this.close(); this.editor.focus();}
198 else if (code == key.esc ) {CodeMirror.e_stop(event); this.close(); this.editor.focus();}
198 else if (code == key.space || code == key.backspace) {this.close(); this.editor.focus();}
199 else if (code == key.space || code == key.backspace) {this.close(); this.editor.focus();}
199 else if (code == key.tab){
200 else if (code == key.tab){
200 //all the fastforwarding operation,
201 //all the fastforwarding operation,
201 //Check that shared start is not null which can append with prefixed completion
202 //Check that shared start is not null which can append with prefixed completion
202 // like %pylab , pylab have no shred start, and ff will result in py<tab><tab>
203 // like %pylab , pylab have no shred start, and ff will result in py<tab><tab>
203 // to erase py
204 // to erase py
204 var sh = sharedStart(this.raw_result);
205 var sh = sharedStart(this.raw_result);
205 if(sh){
206 if(sh){
206 this.insert(sh);
207 this.insert(sh);
207 }
208 }
208 this.close();
209 this.close();
209 CodeMirror.e_stop(event);
210 CodeMirror.e_stop(event);
210 this.editor.focus();
211 this.editor.focus();
211 //reinvoke self
212 //reinvoke self
212 var that = this;
213 setTimeout(function(){that.carryOnCompletion();}, 50);
213 setTimeout(function(){that.carryOnCompletion();}, 50);
214 }
214 }
215 else if (code == key.upArrow || code == key.downArrow) {
215 else if (code == key.upArrow || code == key.downArrow) {
216 // need to do that to be able to move the arrow
216 // need to do that to be able to move the arrow
217 // when on the first or last line ofo a code cell
217 // when on the first or last line ofo a code cell
218 event.stopPropagation();
218 event.stopPropagation();
219 }
219 }
220 else if (code != key.upArrow && code != key.downArrow) {
220 else if (code != key.upArrow && code != key.downArrow) {
221 this.close(); this.editor.focus();
221 this.close(); this.editor.focus();
222 //we give focus to the editor immediately and call sell in 50 ms
222 //we give focus to the editor immediately and call sell in 50 ms
223 var that = this;
224 setTimeout(function(){that.carryOnCompletion();}, 50);
223 setTimeout(function(){that.carryOnCompletion();}, 50);
225 }
224 }
226 }
225 }
227
226
228
227
229 IPython.Completer = Completer;
228 IPython.Completer = Completer;
230
229
231 return IPython;
230 return IPython;
232 }(IPython));
231 }(IPython));
1 NO CONTENT: modified file
NO CONTENT: modified file
@@ -1,297 +1,294 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 // Tooltip
9 // Tooltip
10 //============================================================================
10 //============================================================================
11 //
11 //
12 // you can set the autocall time by setting `IPython.notebook.time_before_tooltip` in ms
12 // you can set the autocall time by setting `IPython.tooltip.time_before_tooltip` in ms
13
13
14 var IPython = (function (IPython) {
14 var IPython = (function (IPython) {
15
15
16 var utils = IPython.utils;
16 var utils = IPython.utils;
17
17
18 // tooltip constructor
18 // tooltip constructor
19 var Tooltip = function () {
19 var Tooltip = function () {
20 var that = this;
20 var that = this;
21 this.time_before_tooltip = 1200;
21 this.time_before_tooltip = 1200;
22
22
23 // handle to html
23 // handle to html
24 this.tooltip = $('#tooltip');
24 this.tooltip = $('#tooltip');
25 var tooltip = this.tooltip;
25 var tooltip = this.tooltip;
26 this._hidden = true;
26 this._hidden = true;
27
27
28 // variable for consecutive call
28 // variable for consecutive call
29 this._old_cell = null ;
29 this._old_cell = null ;
30 this._old_request = null ;
30 this._old_request = null ;
31 this._consecutive_conter = 0;
31 this._consecutive_conter = 0;
32
32
33 // 'sticky ?'
33 // 'sticky ?'
34 this._sticky = false;
34 this._sticky = false;
35
35
36 // contain the button in the upper right corner
36 // contain the button in the upper right corner
37 this.buttons = $('<div/>')
37 this.buttons = $('<div/>')
38 .addClass('tooltipbuttons');
38 .addClass('tooltipbuttons');
39
39
40 // will contain the docstring
40 // will contain the docstring
41 this.text = $('<div/>')
41 this.text = $('<div/>')
42 .addClass('tooltiptext')
42 .addClass('tooltiptext')
43 .addClass('smalltooltip');
43 .addClass('smalltooltip');
44
44
45 // build the buttons menu on the upper right
45 // build the buttons menu on the upper right
46
46
47 // expand the tooltip to see more
47 // expand the tooltip to see more
48 var expandlink=$('<a/>').attr('href',"#")
48 var expandlink=$('<a/>').attr('href',"#")
49 .addClass("ui-corner-all") //rounded corner
49 .addClass("ui-corner-all") //rounded corner
50 .attr('role',"button")
50 .attr('role',"button")
51 .attr('id','expanbutton')
51 .attr('id','expanbutton')
52 .click(function(){that.expand()})
52 .click(function(){that.expand()})
53 .append(
53 .append(
54 $('<span/>').text('Expand')
54 $('<span/>').text('Expand')
55 .addClass('ui-icon')
55 .addClass('ui-icon')
56 .addClass('ui-icon-plus')
56 .addClass('ui-icon-plus')
57 );
57 );
58
58
59 // open in pager
59 // open in pager
60 var morelink=$('<a/>').attr('href',"#")
60 var morelink=$('<a/>').attr('href',"#")
61 .attr('role',"button")
61 .attr('role',"button")
62 .addClass('ui-button');
62 .addClass('ui-button');
63 var morespan=$('<span/>').text('Open in Pager')
63 var morespan=$('<span/>').text('Open in Pager')
64 .addClass('ui-icon')
64 .addClass('ui-icon')
65 .addClass('ui-icon-arrowstop-l-n');
65 .addClass('ui-icon-arrowstop-l-n');
66 morelink.append(morespan);
66 morelink.append(morespan);
67 morelink.click(function(){
67 morelink.click(function(){
68 that.showInPager();
68 that.showInPager();
69 });
69 });
70
70
71 // close the tooltip
71 // close the tooltip
72 var closelink=$('<a/>').attr('href',"#");
72 var closelink=$('<a/>').attr('href',"#");
73 closelink.attr('role',"button");
73 closelink.attr('role',"button");
74 closelink.addClass('ui-button');
74 closelink.addClass('ui-button');
75 var closespan=$('<span/>').text('Close');
75 var closespan=$('<span/>').text('Close');
76 closespan.addClass('ui-icon');
76 closespan.addClass('ui-icon');
77 closespan.addClass('ui-icon-close');
77 closespan.addClass('ui-icon-close');
78 closelink.append(closespan);
78 closelink.append(closespan);
79 closelink.click(function(){
79 closelink.click(function(){
80 that.remove_and_cancel_tooltip(true);
80 that.remove_and_cancel_tooltip(true);
81 });
81 });
82
82
83 //construct the tooltip
83 //construct the tooltip
84 // add in the reverse order you want them to appear
84 // add in the reverse order you want them to appear
85 this.buttons.append(closelink);
85 this.buttons.append(closelink);
86 this.buttons.append(expandlink);
86 this.buttons.append(expandlink);
87 this.buttons.append(morelink);
87 this.buttons.append(morelink);
88
88
89 // we need a phony element to make the small arrow
89 // we need a phony element to make the small arrow
90 // of the tooltip in css
90 // of the tooltip in css
91 // we will move the arrow later
91 // we will move the arrow later
92 this.arrow = $('<div/>').addClass('pretooltiparrow');
92 this.arrow = $('<div/>').addClass('pretooltiparrow');
93 this.tooltip.append(this.buttons);
93 this.tooltip.append(this.buttons);
94 this.tooltip.append(this.arrow);
94 this.tooltip.append(this.arrow);
95 this.tooltip.append(this.text);
95 this.tooltip.append(this.text);
96 };
96 };
97
97
98 // will resend the request on behalf on the cell which invoked the tooltip
99 // to show in it in pager. This is done so to be sure of having the same
100 // result as invoking `something?`
101 Tooltip.prototype.showInPager = function()
98 Tooltip.prototype.showInPager = function()
102 {
99 {
103 var that = this;
100 var that = this;
104 var callbacks = {'execute_reply': $.proxy(that._handle_execute_reply,that)}
101 var callbacks = {'execute_reply': $.proxy(that._handle_execute_reply,that)}
105 var msg_id = IPython.notebook.kernel.execute(this.name+"?", callbacks);
102 var msg_id = IPython.notebook.kernel.execute(this.name+"?", callbacks);
106
103
107 this.remove_and_cancel_tooltip();
104 this.remove_and_cancel_tooltip();
108 this._cmfocus();
105 this._cmfocus();
109 }
106 }
110
107
111 // grow the tooltip verticaly
108 // grow the tooltip verticaly
112 Tooltip.prototype.expand = function(){
109 Tooltip.prototype.expand = function(){
113 this.text.removeClass('smalltooltip');
110 this.text.removeClass('smalltooltip');
114 this.text.addClass('bigtooltip');
111 this.text.addClass('bigtooltip');
115 $('#expanbutton').addClass('hidden');
112 $('#expanbutton').addClass('hidden');
116 this._cmfocus();
113 this._cmfocus();
117 }
114 }
118
115
119 // deal with all the logic of hiding the tooltip
116 // deal with all the logic of hiding the tooltip
120 // and reset it's status
117 // and reset it's status
121 Tooltip.prototype.hide = function()
118 Tooltip.prototype.hide = function()
122 {
119 {
123 this.tooltip.addClass('hide');
120 this.tooltip.addClass('hide');
124 $('#expanbutton').removeClass('hidden');
121 $('#expanbutton').removeClass('hidden');
125 this.text.removeClass('bigtooltip');
122 this.text.removeClass('bigtooltip');
126 this.text.addClass('smalltooltip');
123 this.text.addClass('smalltooltip');
127 // keep scroll top to be sure to always see the first line
124 // keep scroll top to be sure to always see the first line
128 this.text.scrollTop(0);
125 this.text.scrollTop(0);
129 this._hidden = true;
126 this._hidden = true;
130 }
127 }
131
128
132 Tooltip.prototype.remove_and_cancel_tooltip = function(force) {
129 Tooltip.prototype.remove_and_cancel_tooltip = function(force) {
133 // note that we don't handle closing directly inside the calltip
130 // note that we don't handle closing directly inside the calltip
134 // as in the completer, because it is not focusable, so won't
131 // as in the completer, because it is not focusable, so won't
135 // get the event.
132 // get the event.
136 if(this._sticky == false || force == true)
133 if(this._sticky == false || force == true)
137 {
134 {
138 this.hide();
135 this.hide();
139 }
136 }
140 this.cancel_pending();
137 this.cancel_pending();
141 this._old_cell = null ;
138 this._old_cell = null ;
142 this._old_request = null ;
139 this._old_request = null ;
143 this._consecutive_conter = 0;
140 this._consecutive_conter = 0;
144 }
141 }
145
142
146 // cancel autocall done after '(' for example.
143 // cancel autocall done after '(' for example.
147 Tooltip.prototype.cancel_pending = function(){
144 Tooltip.prototype.cancel_pending = function(){
148 if (this.tooltip_timeout != null){
145 if (this.tooltip_timeout != null){
149 clearTimeout(this.tooltip_timeout);
146 clearTimeout(this.tooltip_timeout);
150 this.tooltip_timeout = null;
147 this.tooltip_timeout = null;
151 }
148 }
152 }
149 }
153
150
154 // will trigger tooltip after timeout
151 // will trigger tooltip after timeout
155 Tooltip.prototype.pending = function(cell,text)
152 Tooltip.prototype.pending = function(cell,text)
156 {
153 {
157 var that = this;
154 var that = this;
158 this.tooltip_timeout = setTimeout(function(){that.request(cell)} , that.time_before_tooltip);
155 this.tooltip_timeout = setTimeout(function(){that.request(cell)} , that.time_before_tooltip);
159 }
156 }
160
157
161 // make an imediate completion request
158 // make an imediate completion request
162 Tooltip.prototype.request = function(cell)
159 Tooltip.prototype.request = function(cell)
163 {
160 {
164 this.cancel_pending();
161 this.cancel_pending();
165 var editor = cell.code_mirror;
162 var editor = cell.code_mirror;
166 this.code_mirror = editor;
163 this.code_mirror = editor;
167 var cursor = editor.getCursor();
164 var cursor = editor.getCursor();
168 var text = editor.getRange({line:cursor.line,ch:0},cursor).trim();
165 var text = editor.getRange({line:cursor.line,ch:0},cursor).trim();
169
166
170 if( this._old_cell == cell && this._old_request == text && this._hidden == false)
167 if( this._old_cell == cell && this._old_request == text && this._hidden == false)
171 {
168 {
172 this._consecutive_conter = this._consecutive_conter +1;
169 this._consecutive_conter = this._consecutive_conter +1;
173 } else {
170 } else {
174 this._old_cell = cell ;
171 this._old_cell = cell ;
175 this._old_request = text ;
172 this._old_request = text ;
176 this._consecutive_conter =0;
173 this._consecutive_conter =0;
177 this.cancel_stick();
174 this.cancel_stick();
178 }
175 }
179
176
180 if( this._consecutive_conter == 1 )
177 if( this._consecutive_conter == 1 )
181 {
178 {
182 this.expand()
179 this.expand()
183 return;
180 return;
184 }
181 }
185 else if( this._consecutive_conter == 2)
182 else if( this._consecutive_conter == 2)
186 {
183 {
187 this.stick();
184 this.stick();
188 return;
185 return;
189 }
186 }
190 else if( this._consecutive_conter == 3)
187 else if( this._consecutive_conter == 3)
191 {
188 {
192 this._old_cell = null ;
189 this._old_cell = null ;
193 this.cancel_stick();
190 this.cancel_stick();
194 this._old_request = null ;
191 this._old_request = null ;
195 this._consecutive_conter = 0;
192 this._consecutive_conter = 0;
196 this.showInPager();
193 this.showInPager();
197 this._cmfocus();
194 this._cmfocus();
198 return;
195 return;
199 }
196 }
200 else if( this._consecutive_conter == 4)
197 else if( this._consecutive_conter == 4)
201 {
198 {
202
199
203 }
200 }
204
201
205 if (text === "" || text === "(" ) {
202 if (text === "" || text === "(" ) {
206 return;
203 return;
207 // don't do anything if line beggin with '(' or is empty
204 // don't do anything if line beggin with '(' or is empty
208 }
205 }
209 cell.request_tooltip(text);
206 cell.request_tooltip(text);
210 }
207 }
211
208
212 // cancel the option of having the tooltip to stick
209 // cancel the option of having the tooltip to stick
213 Tooltip.prototype.cancel_stick = function()
210 Tooltip.prototype.cancel_stick = function()
214 {
211 {
215 clearTimeout(this._stick_timeout);
212 clearTimeout(this._stick_timeout);
216 this._sticky = false;
213 this._sticky = false;
217 }
214 }
218
215
219 // put the tooltip in a sicky state for 10 seconds
216 // put the tooltip in a sicky state for 10 seconds
220 // it won't be removed by remove_and_cancell() unless you called with
217 // it won't be removed by remove_and_cancell() unless you called with
221 // the first parameter set to true.
218 // the first parameter set to true.
222 // remove_and_cancell_tooltip(true)
219 // remove_and_cancell_tooltip(true)
223 Tooltip.prototype.stick = function()
220 Tooltip.prototype.stick = function()
224 {
221 {
225 var that = this;
222 var that = this;
226 this._sticky = true;
223 this._sticky = true;
227 this._stick_timeout = setTimeout( function(){
224 this._stick_timeout = setTimeout( function(){
228 that._sticky = false;
225 that._sticky = false;
229 }, 10*1000
226 }, 10*1000
230 );
227 );
231 }
228 }
232
229
233 // should be called with the kernel reply to actually show the tooltip
230 // should be called with the kernel reply to actually show the tooltip
234 Tooltip.prototype.show = function(reply, codecell)
231 Tooltip.prototype.show = function(reply, codecell)
235 {
232 {
236 // move the bubble if it is not hidden
233 // move the bubble if it is not hidden
237 // otherwise fade it
234 // otherwise fade it
238 var editor = codecell.code_mirror;
235 var editor = codecell.code_mirror;
239 this.name = reply.name;
236 this.name = reply.name;
240 this.code_mirror = editor;
237 this.code_mirror = editor;
241
238
242 // do some math to have the tooltip arrow on more or less on left or right
239 // do some math to have the tooltip arrow on more or less on left or right
243 // width of the editor
240 // width of the editor
244 var w= $(this.code_mirror.getScrollerElement()).width();
241 var w= $(this.code_mirror.getScrollerElement()).width();
245 // ofset of the editor
242 // ofset of the editor
246 var o= $(this.code_mirror.getScrollerElement()).offset();
243 var o= $(this.code_mirror.getScrollerElement()).offset();
247 var pos = editor.cursorCoords();
244 var pos = editor.cursorCoords();
248 var xinit = pos.x;
245 var xinit = pos.x;
249 var xinter = o.left + (xinit-o.left)/w*(w-450);
246 var xinter = o.left + (xinit-o.left)/w*(w-450);
250 var posarrowleft = xinit - xinter;
247 var posarrowleft = xinit - xinter;
251
248
252
249
253 if( this._hidden == false)
250 if( this._hidden == false)
254 {
251 {
255 this.tooltip.animate({'left' : xinter-30+'px','top' :(pos.yBot+10)+'px'});
252 this.tooltip.animate({'left' : xinter-30+'px','top' :(pos.yBot+10)+'px'});
256 } else
253 } else
257 {
254 {
258 this.tooltip.css({'left' : xinter-30+'px'});
255 this.tooltip.css({'left' : xinter-30+'px'});
259 this.tooltip.css({'top' :(pos.yBot+10)+'px'});
256 this.tooltip.css({'top' :(pos.yBot+10)+'px'});
260 }
257 }
261 this.arrow.animate({'left' : posarrowleft+'px'});
258 this.arrow.animate({'left' : posarrowleft+'px'});
262 this.tooltip.removeClass('hidden')
259 this.tooltip.removeClass('hidden')
263 this.tooltip.removeClass('hide');
260 this.tooltip.removeClass('hide');
264 this._hidden = false;
261 this._hidden = false;
265
262
266 // build docstring
263 // build docstring
267 defstring = reply.call_def;
264 defstring = reply.call_def;
268 if (defstring == null) { defstring = reply.init_definition; }
265 if (defstring == null) { defstring = reply.init_definition; }
269 if (defstring == null) { defstring = reply.definition; }
266 if (defstring == null) { defstring = reply.definition; }
270
267
271 docstring = reply.call_docstring;
268 docstring = reply.call_docstring;
272 if (docstring == null) { docstring = reply.init_docstring; }
269 if (docstring == null) { docstring = reply.init_docstring; }
273 if (docstring == null) { docstring = reply.docstring; }
270 if (docstring == null) { docstring = reply.docstring; }
274 if (docstring == null) { docstring = "<empty docstring>"; }
271 if (docstring == null) { docstring = "<empty docstring>"; }
275
272
276 this.text.children().remove();
273 this.text.children().remove();
277
274
278 var pre=$('<pre/>').html(utils.fixConsole(docstring));
275 var pre=$('<pre/>').html(utils.fixConsole(docstring));
279 if(defstring){
276 if(defstring){
280 var defstring_html = $('<pre/>').html(utils.fixConsole(defstring));
277 var defstring_html = $('<pre/>').html(utils.fixConsole(defstring));
281 this.text.append(defstring_html);
278 this.text.append(defstring_html);
282 }
279 }
283 this.text.append(pre);
280 this.text.append(pre);
284 // keep scroll top to be sure to always see the first line
281 // keep scroll top to be sure to always see the first line
285 this.text.scrollTop(0);
282 this.text.scrollTop(0);
286 }
283 }
287
284
288 // convenient funciton to have the correct codemirror back into focus
285 // convenient funciton to have the correct codemirror back into focus
289 Tooltip.prototype._cmfocus = function()
286 Tooltip.prototype._cmfocus = function()
290 {
287 {
291 var cm = this.code_mirror;
288 var cm = this.code_mirror;
292 setTimeout(function(){cm.focus();}, 50);
289 setTimeout(function(){cm.focus();}, 50);
293 }
290 }
294
291
295 IPython.Tooltip = Tooltip;
292 IPython.Tooltip = Tooltip;
296 return IPython;
293 return IPython;
297 }(IPython));
294 }(IPython));
General Comments 0
You need to be logged in to leave comments. Login now