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/container33
// 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 may48
// remain unchanged.49
//50
// The condition: clickedDepth > prevDepth handles normal51
// zoom-in transitions.52
//53
// The additional condition: clickedDepth === prevDepth && !currentId54
// 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
""")