aboutsummaryrefslogtreecommitdiff
path: root/resources/assets/javascripts/bootstrap/tooltip.js
blob: c84042b82534486b0700efea51f1fad77c4396bb (plain)
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
// Attach global hover handler for tooltips.
// Applies to all elements having a "data-tooltip" attribute.
// Tooltip may be provided in the data-attribute itself or by
// defining a title attribute. The latter is prefered due to
// the obvious accessibility issues.

var timeout = null;

STUDIP.Tooltip.threshold = 6;

$(document).on('mouseenter mouseleave focusin focusout', '[data-tooltip],.tooltip:has(.tooltip-content)', function(event) {
    let data = $(this).data();

    const visible = event.type === 'mouseenter' || event.type === 'focusin';
    const offset = $(this).offset();
    const x = offset.left + $(this).outerWidth(true) / 2;
    const y = offset.top;
    const delay = data.tooltipDelay ?? 300;

    let content;
    let tooltip;

    if (!data.tooltipObject) {
        // If tooltip has not yet been created (first hover), obtain it's
        // contents and create the actual tooltip object.
        if (!data.tooltip || !$.isPlainObject(data.tooltip)) {
            content = $('<div/>').text(data.tooltip || $(this).attr('title')).html();
        } else if (data.tooltip.html !== undefined) {
            content = data.tooltip.html;
        } else if (data.tooltip.text !== undefined) {
            content = data.tooltip.text;
        } else {
            throw "Invalid content for tooltip via data";
        }
        if (!content) {
            content = $(this).find('.tooltip-content').remove().html();
        }
        $(this).attr('title', null);
        $(this).attr('data-tooltip', content);

        tooltip = new STUDIP.Tooltip(x, y, content);

        data.tooltipObject = tooltip;
        $(this).attr('aria-describedby', tooltip.id);

        $(this).on('remove', function() {
            tooltip.remove();
        });
    } else if (visible) {
        // If tooltip has already been created, update it's position.
        // This is neccessary if the surrounding content is scrollable AND has
        // been scrolled. Otherwise the tooltip would appear at it's previous
        // and now wrong location.
        data.tooltipObject.position(x, y);
    }

    if (visible) {
        $('.studip-tooltip').not(data.tooltipObject).hide();
        data.tooltipObject.show();
    } else {
        timeout = setTimeout(() => data.tooltipObject.hide(), delay);
    }
}).on('mouseenter focusin', '.studip-tooltip', () => {
    clearTimeout(timeout);
}).on('mouseleave focusout', '.studip-tooltip', function() {
    $(this).hide();
});