function createRow(table, cellName, items) { var tr = document.createElement('tr'); var res = []; items.forEach(function(x, i) { if (x === undefined) { res.push(null); return; } var td = document.createElement(cellName); td.textContent = x; tr.appendChild(td); res.push(td); var colspan = 1; for (var n = i + 1; n < items.length; n++) { if (items[n] !== undefined) { break; } colspan += 1; } if (colspan > 1) { td.colSpan = colspan; } }); table.appendChild(tr); return res; } function createVisualizationTable(data, cutoff = 0, sort = "") { var table = document.createElement('table'); table.className = 'popup-table'; var keys = Object.keys(data); if (sort === "number") { keys = keys.sort(function(a, b) { return data[b] - data[a]; }); } else { keys = keys.sort(); } var items = keys.map(function(x) { return {key: x, parts: x.split('/'), value: data[x]}; }); var maxLength = items.reduce(function(a, b) { return Math.max(a, b.parts.length); }, 0); var cols = createRow( table, 'th', [ cutoff === 0 ? 'key' : 'record', cutoff === 0 ? 'value' : 'seconds' ] ); cols[0].colSpan = maxLength; function arraysEqual(a, b) { return !(a < b || b < a); } var addLevel = function(level, parent, hide) { var matching = items.filter(function(x) { return x.parts[level] && !x.parts[level + 1] && arraysEqual(x.parts.slice(0, level), parent); }); if (sort === "number") { matching = matching.sort(function(a, b) { return b.value - a.value; }); } else { matching = matching.sort(); } var othersTime = 0; var othersList = []; var othersRows = []; var childrenRows = []; matching.forEach(function(x) { var visible = (cutoff === 0 && !hide) || (x.value >= cutoff && !hide); var cells = []; for (var i = 0; i < maxLength; i++) { cells.push(x.parts[i]); } cells.push(cutoff === 0 ? x.value : x.value.toFixed(3)); var cols = createRow(table, 'td', cells); for (i = 0; i < level; i++) { cols[i].className = 'muted'; } var tr = cols[0].parentNode; if (!visible) { tr.classList.add("hidden"); } if (cutoff === 0 || x.value >= cutoff) { childrenRows.push(tr); } else { othersTime += x.value; othersList.push(x.parts[level]); othersRows.push(tr); } var children = addLevel(level + 1, parent.concat([x.parts[level]]), true); if (children.length > 0) { var cell = cols[level]; var onclick = function() { cell.classList.remove("link"); cell.removeEventListener("click", onclick); children.forEach(function(x) { x.classList.remove("hidden"); }); }; cell.classList.add("link"); cell.addEventListener("click", onclick); } }); if (othersTime > 0) { var cells = []; for (var i = 0; i < maxLength; i++) { cells.push(parent[i]); } cells.push(othersTime.toFixed(3)); cells[level] = 'others'; var cols = createRow(table, 'td', cells); for (i = 0; i < level; i++) { cols[i].className = 'muted'; } var cell = cols[level]; var tr = cell.parentNode; var onclick = function() { tr.classList.add("hidden"); cell.classList.remove("link"); cell.removeEventListener("click", onclick); othersRows.forEach(function(x) { x.classList.remove("hidden"); }); }; cell.title = othersList.join(", "); cell.classList.add("link"); cell.addEventListener("click", onclick); if (hide) { tr.classList.add("hidden"); } childrenRows.push(tr); } return childrenRows; }; addLevel(0, []); return table; } function showProfile(path, cutoff = 0.05) { requestGet(path, {}, function(data) { data.records['total'] = data.total; const table = createVisualizationTable(data.records, cutoff, "number"); popup(table); }); }