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