##// END OF EJS Templates
Removing IPython.notebook references from tooltip.js
Brian E. Granger -
Show More
@@ -1,375 +1,376
1 1 //----------------------------------------------------------------------------
2 2 // Copyright (C) 2008-2011 The IPython Development Team
3 3 //
4 4 // Distributed under the terms of the BSD License. The full license is in
5 5 // the file COPYING, distributed as part of this software.
6 6 //----------------------------------------------------------------------------
7 7 //============================================================================
8 8 // Tooltip
9 9 //============================================================================
10 10 //
11 11 // you can set the autocall time by setting `IPython.tooltip.time_before_tooltip` in ms
12 12 //
13 13 // you can configure the differents action of pressing tab several times in a row by
14 14 // setting/appending different fonction in the array
15 15 // IPython.tooltip.tabs_functions
16 16 //
17 17 // eg :
18 18 // IPython.tooltip.tabs_functions[4] = function (){console.log('this is the action of the 4th tab pressing')}
19 19 //
20 20 var IPython = (function (IPython) {
21 21 "use strict";
22 22
23 23 var utils = IPython.utils;
24 24
25 25 // tooltip constructor
26 26 var Tooltip = function () {
27 27 var that = this;
28 28 this.time_before_tooltip = 1200;
29 29
30 30 // handle to html
31 31 this.tooltip = $('#tooltip');
32 32 this._hidden = true;
33 33
34 34 // variable for consecutive call
35 35 this._old_cell = null;
36 36 this._old_request = null;
37 37 this._consecutive_counter = 0;
38 38
39 39 // 'sticky ?'
40 40 this._sticky = false;
41 41
42 42 // contain the button in the upper right corner
43 43 this.buttons = $('<div/>').addClass('tooltipbuttons');
44 44
45 45 // will contain the docstring
46 46 this.text = $('<div/>').addClass('tooltiptext').addClass('smalltooltip');
47 47
48 48 // build the buttons menu on the upper right
49 49 // expand the tooltip to see more
50 50 var expandlink = $('<a/>').attr('href', "#").addClass("ui-corner-all") //rounded corner
51 51 .attr('role', "button").attr('id', 'expanbutton').attr('title', 'Grow the tooltip vertically (press tab 2 times)').click(function () {
52 52 that.expand()
53 53 }).append(
54 54 $('<span/>').text('Expand').addClass('ui-icon').addClass('ui-icon-plus'));
55 55
56 56 // open in pager
57 57 var morelink = $('<a/>').attr('href', "#").attr('role', "button").addClass('ui-button').attr('title', 'show the current docstring in pager (press tab 4 times)');
58 58 var morespan = $('<span/>').text('Open in Pager').addClass('ui-icon').addClass('ui-icon-arrowstop-l-n');
59 59 morelink.append(morespan);
60 60 morelink.click(function () {
61 61 that.showInPager();
62 62 });
63 63
64 64 // close the tooltip
65 65 var closelink = $('<a/>').attr('href', "#").attr('role', "button").addClass('ui-button');
66 66 var closespan = $('<span/>').text('Close').addClass('ui-icon').addClass('ui-icon-close');
67 67 closelink.append(closespan);
68 68 closelink.click(function () {
69 69 that.remove_and_cancel_tooltip(true);
70 70 });
71 71
72 72 this._clocklink = $('<a/>').attr('href', "#");
73 73 this._clocklink.attr('role', "button");
74 74 this._clocklink.addClass('ui-button');
75 75 this._clocklink.attr('title', 'Tootip is not dismissed while typing for 10 seconds');
76 76 var clockspan = $('<span/>').text('Close');
77 77 clockspan.addClass('ui-icon');
78 78 clockspan.addClass('ui-icon-clock');
79 79 this._clocklink.append(clockspan);
80 80 this._clocklink.click(function () {
81 81 that.cancel_stick();
82 82 });
83 83
84 84
85 85
86 86
87 87 //construct the tooltip
88 88 // add in the reverse order you want them to appear
89 89 this.buttons.append(closelink);
90 90 this.buttons.append(expandlink);
91 91 this.buttons.append(morelink);
92 92 this.buttons.append(this._clocklink);
93 93 this._clocklink.hide();
94 94
95 95
96 96 // we need a phony element to make the small arrow
97 97 // of the tooltip in css
98 98 // we will move the arrow later
99 99 this.arrow = $('<div/>').addClass('pretooltiparrow');
100 100 this.tooltip.append(this.buttons);
101 101 this.tooltip.append(this.arrow);
102 102 this.tooltip.append(this.text);
103 103
104 104 // function that will be called if you press tab 1, 2, 3... times in a row
105 105 this.tabs_functions = [function (cell, text) {
106 106 that._request_tooltip(cell, text);
107 107 }, function () {
108 108 that.expand();
109 109 }, function () {
110 110 that.stick();
111 111 }, function (cell) {
112 112 that.cancel_stick();
113 113 that.showInPager(cell);
114 114 that._cmfocus();
115 115 }];
116 116 // call after all the tabs function above have bee call to clean their effects
117 117 // if necessary
118 118 this.reset_tabs_function = function (cell, text) {
119 119 this._old_cell = (cell) ? cell : null;
120 120 this._old_request = (text) ? text : null;
121 121 this._consecutive_counter = 0;
122 122 }
123 123 };
124 124
125 125 Tooltip.prototype.showInPager = function (cell) {
126 126 // reexecute last call in pager by appending ? to show back in pager
127 127 var that = this;
128 128 var empty = function () {};
129 IPython.notebook.kernel.execute(
129 cell.kernel.execute(
130 130 that.name + '?', {
131 131 'execute_reply': empty,
132 132 'output': empty,
133 133 'clear_output': empty,
134 134 'cell': cell
135 135 }, {
136 136 'silent': false
137 137 });
138 138 this.remove_and_cancel_tooltip();
139 139 this._cmfocus();
140 140 }
141 141
142 142 // grow the tooltip verticaly
143 143 Tooltip.prototype.expand = function () {
144 144 this.text.removeClass('smalltooltip');
145 145 this.text.addClass('bigtooltip');
146 146 $('#expanbutton').hide('slow');
147 147 this._cmfocus();
148 148 }
149 149
150 150 // deal with all the logic of hiding the tooltip
151 151 // and reset it's status
152 152 Tooltip.prototype._hide = function () {
153 153 this.tooltip.fadeOut('fast');
154 154 $('#expanbutton').show('slow');
155 155 this.text.removeClass('bigtooltip');
156 156 this.text.addClass('smalltooltip');
157 157 // keep scroll top to be sure to always see the first line
158 158 this.text.scrollTop(0);
159 159 this._hidden = true;
160 160 this.code_mirror = null;
161 161 }
162 162
163 163 Tooltip.prototype.remove_and_cancel_tooltip = function (force) {
164 164 // note that we don't handle closing directly inside the calltip
165 165 // as in the completer, because it is not focusable, so won't
166 166 // get the event.
167 167 if (this._sticky == false || force == true) {
168 168 this.cancel_stick();
169 169 this._hide();
170 170 }
171 171 this.cancel_pending();
172 172 this.reset_tabs_function();
173 173 this._cmfocus();
174 174 }
175 175
176 176 // cancel autocall done after '(' for example.
177 177 Tooltip.prototype.cancel_pending = function () {
178 178 if (this._tooltip_timeout != null) {
179 179 clearTimeout(this._tooltip_timeout);
180 180 this._tooltip_timeout = null;
181 181 }
182 182 }
183 183
184 184 // will trigger tooltip after timeout
185 185 Tooltip.prototype.pending = function (cell) {
186 186 var that = this;
187 187 this._tooltip_timeout = setTimeout(function () {
188 188 that.request(cell)
189 189 }, that.time_before_tooltip);
190 190 }
191 191
192 192 Tooltip.prototype._request_tooltip = function (cell, func) {
193 193 // use internally just to make the request to the kernel
194 194 // Feel free to shorten this logic if you are better
195 195 // than me in regEx
196 196 // basicaly you shoul be able to get xxx.xxx.xxx from
197 197 // something(range(10), kwarg=smth) ; xxx.xxx.xxx( firstarg, rand(234,23), kwarg1=2,
198 198 // remove everything between matchin bracket (need to iterate)
199 199 var matchBracket = /\([^\(\)]+\)/g;
200 200 var endBracket = /\([^\(]*$/g;
201 201 var oldfunc = func;
202 202
203 203 func = func.replace(matchBracket, "");
204 204 while (oldfunc != func) {
205 205 oldfunc = func;
206 206 func = func.replace(matchBracket, "");
207 207 }
208 208 // remove everything after last open bracket
209 209 func = func.replace(endBracket, "");
210 210
211 211 var re = /[a-z_][0-9a-z._]+$/gi; // casse insensitive
212 212 var callbacks = {
213 213 'object_info_reply': $.proxy(this._show, this)
214 214 }
215 var msg_id = IPython.notebook.kernel.object_info_request(re.exec(func), callbacks);
215 var msg_id = cell.kernel.object_info_request(re.exec(func), callbacks);
216 216 }
217 217
218 218 // make an imediate completion request
219 219 Tooltip.prototype.request = function (cell) {
220 220 // request(codecell)
221 221 // Deal with extracting the text from the cell and counting
222 222 // call in a row
223 223 this.cancel_pending();
224 224 var editor = cell.code_mirror;
225 225 var cursor = editor.getCursor();
226 226 var text = editor.getRange({
227 227 line: cursor.line,
228 228 ch: 0
229 229 }, cursor).trim();
230 230
231 231 if(editor.somethingSelected()){
232 232 text = editor.getSelection();
233 233 }
234 234
235 235 // need a permanent handel to code_mirror for future auto recall
236 236 this.code_mirror = editor;
237 237
238 238 // now we treat the different number of keypress
239 239 // first if same cell, same text, increment counter by 1
240 240 if (this._old_cell == cell && this._old_request == text && this._hidden == false) {
241 241 this._consecutive_counter++;
242 242 } else {
243 243 // else reset
244 244 this.cancel_stick();
245 245 this.reset_tabs_function (cell, text);
246 246 }
247 247
248 248 // don't do anything if line beggin with '(' or is empty
249 249 if (text === "" || text === "(") {
250 250 return;
251 251 }
252 252
253 253 this.tabs_functions[this._consecutive_counter](cell, text);
254 254
255 255 // then if we are at the end of list function, reset
256 256 if (this._consecutive_counter == this.tabs_functions.length) this.reset_tabs_function (cell, text);
257 257
258 258 return;
259 259 }
260 260
261 261 // cancel the option of having the tooltip to stick
262 262 Tooltip.prototype.cancel_stick = function () {
263 263 clearTimeout(this._stick_timeout);
264 264 this._stick_timeout = null;
265 265 this._clocklink.hide('slow');
266 266 this._sticky = false;
267 267 }
268 268
269 269 // put the tooltip in a sicky state for 10 seconds
270 270 // it won't be removed by remove_and_cancell() unless you called with
271 271 // the first parameter set to true.
272 272 // remove_and_cancell_tooltip(true)
273 273 Tooltip.prototype.stick = function (time) {
274 274 time = (time != undefined) ? time : 10;
275 275 var that = this;
276 276 this._sticky = true;
277 277 this._clocklink.show('slow');
278 278 this._stick_timeout = setTimeout(function () {
279 279 that._sticky = false;
280 280 that._clocklink.hide('slow');
281 281 }, time * 1000);
282 282 }
283 283
284 284 // should be called with the kernel reply to actually show the tooltip
285 285 Tooltip.prototype._show = function (reply) {
286 286 // move the bubble if it is not hidden
287 287 // otherwise fade it
288 288 this.name = reply.name;
289 289
290 290 // do some math to have the tooltip arrow on more or less on left or right
291 291 // width of the editor
292 292 var w = $(this.code_mirror.getScrollerElement()).width();
293 293 // ofset of the editor
294 294 var o = $(this.code_mirror.getScrollerElement()).offset();
295 295
296 296 // whatever anchor/head order but arrow at mid x selection
297 297 var anchor = this.code_mirror.cursorCoords(false);
298 298 var head = this.code_mirror.cursorCoords(true);
299 299 var pos = {};
300 300 pos.y = head.y
301 301 pos.yBot = head.yBot
302 302 pos.x = (head.x+anchor.x)/2;
303 303
304 304 var xinit = pos.x;
305 305 var xinter = o.left + (xinit - o.left) / w * (w - 450);
306 306 var posarrowleft = xinit - xinter;
307 307
308 308
309 309 if (this._hidden == false) {
310 310 this.tooltip.animate({
311 311 'left': xinter - 30 + 'px',
312 312 'top': (pos.yBot + 10) + 'px'
313 313 });
314 314 } else {
315 315 this.tooltip.css({
316 316 'left': xinter - 30 + 'px'
317 317 });
318 318 this.tooltip.css({
319 319 'top': (pos.yBot + 10) + 'px'
320 320 });
321 321 }
322 322 this.arrow.animate({
323 323 'left': posarrowleft + 'px'
324 324 });
325 325 this.tooltip.fadeIn('fast');
326 326 this._hidden = false;
327 327
328 328 // build docstring
329 329 var defstring = reply.call_def;
330 330 if (defstring == null) {
331 331 defstring = reply.init_definition;
332 332 }
333 333 if (defstring == null) {
334 334 defstring = reply.definition;
335 335 }
336 336
337 337 var docstring = reply.call_docstring;
338 338 if (docstring == null) {
339 339 docstring = reply.init_docstring;
340 340 }
341 341 if (docstring == null) {
342 342 docstring = reply.docstring;
343 343 }
344 344 if (docstring == null) {
345 345 docstring = "<empty docstring>";
346 346 }
347 347
348 348 this.text.children().remove();
349 349
350 350 var pre = $('<pre/>').html(utils.fixConsole(docstring));
351 351 if (defstring) {
352 352 var defstring_html = $('<pre/>').html(utils.fixConsole(defstring));
353 353 this.text.append(defstring_html);
354 354 }
355 355 this.text.append(pre);
356 356 // keep scroll top to be sure to always see the first line
357 357 this.text.scrollTop(0);
358 358 }
359 359
360 360 // convenient funciton to have the correct code_mirror back into focus
361 361 Tooltip.prototype._cmfocus = function () {
362 362 var cm = this.code_mirror;
363 if (cm == IPython.notebook.get_selected_cell())
364 {
365 setTimeout(function () {
366 cm.focus();
367 }, 50);
363 if (IPython.notebook !== undefined) {
364 if (cm == IPython.notebook.get_selected_cell()) {
365 setTimeout(function () {
366 cm.focus();
367 }, 50);
368 }
368 369 }
369 370 }
370 371
371 372 IPython.Tooltip = Tooltip;
372 373
373 374 return IPython;
374 375
375 376 }(IPython));
General Comments 0
You need to be logged in to leave comments. Login now