##// END OF EJS Templates
Merge pull request #2728 from Carreau/shifttab...
Merge pull request #2728 from Carreau/shifttab also bind shift tab for tooltip + config This does not change the curent behavior, only add the shift+tab shortcut. Note that the shift tab shortcut has a slightly different behavior. You can select part of a line and pressing shift-tab will show you the tooltip only for the selection. This is disabled for multiline selection to still allow to unindent block of code, Keep in mind that the real real shortcut for indent unindent is Ctrl+] or [ . Select/tab is not really supported by codemirror. Finally the "tooltip_on_tab" behavior is globally configurable via IPython.config so that it could be easily switched to false. It can be overridden via js console for test purpose. IPython.config.tooltip_on_tab = true | false Take effect immediately, only on current notebook. or globally via custom.js var user_conf = {tooltip_on_tab:false | true}; $.extend(IPython.config, user_conf)

File last commit:

r8949:77fe6f1f
r8971:99339d10 merge
Show More
tooltip.js
375 lines | 13.2 KiB | application/javascript | JavascriptLexer
Matthias Bussonnier
tooltip to mac
r7145 //----------------------------------------------------------------------------
// Copyright (C) 2008-2011 The IPython Development Team
//
// Distributed under the terms of the BSD License. The full license is in
// the file COPYING, distributed as part of this software.
//----------------------------------------------------------------------------
//============================================================================
// Tooltip
//============================================================================
Matthias Bussonnier
fix scrolltop
r7151 //
Matthias BUSSONNIER
Clean code, retab and minor fix...
r7170 // you can set the autocall time by setting `IPython.tooltip.time_before_tooltip` in ms
Matthias BUSSONNIER
make tooltip tabs fonction configurable
r7172 //
Matthias BUSSONNIER
clean code, show clock if tooltip is 'sticky'...
r7173 // you can configure the differents action of pressing tab several times in a row by
// setting/appending different fonction in the array
Matthias BUSSONNIER
make tooltip tabs fonction configurable
r7172 // IPython.tooltip.tabs_functions
//
// eg :
Matthias BUSSONNIER
space before function keyword in js
r7191 // IPython.tooltip.tabs_functions[4] = function (){console.log('this is the action of the 4th tab pressing')}
Matthias BUSSONNIER
make tooltip tabs fonction configurable
r7172 //
Matthias BUSSONNIER
space before function keyword in js
r7191 var IPython = (function (IPython) {
Matthias BUSSONNIER
clean code, show clock if tooltip is 'sticky'...
r7173 "use strict";
Matthias Bussonnier
tooltip to mac
r7145
var utils = IPython.utils;
Matthias BUSSONNIER
clean code, show clock if tooltip is 'sticky'...
r7173
Matthias BUSSONNIER
clean and comment tooltip file
r7162 // tooltip constructor
Matthias BUSSONNIER
space before function keyword in js
r7191 var Tooltip = function () {
Matthias BUSSONNIER
beautify tooltip.js
r7189 var that = this;
this.time_before_tooltip = 1200;
Matthias BUSSONNIER
clean and comment tooltip file
r7162
Matthias BUSSONNIER
beautify tooltip.js
r7189 // handle to html
this.tooltip = $('#tooltip');
this._hidden = true;
Matthias BUSSONNIER
animation if already shown
r7153
Matthias BUSSONNIER
beautify tooltip.js
r7189 // variable for consecutive call
this._old_cell = null;
this._old_request = null;
this._consecutive_counter = 0;
Matthias BUSSONNIER
multiple tooltip action...
r7160
Matthias BUSSONNIER
beautify tooltip.js
r7189 // 'sticky ?'
this._sticky = false;
Matthias BUSSONNIER
multiple tooltip action...
r7160
Matthias BUSSONNIER
beautify tooltip.js
r7189 // contain the button in the upper right corner
this.buttons = $('<div/>').addClass('tooltipbuttons');
// will contain the docstring
this.text = $('<div/>').addClass('tooltiptext').addClass('smalltooltip');
// build the buttons menu on the upper right
// expand the tooltip to see more
var expandlink = $('<a/>').attr('href', "#").addClass("ui-corner-all") //rounded corner
Matthias BUSSONNIER
space before function keyword in js
r7191 .attr('role', "button").attr('id', 'expanbutton').attr('title', 'Grow the tooltip vertically (press tab 2 times)').click(function () {
Matthias BUSSONNIER
beautify tooltip.js
r7189 that.expand()
}).append(
$('<span/>').text('Expand').addClass('ui-icon').addClass('ui-icon-plus'));
// open in pager
var morelink = $('<a/>').attr('href', "#").attr('role', "button").addClass('ui-button').attr('title', 'show the current docstring in pager (press tab 4 times)');
var morespan = $('<span/>').text('Open in Pager').addClass('ui-icon').addClass('ui-icon-arrowstop-l-n');
morelink.append(morespan);
Matthias BUSSONNIER
space before function keyword in js
r7191 morelink.click(function () {
Matthias BUSSONNIER
beautify tooltip.js
r7189 that.showInPager();
});
Matthias BUSSONNIER
improve new tooltip
r7147
Matthias BUSSONNIER
beautify tooltip.js
r7189 // close the tooltip
var closelink = $('<a/>').attr('href', "#").attr('role', "button").addClass('ui-button');
var closespan = $('<span/>').text('Close').addClass('ui-icon').addClass('ui-icon-close');
closelink.append(closespan);
Matthias BUSSONNIER
space before function keyword in js
r7191 closelink.click(function () {
Matthias BUSSONNIER
beautify tooltip.js
r7189 that.remove_and_cancel_tooltip(true);
Matthias BUSSONNIER
improve new tooltip
r7147 });
Matthias BUSSONNIER
clean and comment tooltip file
r7162
Matthias BUSSONNIER
beautify tooltip.js
r7189 this._clocklink = $('<a/>').attr('href', "#");
this._clocklink.attr('role', "button");
this._clocklink.addClass('ui-button');
this._clocklink.attr('title', 'Tootip is not dismissed while typing for 10 seconds');
var clockspan = $('<span/>').text('Close');
Matthias BUSSONNIER
clean code, show clock if tooltip is 'sticky'...
r7173 clockspan.addClass('ui-icon');
clockspan.addClass('ui-icon-clock');
Matthias BUSSONNIER
beautify tooltip.js
r7189 this._clocklink.append(clockspan);
Matthias BUSSONNIER
space before function keyword in js
r7191 this._clocklink.click(function () {
Matthias BUSSONNIER
beautify tooltip.js
r7189 that.cancel_stick();
Matthias BUSSONNIER
clean code, show clock if tooltip is 'sticky'...
r7173 });
Matthias BUSSONNIER
beautify tooltip.js
r7189 //construct the tooltip
// add in the reverse order you want them to appear
this.buttons.append(closelink);
this.buttons.append(expandlink);
this.buttons.append(morelink);
this.buttons.append(this._clocklink);
this._clocklink.hide();
// we need a phony element to make the small arrow
// of the tooltip in css
// we will move the arrow later
this.arrow = $('<div/>').addClass('pretooltiparrow');
this.tooltip.append(this.buttons);
this.tooltip.append(this.arrow);
this.tooltip.append(this.text);
// function that will be called if you press tab 1, 2, 3... times in a row
Matthias BUSSONNIER
space before function keyword in js
r7191 this.tabs_functions = [function (cell, text) {
Matthias BUSSONNIER
beautify tooltip.js
r7189 that._request_tooltip(cell, text);
Matthias BUSSONNIER
space before function keyword in js
r7191 }, function () {
Matthias BUSSONNIER
beautify tooltip.js
r7189 that.expand();
Matthias BUSSONNIER
space before function keyword in js
r7191 }, function () {
Matthias BUSSONNIER
beautify tooltip.js
r7189 that.stick();
Matthias BUSSONNIER
space before function keyword in js
r7191 }, function (cell) {
Matthias BUSSONNIER
beautify tooltip.js
r7189 that.cancel_stick();
that.showInPager(cell);
that._cmfocus();
}];
// call after all the tabs function above have bee call to clean their effects
// if necessary
Matthias BUSSONNIER
space before function keyword in js
r7191 this.reset_tabs_function = function (cell, text) {
Matthias BUSSONNIER
beautify tooltip.js
r7189 this._old_cell = (cell) ? cell : null;
this._old_request = (text) ? text : null;
this._consecutive_counter = 0;
}
};
Matthias BUSSONNIER
space before function keyword in js
r7191 Tooltip.prototype.showInPager = function (cell) {
Matthias BUSSONNIER
make tooltip tabs fonction configurable
r7172 // reexecute last call in pager by appending ? to show back in pager
var that = this;
Matthias BUSSONNIER
space before function keyword in js
r7191 var empty = function () {};
Matthias BUSSONNIER
tooltip, pager bring pager...
r7184 IPython.notebook.kernel.execute(
Matthias BUSSONNIER
beautify tooltip.js
r7189 that.name + '?', {
'execute_reply': empty,
'output': empty,
'clear_output': empty,
'cell': cell
}, {
'silent': false
});
Matthias BUSSONNIER
make tooltip tabs fonction configurable
r7172 this.remove_and_cancel_tooltip();
this._cmfocus();
Matthias BUSSONNIER
multiple tooltip action...
r7160 }
Matthias BUSSONNIER
clean and comment tooltip file
r7162 // grow the tooltip verticaly
Matthias BUSSONNIER
space before function keyword in js
r7191 Tooltip.prototype.expand = function () {
Matthias BUSSONNIER
multiple tooltip action...
r7160 this.text.removeClass('smalltooltip');
this.text.addClass('bigtooltip');
Matthias BUSSONNIER
clean code, show clock if tooltip is 'sticky'...
r7173 $('#expanbutton').hide('slow');
Matthias BUSSONNIER
multiple tooltip action...
r7160 this._cmfocus();
}
Matthias Bussonnier
fix scrolltop
r7151 // deal with all the logic of hiding the tooltip
// and reset it's status
Matthias BUSSONNIER
rename show/hide methods to avoid jQuery conflict....
r7202 Tooltip.prototype._hide = function () {
this.tooltip.fadeOut('fast');
Matthias BUSSONNIER
beautify tooltip.js
r7189 $('#expanbutton').show('slow');
this.text.removeClass('bigtooltip');
this.text.addClass('smalltooltip');
// keep scroll top to be sure to always see the first line
this.text.scrollTop(0);
this._hidden = true;
Matthias BUSSONNIER
fix tooltip keep focus on wrong cell...
r7204 this.code_mirror = null;
Matthias Bussonnier
fix scrolltop
r7151 }
Matthias Bussonnier
tooltip to mac
r7145
Matthias BUSSONNIER
space before function keyword in js
r7191 Tooltip.prototype.remove_and_cancel_tooltip = function (force) {
Matthias Bussonnier
tooltip to mac
r7145 // note that we don't handle closing directly inside the calltip
// as in the completer, because it is not focusable, so won't
// get the event.
Matthias BUSSONNIER
beautify tooltip.js
r7189 if (this._sticky == false || force == true) {
Matthias BUSSONNIER
click on close cancell stick
r7206 this.cancel_stick();
Matthias BUSSONNIER
rename show/hide methods to avoid jQuery conflict....
r7202 this._hide();
Matthias BUSSONNIER
multiple tooltip action...
r7160 }
this.cancel_pending();
Matthias BUSSONNIER
rename show/hide methods to avoid jQuery conflict....
r7202 this.reset_tabs_function();
this._cmfocus();
Matthias BUSSONNIER
multiple tooltip action...
r7160 }
Matthias BUSSONNIER
clean and comment tooltip file
r7162 // cancel autocall done after '(' for example.
Matthias BUSSONNIER
space before function keyword in js
r7191 Tooltip.prototype.cancel_pending = function () {
Matthias BUSSONNIER
beautify tooltip.js
r7189 if (this._tooltip_timeout != null) {
Matthias BUSSONNIER
clean code, show clock if tooltip is 'sticky'...
r7173 clearTimeout(this._tooltip_timeout);
this._tooltip_timeout = null;
Matthias Bussonnier
tooltip to mac
r7145 }
}
Matthias BUSSONNIER
clean and comment tooltip file
r7162
// will trigger tooltip after timeout
Matthias BUSSONNIER
space before function keyword in js
r7191 Tooltip.prototype.pending = function (cell) {
Matthias BUSSONNIER
call tooltip after time
r7157 var that = this;
Matthias BUSSONNIER
space before function keyword in js
r7191 this._tooltip_timeout = setTimeout(function () {
Matthias BUSSONNIER
beautify tooltip.js
r7189 that.request(cell)
}, that.time_before_tooltip);
Matthias BUSSONNIER
call tooltip after time
r7157 }
Matthias BUSSONNIER
clean code, show clock if tooltip is 'sticky'...
r7173
Matthias BUSSONNIER
space before function keyword in js
r7191 Tooltip.prototype._request_tooltip = function (cell, func) {
Matthias BUSSONNIER
beautify tooltip.js
r7189 // use internally just to make the request to the kernel
// Feel free to shorten this logic if you are better
// than me in regEx
// basicaly you shoul be able to get xxx.xxx.xxx from
// something(range(10), kwarg=smth) ; xxx.xxx.xxx( firstarg, rand(234,23), kwarg1=2,
// remove everything between matchin bracket (need to iterate)
var matchBracket = /\([^\(\)]+\)/g;
var endBracket = /\([^\(]*$/g;
var oldfunc = func;
func = func.replace(matchBracket, "");
while (oldfunc != func) {
oldfunc = func;
func = func.replace(matchBracket, "");
}
// remove everything after last open bracket
func = func.replace(endBracket, "");
var re = /[a-z_][0-9a-z._]+$/gi; // casse insensitive
var callbacks = {
Matthias BUSSONNIER
rename show/hide methods to avoid jQuery conflict....
r7202 'object_info_reply': $.proxy(this._show, this)
Matthias BUSSONNIER
beautify tooltip.js
r7189 }
var msg_id = IPython.notebook.kernel.object_info_request(re.exec(func), callbacks);
Matthias BUSSONNIER
move some tooltip logic away from codecell.js
r7171 }
Matthias BUSSONNIER
clean and comment tooltip file
r7162
// make an imediate completion request
Matthias BUSSONNIER
space before function keyword in js
r7191 Tooltip.prototype.request = function (cell) {
Matthias BUSSONNIER
clean code, show clock if tooltip is 'sticky'...
r7173 // request(codecell)
Matthias BUSSONNIER
make tooltip tabs fonction configurable
r7172 // Deal with extracting the text from the cell and counting
// call in a row
Matthias BUSSONNIER
multiple tooltip action...
r7160 this.cancel_pending();
var editor = cell.code_mirror;
var cursor = editor.getCursor();
Matthias BUSSONNIER
beautify tooltip.js
r7189 var text = editor.getRange({
line: cursor.line,
ch: 0
}, cursor).trim();
Matthias BUSSONNIER
clean code, show clock if tooltip is 'sticky'...
r7173
Bussonnier Matthias
shift tqb for tooltip
r8949 if(editor.somethingSelected()){
text = editor.getSelection();
}
Matthias BUSSONNIER
fix tooltip keep focus on wrong cell...
r7204 // need a permanent handel to code_mirror for future auto recall
Matthias BUSSONNIER
make tooltip tabs fonction configurable
r7172 this.code_mirror = editor;
Matthias BUSSONNIER
clean code, show clock if tooltip is 'sticky'...
r7173 // now we treat the different number of keypress
Matthias BUSSONNIER
make tooltip tabs fonction configurable
r7172 // first if same cell, same text, increment counter by 1
Matthias BUSSONNIER
beautify tooltip.js
r7189 if (this._old_cell == cell && this._old_request == text && this._hidden == false) {
Matthias BUSSONNIER
clean code, show clock if tooltip is 'sticky'...
r7173 this._consecutive_counter++;
Matthias BUSSONNIER
multiple tooltip action...
r7160 } else {
Matthias BUSSONNIER
make tooltip tabs fonction configurable
r7172 // else reset
Matthias BUSSONNIER
clean code, show clock if tooltip is 'sticky'...
r7173 this.cancel_stick();
Matthias BUSSONNIER
space before function keyword in js
r7191 this.reset_tabs_function (cell, text);
Matthias BUSSONNIER
multiple tooltip action...
r7160 }
Matthias BUSSONNIER
clean code, show clock if tooltip is 'sticky'...
r7173
Matthias BUSSONNIER
make tooltip tabs fonction configurable
r7172 // don't do anything if line beggin with '(' or is empty
Matthias BUSSONNIER
beautify tooltip.js
r7189 if (text === "" || text === "(") {
Matthias BUSSONNIER
multiple tooltip action...
r7160 return;
}
Matthias BUSSONNIER
clean code, show clock if tooltip is 'sticky'...
r7173
Matthias BUSSONNIER
beautify tooltip.js
r7189 this.tabs_functions[this._consecutive_counter](cell, text);
Matthias BUSSONNIER
clean code, show clock if tooltip is 'sticky'...
r7173
// then if we are at the end of list function, reset
Matthias BUSSONNIER
space before function keyword in js
r7191 if (this._consecutive_counter == this.tabs_functions.length) this.reset_tabs_function (cell, text);
Matthias BUSSONNIER
clean code, show clock if tooltip is 'sticky'...
r7173
Matthias BUSSONNIER
make tooltip tabs fonction configurable
r7172 return;
Matthias BUSSONNIER
multiple tooltip action...
r7160 }
Matthias BUSSONNIER
clean and comment tooltip file
r7162
// cancel the option of having the tooltip to stick
Matthias BUSSONNIER
space before function keyword in js
r7191 Tooltip.prototype.cancel_stick = function () {
Matthias BUSSONNIER
beautify tooltip.js
r7189 clearTimeout(this._stick_timeout);
this._stick_timeout = null;
this._clocklink.hide('slow');
this._sticky = false;
Matthias BUSSONNIER
multiple tooltip action...
r7160 }
Matthias BUSSONNIER
clean and comment tooltip file
r7162 // put the tooltip in a sicky state for 10 seconds
// it won't be removed by remove_and_cancell() unless you called with
// the first parameter set to true.
// remove_and_cancell_tooltip(true)
Matthias BUSSONNIER
space before function keyword in js
r7191 Tooltip.prototype.stick = function (time) {
Matthias BUSSONNIER
beautify tooltip.js
r7189 time = (time != undefined) ? time : 10;
Matthias BUSSONNIER
clean and comment tooltip file
r7162 var that = this;
Matthias BUSSONNIER
multiple tooltip action...
r7160 this._sticky = true;
Matthias BUSSONNIER
clean code, show clock if tooltip is 'sticky'...
r7173 this._clocklink.show('slow');
Matthias BUSSONNIER
space before function keyword in js
r7191 this._stick_timeout = setTimeout(function () {
Matthias BUSSONNIER
multiple tooltip action...
r7160 that._sticky = false;
Matthias BUSSONNIER
clean code, show clock if tooltip is 'sticky'...
r7173 that._clocklink.hide('slow');
Matthias BUSSONNIER
beautify tooltip.js
r7189 }, time * 1000);
Matthias BUSSONNIER
call tooltip by cell reference
r7156 }
Matthias BUSSONNIER
clean and comment tooltip file
r7162 // should be called with the kernel reply to actually show the tooltip
Matthias BUSSONNIER
rename show/hide methods to avoid jQuery conflict....
r7202 Tooltip.prototype._show = function (reply) {
Matthias BUSSONNIER
animation if already shown
r7153 // move the bubble if it is not hidden
// otherwise fade it
Matthias BUSSONNIER
make tooltip tabs fonction configurable
r7172 this.name = reply.name;
Matthias BUSSONNIER
multiple tooltip action...
r7160
// do some math to have the tooltip arrow on more or less on left or right
// width of the editor
Matthias BUSSONNIER
clean code, show clock if tooltip is 'sticky'...
r7173 var w = $(this.code_mirror.getScrollerElement()).width();
Matthias BUSSONNIER
multiple tooltip action...
r7160 // ofset of the editor
Matthias BUSSONNIER
clean code, show clock if tooltip is 'sticky'...
r7173 var o = $(this.code_mirror.getScrollerElement()).offset();
Bussonnier Matthias
shift tqb for tooltip
r8949
// whatever anchor/head order but arrow at mid x selection
var anchor = this.code_mirror.cursorCoords(false);
var head = this.code_mirror.cursorCoords(true);
var pos = {};
pos.y = head.y
pos.yBot = head.yBot
pos.x = (head.x+anchor.x)/2;
Matthias BUSSONNIER
move arow with tooltip positoin
r7155 var xinit = pos.x;
Matthias BUSSONNIER
beautify tooltip.js
r7189 var xinter = o.left + (xinit - o.left) / w * (w - 450);
Matthias BUSSONNIER
move arow with tooltip positoin
r7155 var posarrowleft = xinit - xinter;
Matthias BUSSONNIER
clean and comment tooltip file
r7162
Matthias BUSSONNIER
move arow with tooltip positoin
r7155
Matthias BUSSONNIER
beautify tooltip.js
r7189 if (this._hidden == false) {
this.tooltip.animate({
'left': xinter - 30 + 'px',
'top': (pos.yBot + 10) + 'px'
});
} else {
this.tooltip.css({
'left': xinter - 30 + 'px'
});
this.tooltip.css({
'top': (pos.yBot + 10) + 'px'
});
Matthias BUSSONNIER
animation if already shown
r7153 }
Matthias BUSSONNIER
beautify tooltip.js
r7189 this.arrow.animate({
'left': posarrowleft + 'px'
});
Matthias BUSSONNIER
rename show/hide methods to avoid jQuery conflict....
r7202 this.tooltip.fadeIn('fast');
Matthias BUSSONNIER
animation if already shown
r7153 this._hidden = false;
Matthias BUSSONNIER
improve new tooltip
r7147
// build docstring
Matthias BUSSONNIER
clean code, show clock if tooltip is 'sticky'...
r7173 var defstring = reply.call_def;
Matthias BUSSONNIER
beautify tooltip.js
r7189 if (defstring == null) {
defstring = reply.init_definition;
}
if (defstring == null) {
defstring = reply.definition;
}
Matthias BUSSONNIER
improve new tooltip
r7147
Matthias BUSSONNIER
clean code, show clock if tooltip is 'sticky'...
r7173 var docstring = reply.call_docstring;
Matthias BUSSONNIER
beautify tooltip.js
r7189 if (docstring == null) {
docstring = reply.init_docstring;
}
if (docstring == null) {
docstring = reply.docstring;
}
if (docstring == null) {
docstring = "<empty docstring>";
}
Matthias BUSSONNIER
improve new tooltip
r7147
this.text.children().remove();
Matthias BUSSONNIER
beautify tooltip.js
r7189 var pre = $('<pre/>').html(utils.fixConsole(docstring));
if (defstring) {
Matthias BUSSONNIER
improve new tooltip
r7147 var defstring_html = $('<pre/>').html(utils.fixConsole(defstring));
this.text.append(defstring_html);
}
Matthias Bussonnier
fix scrolltop
r7151 this.text.append(pre);
Matthias BUSSONNIER
almost all logic in tooltip.js, padding right button
r7158 // keep scroll top to be sure to always see the first line
this.text.scrollTop(0);
Matthias Bussonnier
tooltip to mac
r7145 }
Matthias BUSSONNIER
fix tooltip keep focus on wrong cell...
r7204 // convenient funciton to have the correct code_mirror back into focus
Matthias BUSSONNIER
space before function keyword in js
r7191 Tooltip.prototype._cmfocus = function () {
Matthias BUSSONNIER
call tooltip by cell reference
r7156 var cm = this.code_mirror;
Matthias BUSSONNIER
fix tooltip keep focus on wrong cell...
r7204 if (cm == IPython.notebook.get_selected_cell())
{
setTimeout(function () {
cm.focus();
}, 50);
}
Matthias BUSSONNIER
call tooltip by cell reference
r7156 }
Matthias Bussonnier
tooltip to mac
r7145 IPython.Tooltip = Tooltip;
Matthias BUSSONNIER
clean code, show clock if tooltip is 'sticky'...
r7173
Matthias Bussonnier
tooltip to mac
r7145 return IPython;
Matthias BUSSONNIER
clean code, show clock if tooltip is 'sticky'...
r7173
Matthias Bussonnier
tooltip to mac
r7145 }(IPython));