blob: d22f0aef097ef8e3213dca9bf3cff326701d789c [file] [log] [blame]
<!DOCTYPE html>
<!--
Copyright (c) 2013 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
-->
<link rel="stylesheet" href="/core/analysis/analysis_results.css">
<link rel="import" href="/base/ui.html">
<link rel="import" href="/base/units/util.html">
<link rel="import" href="/core/analysis/analysis_link.html">
<link rel="import" href="/core/analysis/generic_object_view.html">
<script>
'use strict';
tr.exportTo('tr.c.analysis', function() {
var AnalysisResults = tr.b.ui.define('div');
AnalysisResults.prototype = {
__proto__: HTMLDivElement.prototype,
decorate: function() {
this.className = 'analysis-results';
},
get requiresTallView() {
return true;
},
clear: function() {
this.textContent = '';
},
createSelectionChangingLink: function(text, selectionGenerator,
opt_tooltip) {
var el = this.ownerDocument.createElement('tr-c-a-analysis-link');
function wrap() {
return selectionGenerator();
}
wrap.userFriendlyName = text;
el.selection = wrap;
if (opt_tooltip)
el.title = opt_tooltip;
return el;
},
appendElement_: function(parent, tagName, opt_text) {
var n = parent.ownerDocument.createElement(tagName);
parent.appendChild(n);
if (opt_text != undefined)
n.textContent = opt_text;
return n;
},
appendText_: function(parent, text) {
var textElement = parent.ownerDocument.createTextNode(text);
parent.appendChild(textNode);
return textNode;
},
appendTableCell_: function(table, row, cellnum, text, opt_warning) {
var td = this.appendElement_(row, 'td', text);
td.className = table.className + '-col-' + cellnum;
if (opt_warning) {
var span = document.createElement('span');
span.textContent = ' ' + String.fromCharCode(9888);
span.title = opt_warning;
td.appendChild(span);
}
return td;
},
/**
* Creates and append a table cell at the end of the given row.
*/
appendTableCell: function(table, row, text) {
return this.appendTableCell_(table, row, row.children.length, text);
},
appendTableCellWithTooltip_: function(table, row, cellnum, text, tooltip) {
if (tooltip) {
var td = this.appendElement_(row, 'td');
td.className = table.className + '-col-' + cellnum;
var span = this.appendElement_(td, 'span', text);
span.className = 'tooltip';
span.title = tooltip;
return td;
} else {
return this.appendTableCell_(table, row, cellnum, text);
}
},
/**
* Creates and appends a section header element.
*/
appendHeader: function(label) {
var header = this.appendElement_(this, 'span', label);
header.className = 'analysis-header';
return header;
},
/**
* Creates and appends a info element of the format "<b>label</b>value".
*/
appendInfo: function(label, value) {
var div = this.appendElement_(this, 'div');
div.label = this.appendElement_(div, 'b', label);
div.value = this.appendElement_(div, 'span', value);
return div;
},
/**
* Adds a table with the given className.
*
* @return {HTMLTableElement} The newly created table.
*/
appendTable: function(className, numColumns) {
var table = this.appendElement_(this, 'table');
table.className = className + ' analysis-table';
table.numColumns = numColumns;
return table;
},
/**
* Creates and appends a |tr| in |thead|, if |thead| does not exist, create
* it as well.
*/
appendHeadRow: function(table) {
if (table.headerRow)
throw new Error('Only one header row allowed.');
if (table.tbody || table.tfoot)
throw new Error(
'Cannot add a header row after data rows have been added.');
table.headerRow = this.appendElement_(
this.appendElement_(table, 'thead'), 'tr');
table.headerRow.className = 'analysis-table-header';
return table.headerRow;
},
/**
* Creates and appends a |tr| in |tbody|, if |tbody| does not exist, create
* it as well.
*/
appendBodyRow: function(table) {
if (table.tfoot)
throw new Error(
'Cannot add a tbody row after footer rows have been added.');
if (!table.tbody)
table.tbody = this.appendElement_(table, 'tbody');
var row = this.appendElement_(table.tbody, 'tr');
if (table.headerRow)
row.className = 'analysis-table-row';
else
row.className = 'analysis-table-row-inverted';
return row;
},
/**
* Creates and appends a |tr| in |tfoot|, if |tfoot| does not exist, create
* it as well.
*/
appendFootRow: function(table) {
if (!table.tfoot) {
table.tfoot = this.appendElement_(table, 'tfoot');
table.tfoot.rowsClassName = (
(table.headerRow ? 1 : 0) +
(table.tbody ? table.tbody.rows.length : 0)) % 2 ?
'analysis-table-row' : 'analysis-table-row-inverted';
}
var row = this.appendElement_(table.tfoot, 'tr');
row.className = table.tfoot.rowsClassName;
return row;
},
/**
* Adds a spacing row to spread out results.
*/
appendSpacingRow: function(table, opt_inFoot) {
if (table.tfoot || opt_inFoot)
var row = this.appendFootRow(table);
else
var row = this.appendBodyRow(table);
for (var i = 0; i < table.numColumns; i++)
this.appendTableCell_(table, row, i, ' ');
},
/**
* Creates and appends a row to |table| with a left-aligned |label] in the
* first column and an optional |opt_value| in the second column.
*/
appendInfoRow: function(table, label, opt_value, opt_inFoot) {
if (table.tfoot || opt_inFoot)
var row = this.appendFootRow(table);
else
var row = this.appendBodyRow(table);
this.appendTableCell_(table, row, 0, label);
if (opt_value !== undefined) {
var objectView =
document.createElement('tr-c-a-generic-object-view');
objectView.object = opt_value;
objectView.classList.add('analysis-table-col-1');
objectView.style.display = 'table-cell';
row.appendChild(objectView);
} else {
this.appendTableCell_(table, row, 1, '');
}
for (var i = 2; i < table.numColumns; i++)
this.appendTableCell_(table, row, i, '');
},
/**
* Creates and appends a row to |table| with a left-aligned |label] in the
* first column and a millisecond |time| value in the second column.
*/
appendInfoRowTime: function(table, label, time, opt_inFoot, opt_warning) {
if (table.tfoot || opt_inFoot)
var row = this.appendFootRow(table);
else
var row = this.appendBodyRow(table);
this.appendTableCell_(table, row, 0, label);
this.appendTableCell_(
table, row, 1, tr.b.units.tsString(time), opt_warning);
},
/**
* Creates and appends a row to |table| that summarizes a single slice or a
* single counter. The row has a left-aligned |start| in the first column,
* the |duration| of the data in the second, the number of |occurrences| in
* the third.
*
* @param {object=} opt_statistics May be undefined, or an object which
* contains calculated statistics containing min/max/avg for
* slices, or min/max/avg/start/end for counters.
*/
appendDetailsRow: function(table, start, duration, selfTime, args,
opt_selectionGenerator, opt_cpuDuration, opt_inFoot) {
if (opt_inFoot) {
// If inFoot is true, then we're reporting Totals.
var row = this.appendFootRow(table);
this.appendTableCell(table, row, 'Totals');
}
else {
var row = this.appendBodyRow(table);
if (opt_selectionGenerator) {
var labelEl = this.appendTableCell(table, row,
tr.b.units.tsString(start));
labelEl.textContent = '';
labelEl.appendChild(this.createSelectionChangingLink(
tr.b.units.tsString(start),
opt_selectionGenerator, ''));
} else {
this.appendTableCell(table, row, tr.b.units.tsString(start));
}
}
if (duration !== null)
this.appendTableCell(table, row, tr.b.units.tsString(duration));
if (opt_cpuDuration)
this.appendTableCell(table, row,
opt_cpuDuration != '' ?
tr.b.units.tsString(opt_cpuDuration) :
'');
if (selfTime !== null)
this.appendTableCell(table, row, tr.b.units.tsString(selfTime));
var argsCell = this.appendTableCell(table, row, '');
var n = 0;
for (var argName in args) {
n += 1;
}
if (n > 0) {
for (var argName in args) {
var argVal = args[argName];
var objectView =
document.createElement('tr-c-a-generic-object-view');
objectView.object = argVal;
var argsRow = this.appendElement_(
this.appendElement_(argsCell, 'table'), 'tr');
this.appendElement_(argsRow, 'td', argName + ':');
this.appendElement_(argsRow, 'td').appendChild(objectView);
}
}
},
/**
* Creates and appends a row to |table| that summarizes one or more slices,
* or one or more counters. The row has a left-aligned |label| in the first
* column, the |duration| of the data in the second, the number of
* |occurrences| in the third.
*
* @param {object=} opt_statistics May be undefined, or an object which
* contains calculated statistics containing min/max/avg for
* slices, or min/max/avg/start/end for counters.
*/
appendDataRow: function(table, label, opt_duration, opt_cpuDuration,
opt_selfTime, opt_cpuSelfTime, opt_occurrences,
opt_percentage, opt_statistics,
opt_selectionGenerator, opt_inFoot) {
var tooltip = undefined;
if (opt_statistics) {
var stddevRounded = Math.round(opt_statistics.avg_stddev * 1000) / 1000;
tooltip = 'Min Duration:\u0009' +
tr.b.units.tsString(opt_statistics.min) +
' \u000DMax Duration:\u0009' +
tr.b.units.tsString(opt_statistics.max) +
' \u000DAvg Duration:\u0009' +
tr.b.units.tsString(opt_statistics.avg) +
' (\u03C3 = ' + stddevRounded + ')';
if (opt_statistics.start) {
tooltip += '\u000DStart Time:\u0009' +
tr.b.units.tsString(opt_statistics.start);
}
if (opt_statistics.end) {
tooltip += '\u000DEnd Time:\u0009' +
tr.b.units.tsString(opt_statistics.end);
}
if (opt_statistics.frequency && opt_statistics.frequency_stddev) {
var fR = Math.round(opt_statistics.frequency * 1000) / 1000;
var fSR = Math.round(opt_statistics.frequency_stddev * 1000) / 1000;
tooltip += '\u000DFrequency:\u0009' +
fR + ' occurrences/s (\u03C3 = ' + fSR + ')';
}
}
if (table.tfoot || opt_inFoot)
var row = this.appendFootRow(table);
else
var row = this.appendBodyRow(table);
var cellNum = 0;
if (!opt_selectionGenerator) {
this.appendTableCellWithTooltip_(table, row, cellNum, label, tooltip);
} else {
var labelEl = this.appendTableCellWithTooltip_(
table, row, cellNum, label, tooltip);
if (labelEl) {
labelEl.textContent = '';
labelEl.appendChild(
this.createSelectionChangingLink(label, opt_selectionGenerator,
tooltip));
}
}
cellNum++;
if (opt_duration !== null) {
if (opt_duration) {
if (opt_duration instanceof Array) {
this.appendTableCellWithTooltip_(table, row, cellNum,
'[' + opt_duration.join(', ') + ']', tooltip);
} else {
this.appendTableCellWithTooltip_(table, row, cellNum,
tr.b.units.tsString(opt_duration), tooltip);
}
} else {
this.appendTableCell_(table, row, cellNum, '');
}
cellNum++;
}
if (opt_cpuDuration !== null) {
if (opt_cpuDuration != '') {
this.appendTableCellWithTooltip_(table, row, cellNum,
tr.b.units.tsString(opt_cpuDuration), tooltip);
} else {
this.appendTableCell_(table, row, cellNum, '');
}
cellNum++;
}
if (opt_selfTime !== null) {
if (opt_selfTime) {
this.appendTableCellWithTooltip_(table, row, cellNum,
tr.b.units.tsString(opt_selfTime), tooltip);
} else {
this.appendTableCell_(table, row, cellNum, '');
}
cellNum++;
}
if (opt_cpuSelfTime !== null) {
if (opt_cpuSelfTime) {
this.appendTableCellWithTooltip_(table, row, cellNum,
tr.b.units.tsString(opt_cpuSelfTime), tooltip);
} else {
this.appendTableCell_(table, row, cellNum, '');
}
cellNum++;
}
if (opt_percentage !== null) {
if (opt_percentage) {
this.appendTableCellWithTooltip_(table, row, cellNum,
opt_percentage, tooltip);
} else {
this.appendTableCell_(table, row, cellNum, '');
}
cellNum++;
}
if (opt_occurrences) {
this.appendTableCellWithTooltip_(table, row, cellNum,
String(opt_occurrences), tooltip);
} else {
this.appendTableCell_(table, row, cellNum, '');
}
cellNum++;
}
};
return {
AnalysisResults: AnalysisResults
};
});
</script>