This file is indexed.

/usr/lib/python2.7/dist-packages/notebook/static/notebook/js/tooltip.js is in python-notebook 5.2.2-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.

define([
    'jquery',
    'base/js/utils',
    'base/js/i18n'
], function($, utils, i18n) {
    "use strict";

    // tooltip constructor
    var Tooltip = function (events) {
        var that = this;
        this.events = events;
        this.time_before_tooltip = 1200;

        // handle to html
        this.tooltip = $('#tooltip');
        this._hidden = true;

        // variable for consecutive call
        this._old_cell = null;
        this._old_request = null;
        this._consecutive_counter = 0;

        // 'sticky ?'
        this._sticky = false;

        // display tooltip if the docstring is empty?
        this._hide_if_no_docstring = false;

        // 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
        .attr('role', "button").attr('id', 'expanbutton').attr('title', i18n.msg._('Grow the tooltip vertically (press shift-tab twice)')).click(function () {
            that.expand();
            event.preventDefault();
        }).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', i18n.msg._('show the current docstring in pager (press shift-tab 4 times)'));
        var morespan = $('<span/>').text(i18n.msg._('Open in Pager')).addClass('ui-icon').addClass('ui-icon-arrowstop-l-n');
        morelink.append(morespan);
        morelink.click(function () {
            that.showInPager(that._old_cell);
            event.preventDefault();
        });

        // close the tooltip
        var closelink = $('<a/>').attr('href', "#").attr('role', "button").addClass('ui-button');
        var closespan = $('<span/>').text(i18n.msg._('Close')).addClass('ui-icon').addClass('ui-icon-close');
        closelink.append(closespan);
        closelink.click(function () {
            that.remove_and_cancel_tooltip(true);
            event.preventDefault();
        });

        this._clocklink = $('<a/>').attr('href', "#");
        this._clocklink.attr('role', "button");
        this._clocklink.addClass('ui-button');
        this._clocklink.attr('title', i18n.msg._('Tooltip will linger for 10 seconds while you type'));
        var clockspan = $('<span/>').text(i18n.msg._('Close'));
        clockspan.addClass('ui-icon');
        clockspan.addClass('ui-icon-clock');
        this._clocklink.append(clockspan);
        this._clocklink.click(function () {
            that.cancel_stick();
            event.preventDefault();
        });




        //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
        this.tabs_functions = [function (cell, text, cursor) {
            that._request_tooltip(cell, text, cursor);
        }, function () {
            that.expand();
        }, function () {
            that.stick();
        }, function (cell) {
            that.cancel_stick();
            that.showInPager(cell);
        }];
        // call after all the tabs function above have bee call to clean their effects
        // if necessary
        this.reset_tabs_function = function (cell, text) {
            this._old_cell = (cell) ? cell : null;
            this._old_request = (text) ? text : null;
            this._consecutive_counter = 0;
        };
    };

    Tooltip.prototype.is_visible = function () {
        return !this._hidden;
    };

    Tooltip.prototype.showInPager = function (cell) {
        /**
         * reexecute last call in pager by appending ? to show back in pager
         */
        this.events.trigger('open_with_text.Pager', this._reply.content);
        this.remove_and_cancel_tooltip();
    };

    // grow the tooltip verticaly
    Tooltip.prototype.expand = function () {
        this.text.removeClass('smalltooltip');
        this.text.addClass('bigtooltip');
        $('#expanbutton').hide('slow');
    };

    // deal with all the logic of hiding the tooltip
    // and reset it's status
    Tooltip.prototype._hide = function () {
        this._hidden = true;
        this.tooltip.fadeOut('fast');
        $('#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.code_mirror = null;
    };

    // return true on successfully removing a visible tooltip; otherwise return
    // false.
    Tooltip.prototype.remove_and_cancel_tooltip = function (force) {
        /**
         * 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.
         */
        this.cancel_pending();
        if (!this._hidden) {
          if (force || !this._sticky) {
              this.cancel_stick();
              this._hide();
          }
          this.reset_tabs_function();
          return true;
        } else {
          return false;
        }
    };

    // cancel autocall done after '(' for example.
    Tooltip.prototype.cancel_pending = function () {
        if (this._tooltip_timeout !== null) {
            clearTimeout(this._tooltip_timeout);
            this._tooltip_timeout = null;
        }
    };

    // will trigger tooltip after timeout
    Tooltip.prototype.pending = function (cell, hide_if_no_docstring) {
        var that = this;
        this._tooltip_timeout = setTimeout(function () {
            that.request(cell, hide_if_no_docstring);
        }, that.time_before_tooltip);
    };

    // easy access for julia monkey patching.
    Tooltip.last_token_re = /[a-z_][0-9a-z._]*$/gi;

    Tooltip.prototype._request_tooltip = function (cell, text, cursor_pos) {
        var callbacks = $.proxy(this._show, this);
        var msg_id = cell.kernel.inspect(text, cursor_pos, callbacks);
    };

    // make an immediate completion request
    Tooltip.prototype.request = function (cell, hide_if_no_docstring) {
        /**
         * request(codecell)
         * Deal with extracting the text from the cell and counting
         * call in a row
         */
        this.cancel_pending();
        var editor = cell.code_mirror;
        var cursor = editor.getCursor();
        var text = cell.get_text();
        var cursor_pos = utils.js_idx_to_char_idx(editor.indexFromPos(cursor), text);

        this._hide_if_no_docstring = hide_if_no_docstring;

        if(editor.somethingSelected()){
            // get only the most recent selection.
            text = editor.getSelection();
        }

        // need a permanent handle to code_mirror for future auto recall
        this.code_mirror = editor;

        // now we treat the different number of keypress
        // first if same cell, same text, increment counter by 1
        if (this._old_cell == cell && this._old_request == text && this._hidden === false) {
            this._consecutive_counter++;
        } else {
            // else reset
            this.cancel_stick();
            this.reset_tabs_function (cell, text);
        }

        this.tabs_functions[this._consecutive_counter](cell, text, cursor_pos);

        // then if we are at the end of list function, reset
        if (this._consecutive_counter == this.tabs_functions.length) {
            this.reset_tabs_function (cell, text, cursor);
        }

        return;
    };

    // cancel the option of having the tooltip to stick
    Tooltip.prototype.cancel_stick = function () {
        clearTimeout(this._stick_timeout);
        this._stick_timeout = null;
        this._clocklink.hide('slow');
        this._sticky = false;
    };

    // 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)
    Tooltip.prototype.stick = function (time) {
        time = (time !== undefined) ? time : 10;
        var that = this;
        this._sticky = true;
        this._clocklink.show('slow');
        this._stick_timeout = setTimeout(function () {
            that._sticky = false;
            that._clocklink.hide('slow');
        }, time * 1000);
    };

    // should be called with the kernel reply to actually show the tooltip
    Tooltip.prototype._show = function (reply) {
        /**
         * move the bubble if it is not hidden
         * otherwise fade it
         */
        this._reply = reply;
        var content = reply.content;
        if (!content.found) {
            // object not found, nothing to show
            return;
        }
        this.name = content.name;

        // do some math to have the tooltip arrow on more or less on left or right
        // position of the editor
        var cm_pos = $(this.code_mirror.getWrapperElement()).position();
        var cell_pos = $(this.code_mirror.getWrapperElement().offsetParent).position();

        // anchor and head positions are local within CodeMirror element
        var anchor = this.code_mirror.cursorCoords(false, 'local');
        var head = this.code_mirror.cursorCoords(true, 'local');
        // locate the target at the center of anchor, head
        var center_left = (head.left + anchor.left) / 2;
        // locate the left edge of the tooltip, at most 450 px left of the arrow
        var edge_left = Math.max(center_left - 450, 0);
        // locate the arrow at the cursor. A 24 px offset seems necessary.
        var arrow_left = center_left - edge_left - 24;
        
        // locate left, top within container element
        var left = (cell_pos.left + cm_pos.left + edge_left) + 'px';
        var top = (cell_pos.top + cm_pos.top + head.bottom + 10) + 'px';

        if (this._hidden === false) {
            this.tooltip.animate({
                left: left,
                top: top
            });
        } else {
            this.tooltip.css({
                left: left
            });
            this.tooltip.css({
                top: top
            });
        }
        this.arrow.animate({
            'left': arrow_left + 'px'
        });
        
        this._hidden = false;
        this.tooltip.fadeIn('fast');
        this.text.children().remove();
        
        // This should support rich data types, but only text/plain for now
        // Any HTML within the docstring is escaped by the fixConsole() method.
        var pre = $('<pre/>').html(utils.fixConsole(content.data['text/plain']));
        this.text.append(pre);
        // keep scroll top to be sure to always see the first line
        this.text.scrollTop(0);
    };

    return {'Tooltip': Tooltip};
});