StrictDoc Documentation
strictdoc/features/tree_map/plotly_js.py
Source file coverage
Path:
strictdoc/features/tree_map/plotly_js.py
Lines:
102
Non-empty lines:
89
Non-empty lines covered with requirements:
89 / 89 (100.0%)
Functions:
0
Functions covered by requirements:
0 / 0 (0.0%)
1
"""
2
@relation(SDOC-SRS-157, scope=file)
3
"""
4
 
5
from markupsafe import Markup
6
 
7
PLOTLY_JS_EXTENSION = Markup("""
8
    window.addEventListener("load", () => {
9
        var tooltip = document.createElement('div');
10
        tooltip.id = 'tooltip';
11
        tooltip.style.position = 'absolute';
12
        tooltip.style.background = '#ddd';
13
        tooltip.style.border = '1px solid black';
14
        tooltip.style.padding = '5px';
15
        tooltip.style.fontFamily = '"Open Sans", verdana, arial, sans-serif';
16
        tooltip.style.fontSize = "12px";
17
        tooltip.style.display = 'none';
18
        tooltip.style.pointerEvents = 'none';
19
        tooltip.style.zIndex = 1000;
20
        document.body.appendChild(tooltip);
21
 
22
        document.querySelectorAll('div.js-plotly-plot').forEach(plot => {
23
            let prevDepth = 0;
24
            let currentId = null;
25
 
26
            plot.on('plotly_treemapclick', function(event) {
27
                const domEvent = event.event;
28
                const link = domEvent?.target?.closest?.('a');
29
 
30
                // This branch handles the "Open in document" link click.
31
                if (link) {
32
                    // Stop the original DOM click from reaching Plotly/container
33
                    // handlers.
34
                    domEvent.stopPropagation();
35
                    domEvent.stopImmediatePropagation?.();
36
 
37
                    return false;
38
                }
39
 
40
                const point = event.points[0];
41
                const clickedNodeId = point.id;
42
 
43
                // Controls toggling of leaf nodes between summary and detailed views.
44
                //
45
                // `currentId` tracks whether a leaf node is currently in its "zoomed-in"
46
                // (detailed) state. This is necessary because depth alone is insufficient:
47
                // when a user zooms out and then back into the same node, the depth may
48
                // remain unchanged.
49
                //
50
                // The condition: clickedDepth > prevDepth handles normal
51
                // zoom-in transitions.
52
                //
53
                // The additional condition: clickedDepth === prevDepth && !currentId
54
                // handles the case where the same node is re-entered without a depth change,
55
                // ensuring it switches back to the detailed view.
56
                if (event.points[0].customdata) {
57
                    let clickedDepth = event.points[0].customdata[4];
58
                    var isLeaf = event.points[0].customdata[3];
59
 
60
                    if (isLeaf) {
61
                        if (
62
                            clickedDepth > prevDepth ||
63
                            (clickedDepth === prevDepth && !currentId)
64
                        ) {
65
                            Plotly.restyle(plot, {'texttemplate': '%{customdata[2]}'});
66
                            currentId = clickedNodeId;
67
                        }
68
                        else {
69
                            Plotly.restyle(plot, {'texttemplate': '%{customdata[1]}'});
70
                            currentId = null;
71
                        }
72
                    } else {
73
                        Plotly.restyle(plot, {'texttemplate': '%{customdata[1]}'});
74
                        currentId = null;
75
                    }
76
                    prevDepth = clickedDepth;
77
                } else {
78
                    Plotly.restyle(plot, {'texttemplate': '%{customdata[1]}'});
79
                    prevDepth = 0;
80
                    currentId = null;
81
                }
82
            });
83
 
84
            plot.on('plotly_hover', function(event) {
85
                var point = event.points[0];
86
                if (!point.customdata) return;
87
 
88
                var text = point.customdata[0];
89
 
90
                tooltip.innerHTML = text;
91
                tooltip.style.left = event.event.clientX + 10 + "px";
92
                tooltip.style.top = event.event.clientY + 10 + "px";
93
                tooltip.style.display = "block";
94
            });
95
 
96
            // Hide tooltip on unhover.
97
            plot.on('plotly_unhover', function(event) {
98
                tooltip.style.display = "none";
99
            });
100
        });
101
    });
102
""")