Files
YellowLabTools/app/node_views/results.html
T

675 lines
44 KiB
HTML

<html>
<head>
<meta charset="utf-8">
<title>Yellow Lab Tools - Results page</title>
<link rel="icon" type="image/png" href="/public/img/favicon.png">
<link rel="stylesheet" type="text/css" href="/public/styles/main.css">
<link rel="stylesheet" type="text/css" href="/public/styles/results.css">
<script src="/bower_components/angular/angular.min.js"></script>
<script src="/bower_components/ngModal/dist/ng-modal.js"></script>
<script src="/public/scripts/app.js"></script>
<script src="/public/scripts/resultsCtrl.js"></script>
<script src="/public/scripts/showOffenders.js"></script>
</head>
<body ng-app="YellowLabTools" ng-controller="ResultsCtrl">
<h1>Yellow Lab <span class="icon-lab"></span> Tools</h1>
<div ng-if="undefined">Untangling and counting the spaghettis...</div>
<div class="ng-cloak">
<div>Tested url: &nbsp; <a class="testedUrl" href="{{phantomasResults.url}}" target="_blank">{{phantomasResults.url}}</a></div>
<div class="resultsMenu">
<a class="menuItem back" href="/"><div class="icon-back"></div><span>New test<span></a>
<div class="menuItem" ng-if="!phantomasResults.error" ng-class="{active: view == 'summary'}" ng-click="setView('summary')"><div class="icon-summary"></div><span>Summary</span></div>
<div class="menuItem" ng-if="!phantomasResults.error" ng-class="{active: view == 'execution'}" ng-click="setView('execution')"><div class="icon-spaghetti"></div><span>JS Timeline</span></div>
<div class="menuItem" ng-if="!phantomasResults.error" ng-class="{active: view == 'metrics'}" ng-click="setView('metrics')"><div class="icon-metrics"></div><span>All Metrics</span></div>
</div>
<div ng-if="phantomasResults.error">
<h2>Error: {{phantomasResults.error}}</h2>
<div ng-if="phantomasResults.error == 252">Phantomas timed out</div>
<div ng-if="phantomasResults.error == 253">Phantomas config error</div>
<div ng-if="phantomasResults.error == 254">Phantomas failed to load page</div>
<div ng-if="phantomasResults.error == 255">Phantomas internal error</div>
<div ng-if="phantomasResults.error == 1001">Javascript execution tree error</div>
<div ng-if="phantomasResults.error == 1002">JSON undefined error</div>
</div>
<div ng-show="view == 'summary' && !phantomasResults.error" class="summary">
<h2>Summary</h2>
<div class="notations">
<div>
<div ng-class="notations.domComplexity">{{notations.domComplexity}}</div>
<div class="notation">DOM complexity</div>
<div class="criteria">
<div class="table">
<div ng-if="phantomasResults.metrics.DOMelementsCount">
<div class="label">DOM elements count</div>
<div class="result">{{phantomasResults.metrics.DOMelementsCount}}</div>
<div class="info">
<div class="icon-question" ng-click="DOMelementsCountTooltip = true"></div>
<modal-dialog show='DOMelementsCountTooltip' dialog-title='Avoid too many DOM elements'>
<p>A high number of DOM elements means a lot of work for the browser to render the page.</p>
<p>It also slows down Javascript DOM queries, as there are more elements to search through.</p>
</modal-dialog>
</div>
</div>
<div ng-if="phantomasResults.metrics.DOMelementMaxDepth">
<div class="label">DOM max depth</div>
<div class="result">
{{phantomasResults.metrics.DOMelementMaxDepth}}
<show-offenders modal-title="DOM max depth" metric-name="DOMelementMaxDepth" phantomas-results="phantomasResults"></show-offenders>
</div>
<div class="info">
<div class="icon-question" ng-click="DOMelementMaxDepthTooltip = true"></div>
<modal-dialog show='DOMelementMaxDepthTooltip' dialog-title='Reduce DOM depth'>
<p>A deep DOM makes difficult the CSS matching with DOM elements.</p>
<p>It also slows down Javascript modifications to the DOM because dimensions calculations bubble up. Same thing for Javascript events.</p>
</modal-dialog>
</div>
</div>
<div ng-if="phantomasResults.metrics.iframesCount">
<div class="label">Number of iframes</div>
<div class="result">{{phantomasResults.metrics.iframesCount}}</div>
<div class="info">
<div class="icon-question" ng-click="DOMelementMaxDepthTooltip = true"></div>
<modal-dialog show='DOMelementMaxDepthTooltip' dialog-title='iFrames are slow'>
<p>iFrames are the most complex HTML elements. They are pages just like the main page and the browser needs to create a new page context, wich has a cost.</p>
</modal-dialog>
</div>
</div>
<div ng-if="phantomasResults.metrics.DOMidDuplicated">
<div class="label">IDs duplicated</div>
<div class="result">
{{phantomasResults.metrics.DOMidDuplicated}}
<show-offenders modal-title="DOM IDs duplicated" metric-name="DOMidDuplicated" phantomas-results="phantomasResults"></show-offenders>
</div>
<div class="icon-question"></div>
</div>
</div>
</div>
</div>
<div>
<div ng-class="notations.domManipulations">{{notations.domManipulations}}</div>
<div class="notation">DOM read and write</div>
<div class="criteria">
<div class="table">
<div ng-if="phantomasResults.metrics.DOMinserts">
<div class="label">DOM inserts</div>
<div class="result">
{{phantomasResults.metrics.DOMinserts}}
<show-offenders modal-title="DOM inserts" metric-name="DOMinserts" phantomas-results="phantomasResults"></show-offenders>
</div>
<div class="icon-question"></div>
</div>
<div ng-if="phantomasResults.metrics.DOMqueries">
<div class="label">DOM queries</div>
<div class="result">{{phantomasResults.metrics.DOMqueries}}</div>
<div class="icon-question"></div>
</div>
<div ng-if="totalJSTime">
<div class="label">Time they took</div>
<div class="result">{{totalJSTime}} ms</div>
<div class="icon-question"></div>
</div>
</div>
</div>
</div>
<div>
<div ng-class="notations.duplicatedDomQueries">{{notations.duplicatedDomQueries}}</div>
<div class="notation">Duplicated DOM queries</div>
<div class="criteria">
<div class="table">
<div ng-if="duplicatedQueriesCountAll">
<div class="label">Avoidable queries</div>
<div class="result">
{{duplicatedQueriesCountAll}}
<show-offenders modal-title="Duplicated DOM queries" metric-name="DOMqueriesDuplicated" phantomas-results="phantomasResults"></show-offenders>
</div>
<div class="icon-question"></div>
</div>
</div>
</div>
</div>
<div>
<div ng-class="notations.eventsBound">{{notations.eventsBound}}</div>
<div class="notation">Events bound</div>
<div class="criteria">
<div class="table">
<div ng-if="phantomasResults.metrics.eventsBound">
<div class="label">Events bound</div>
<div class="result">
{{phantomasResults.metrics.eventsBound}}
<show-offenders modal-title="Events bound" metric-name="eventsBound" phantomas-results="phantomasResults"></show-offenders>
</div>
<div class="icon-question"></div>
</div>
</div>
</div>
</div>
<div>
<div ng-class="notations.jsBadPractices">{{notations.jsBadPractices}}</div>
<div class="notation">Bad Javascript</div>
<div class="criteria">
<div class="table">
<div ng-if="phantomasResults.metrics.jsErrors">
<div class="label">Javascript errors</div>
<div class="result">
{{phantomasResults.metrics.jsErrors}}
<show-offenders modal-title="Javascript errors" metric-name="jsErrors" phantomas-results="phantomasResults"></show-offenders>
</div>
<div class="icon-question"></div>
</div>
<div ng-if="phantomasResults.metrics.evalCalls">
<div class="label">eval calls</div>
<div class="result">{{phantomasResults.metrics.evalCalls}}</div>
<div class="icon-question"></div>
</div>
<div ng-if="phantomasResults.metrics.documentWriteCalls">
<div class="label">document.write calls</div>
<div class="result">{{phantomasResults.metrics.documentWriteCalls}}</div>
<div class="icon-question"></div>
</div>
<div ng-if="phantomasResults.metrics.consoleMessages">
<div class="label">Console messages</div>
<div class="result">{{phantomasResults.metrics.consoleMessages}}</div>
<div class="icon-question"></div>
</div>
<div ng-if="phantomasResults.metrics.globalVariables">
<div class="label">Global variables</div>
<div class="result">
{{phantomasResults.metrics.globalVariables}}
<show-offenders modal-title="Global variables" metric-name="globalVariables" phantomas-results="phantomasResults"></show-offenders>
</div>
<div class="icon-question"></div>
</div>
</div>
</div>
</div>
<div>
<div ng-class="notations.jQueryLoading">{{notations.jQueryLoading}}</div>
<div class="notation">jQuery version</div>
<div class="criteria">
<div class="table">
<div ng-if="phantomasResults.metrics.jQueryDifferentVersions == 1">
<div class="label">jQuery version</div>
<div class="result">{{phantomasResults.metrics.jQueryVersion}}</div>
<div class="icon-question"></div>
</div>
<div ng-if="phantomasResults.metrics.jQueryDifferentVersions > 1">
<div class="label">{{phantomasResults.metrics.jQueryDifferentVersions}}</b> versions loaded</div>
<div class="result"><span ng-repeat="version in phantomasResults.offenders.jQueryDifferentVersions">{{version}}<span ng-show="!$last"> & </span></span></div>
<div class="icon-question"></div>
</div>
</div>
</div>
</div>
<div>
<div ng-class="notations.cssComplexity">{{notations.cssComplexity}}</div>
<div class="notation">CSS complexity</div>
<div class="criteria">
<div class="table">
<div ng-if="phantomasResults.metrics.cssRules">
<div class="label">Rules count</div>
<div class="result">{{phantomasResults.metrics.cssRules}}</div>
<div class="icon-question"></div>
</div>
<div ng-if="phantomasResults.metrics.cssComplexSelectors">
<div class="label">Complex selectors</div>
<div class="result">
{{phantomasResults.metrics.cssComplexSelectors}}
<show-offenders modal-title="Complex selectors" metric-name="cssComplexSelectors" phantomas-results="phantomasResults"></show-offenders>
</div>
<div class="icon-question"></div>
</div>
</div>
</div>
</div>
<div>
<div ng-class="notations.badCss">{{notations.badCss}}</div>
<div class="notation">Bad CSS</div>
<div class="criteria">
<div class="table">
<div ng-if="phantomasResults.metrics.cssDuplicatedSelectors">
<div class="label">Duplicated selectors</div>
<div class="result">
{{phantomasResults.metrics.cssDuplicatedSelectors}}
<show-offenders modal-title="Duplicated selectors" metric-name="cssDuplicatedSelectors" phantomas-results="phantomasResults"></show-offenders>
</div>
<div class="icon-question"></div>
</div>
<div ng-if="phantomasResults.metrics.cssEmptyRules">
<div class="label">Empty rules</div>
<div class="result">
{{phantomasResults.metrics.cssEmptyRules}}
<show-offenders modal-title="Empty rules" metric-name="cssEmptyRules" phantomas-results="phantomasResults"></show-offenders>
</div>
<div class="icon-question"></div>
</div>
<div ng-if="phantomasResults.metrics.cssExpressions">
<div class="label">CSS expressions</div>
<div class="result">
{{phantomasResults.metrics.cssExpressions}}
<show-offenders modal-title="CSS expressions" metric-name="cssExpressions" phantomas-results="phantomasResults"></show-offenders>
</div>
<div class="icon-question"></div>
</div>
<div ng-if="phantomasResults.metrics.cssImportants">
<div class="label">Uses of !important</div>
<div class="result">
{{phantomasResults.metrics.cssImportants}}
<show-offenders modal-title="Uses of !important" metric-name="cssImportants" phantomas-results="phantomasResults"></show-offenders>
</div>
<div class="icon-question"></div>
</div>
<div ng-if="phantomasResults.metrics.cssOldIEFixes">
<div class="label">Old IE fixes</div>
<div class="result">
{{phantomasResults.metrics.cssOldIEFixes}}
<show-offenders modal-title="Old IE fixes" metric-name="cssOldIEFixes" phantomas-results="phantomasResults"></show-offenders>
</div>
<div class="icon-question"></div>
</div>
<div ng-if="phantomasResults.metrics.cssOldPropertyPrefixes">
<div class="label">Old prefixes</div>
<div class="result">
{{phantomasResults.metrics.cssOldPropertyPrefixes}}
<show-offenders modal-title="Old prefixes" metric-name="cssOldPropertyPrefixes" phantomas-results="phantomasResults"></show-offenders>
</div>
<div class="icon-question"></div>
</div>
<div ng-if="phantomasResults.metrics.cssUniversalSelectors">
<div class="label">Universal selectors</div>
<div class="result">
{{phantomasResults.metrics.cssUniversalSelectors}}
<show-offenders modal-title="Universal selectors" metric-name="cssUniversalSelectors" phantomas-results="phantomasResults"></show-offenders>
</div>
<div class="icon-question"></div>
</div>
<div ng-if="phantomasResults.metrics.cssRedundantBodySelectors">
<div class="label">Redundant body selectors</div>
<div class="result">
{{phantomasResults.metrics.cssRedundantBodySelectors}}
<show-offenders modal-title="Redundant body selectors" metric-name="cssRedundantBodySelectors" phantomas-results="phantomasResults"></show-offenders>
</div>
<div class="icon-question"></div>
</div>
</div>
</div>
</div>
<div>
<div ng-class="notations.requests">{{notations.requests}}</div>
<div class="notation">Requests number</div>
<div class="criteria">
<div class="table">
<div>
<div class="label">Total requests</div>
<div class="result">{{phantomasResults.metrics.requests}}</div>
<div class="icon-question"></div>
</div>
<div ng-if="phantomasResults.metrics.htmlCount">
<div class="label">Documents</div>
<div class="result">
{{phantomasResults.metrics.htmlCount}}
<show-offenders modal-title="HTML count" metric-name="htmlCount" phantomas-results="phantomasResults"></show-offenders>
</div>
<div></div>
</div>
<div ng-if="phantomasResults.metrics.jsCount">
<div class="label">Scripts</div>
<div class="result">
{{phantomasResults.metrics.jsCount}}
<show-offenders modal-title="JS count" metric-name="jsCount" phantomas-results="phantomasResults"></show-offenders>
</div>
<div></div>
</div>
<div ng-if="phantomasResults.metrics.cssCount">
<div class="label">Stylesheets</div>
<div class="result">
{{phantomasResults.metrics.cssCount}}
<show-offenders modal-title="CSS count" metric-name="cssCount" phantomas-results="phantomasResults"></show-offenders>
</div>
<div></div>
</div>
<div ng-if="phantomasResults.metrics.imageCount">
<div class="label">Images</div>
<div class="result">
{{phantomasResults.metrics.imageCount}}
<show-offenders modal-title="Image count" metric-name="imageCount" phantomas-results="phantomasResults"></show-offenders>
</div>
<div></div>
</div>
<div ng-if="phantomasResults.metrics.webfontCount">
<div class="label">Fonts</div>
<div class="result">
{{phantomasResults.metrics.webfontCount}}
<show-offenders modal-title="Webfont count" metric-name="webfontCount" phantomas-results="phantomasResults"></show-offenders>
</div>
<div></div>
</div>
<div ng-if="phantomasResults.metrics.videoCount">
<div class="label">Videos</div>
<div class="result">
{{phantomasResults.metrics.videoCount}}
<show-offenders modal-title="Video count" metric-name="videoCount" phantomas-results="phantomasResults"></show-offenders>
</div>
<div></div>
</div>
<div ng-if="phantomasResults.metrics.jsonCount">
<div class="label">JSON</div>
<div class="result">
{{phantomasResults.metrics.jsonCount}}
<show-offenders modal-title="JSON count" metric-name="jsonCount" phantomas-results="phantomasResults"></show-offenders>
</div>
<div></div>
</div>
<div ng-if="phantomasResults.metrics.otherCount">
<div class="label">Other</div>
<div class="result">
{{phantomasResults.metrics.otherCount}}
<show-offenders modal-title="Other count" metric-name="otherCount" phantomas-results="phantomasResults"></show-offenders>
</div>
<div></div>
</div>
</div>
</div>
</div>
<div>
<div ng-class="notations.network">{{notations.network}}</div>
<div class="notation">Network</div>
<div class="criteria">
<div class="table">
<div ng-if="phantomasResults.metrics.notFound">
<div class="label">404 not found</div>
<div class="result">
{{phantomasResults.metrics.otherCount}}
<show-offenders modal-title="404 not found" metric-name="notFound" phantomas-results="phantomasResults"></show-offenders>
</div>
<div class="icon-question"></div>
</div>
<div ng-if="phantomasResults.metrics.closedConnections">
<div class="label">Connections closed</div>
<div class="result">
{{phantomasResults.metrics.otherCount}}
<show-offenders modal-title="Connections closed" metric-name="closedConnections" phantomas-results="phantomasResults"></show-offenders>
</div>
<div class="icon-question"></div>
</div>
<div ng-if="phantomasResults.metrics.multipleRequests">
<div class="label">Duplicated requests</div>
<div class="result">
{{phantomasResults.metrics.otherCount}}
<show-offenders modal-title="Static assets requested more than once" metric-name="multipleRequests" phantomas-results="phantomasResults"></show-offenders>
</div>
<div class="icon-question"></div>
</div>
<div ng-if="phantomasResults.metrics.cachingDisabled">
<div class="label">Caching disabled</div>
<div class="result">
{{phantomasResults.metrics.otherCount}}
<show-offenders modal-title="Caching disabled" metric-name="cachingDisabled" phantomas-results="phantomasResults"></show-offenders>
</div>
<div class="icon-question"></div>
</div>
<div ng-if="phantomasResults.metrics.cachingNotSpecified">
<div class="label">Caching not specified</div>
<div class="result">
{{phantomasResults.metrics.otherCount}}
<show-offenders modal-title="Caching not specified" metric-name="cachingNotSpecified" phantomas-results="phantomasResults"></show-offenders>
</div>
<div class="icon-question"></div>
</div>
<div ng-if="phantomasResults.metrics.cachingTooShort">
<div class="label">Caching too short</div>
<div class="result">
{{phantomasResults.metrics.otherCount}}
<show-offenders modal-title="Caching too short" metric-name="cachingTooShort" phantomas-results="phantomasResults"></show-offenders>
</div>
<div class="icon-question"></div>
</div>
<div ng-if="phantomasResults.metrics.domains">
<div class="label">Different domains</div>
<div class="result">
{{phantomasResults.metrics.otherCount}}
<show-offenders modal-title="Different domains" metric-name="domains" phantomas-results="phantomasResults"></show-offenders>
</div>
<div class="icon-question"></div>
</div>
</div>
</div>
</div>
</div>
</div>
<div ng-show="view == 'execution' && !phantomasResults.error" class="execution">
<h2>Javascript Timeline</h2>
<p>
This graph gives a quick view of when the Javascript interactions with the DOM occur during the loading of the page.
</p>
<div class="timeline">
<div class="chart">
<div class="chartPoints">
<div ng-repeat="duration in timeline track by $index"
class="interval"
ng-class="{
domCreation: $index * timelineIntervalDuration < phantomasResults.metrics.domInteractive,
domInteractive: $index * timelineIntervalDuration >= phantomasResults.metrics.domInteractive
&& $index * timelineIntervalDuration < phantomasResults.metrics.domContentLoaded,
domContentLoaded: $index * timelineIntervalDuration >= phantomasResults.metrics.domContentLoaded
&& $index * timelineIntervalDuration < phantomasResults.metrics.domContentLoadedEnd,
domContentLoadedEnd: $index * timelineIntervalDuration >= phantomasResults.metrics.domContentLoadedEnd
&& $index * timelineIntervalDuration < phantomasResults.metrics.domComplete,
domComplete: $index * timelineIntervalDuration >= phantomasResults.metrics.domComplete
}">
<div style="height: {{100 * duration / timelineMax | number: 0}}px" class="color"></div>
<div class="tooltip detailsOverlay">
<div>Timestamp: {{$index * timelineIntervalDuration | number: 0}} ms</div>
</div>
</div>
</div>
<div class="startTime">0 ms</div>
<div class="endTime">{{endTime | number: 0}} ms</div>
</div>
<div class="legend">
<div class="titles">
<div class="domCreation"><div class="color"></div>DOM creation</div>
<div class="domInteractive"><div class="color"></div>DOM interactive</div>
<div class="domContentLoaded"><div class="color"></div>DOM content loaded event</div>
<div class="domContentLoadedEnd"><div class="color"></div>Page completion</div>
<div class="domComplete"><div class="color"></div>Page is complete</div>
</div>
<div class="tips">
<div>Executing Javascript and DOM queries here is a <b>bad practice</b> and slows down the DOM construction.</div>
<div>Some frameworks do things here, but it's not reliable and should be avoided.</div>
<div>Also known as "document ready". This is where you should execute <b>top-priority</b> scripts, like binding action buttons or launch a video player.</div>
<div>Here you can execute <b>mid-priority</b> tasks. Loading a script with createElement('script') is one way to do so.</div>
<div>The page is considered loaded, it's time for low <b>priority things</b> : trackers, social plugins, easter egg...</div>
</div>
</div>
</div>
<h2>Javascript Profiler</h2>
<p>
The table below shows the interactions between Javascript and the DOM. It is usefull to understand what's going on when the page loads.
<br>
The tool is slower than a real browser, so durations are a little exagerated.
</p>
<div class="filters">
<div>
<input type="checkbox" ng-model="textFilterOn" />
Filter by
<input type="text" ng-model="textFilter" placeholder="search..." class="textFilter" ng-change="textFilterOn = true" />
</div>
<div>
<input type="checkbox" ng-model="slowRequestsOn" id="slowRequests" />
<label for="slowRequests">Requests slower than</label>
<input type="number" value="5" min="0" ng-model="slowRequestsLimit" class="slowRequestsLimit"> ms
</div>
</div>
<div class="table">
<div class="headers">
<div><!-- index --></div>
<div>Type</div>
<div>Params</div>
<div><!-- details --></div>
<div>Duration</div>
<div>Timestamp</div>
</div>
<div ng-repeat="node in javascript.children"
ng-if="(!slowRequestsOn || node.data.time > slowRequestsLimit)
&& (!textFilterOn
|| !textFilter.length
|| node.data.type.indexOf(textFilter) >= 0
|| node.data.callDetails.arguments[0].indexOf(textFilter) >= 0
|| node.data.callDetails.arguments[1].indexOf(textFilter) >= 0
|| node.data.callDetails.arguments[2].indexOf(textFilter) >= 0
|| node.data.callDetails.arguments[3].indexOf(textFilter) >= 0)"
ng-class="{
showingDetails: node.data.showDetails,
jsError: node.data.type == 'error' || node.data.type == 'jQuery version change',
windowPerformance: node.data.type == 'domInteractive' || node.data.type == 'domContentLoaded' || node.data.type == 'domContentLoadedEnd' || node.data.type == 'domComplete'
}">
<div class="index">{{$index}}</div>
<div class="type">{{node.data.type}}</div>
<div class="value">
{{node.data.callDetails.arguments[0]}}
<span ng-if="node.data.callDetails.arguments.length > 1"> : {{node.data.callDetails.arguments[1]}}</span>
<span ng-if="node.data.callDetails.arguments.length > 2"> : {{node.data.callDetails.arguments[2]}}</span>
<span ng-if="node.data.callDetails.arguments.length > 3"> : {{node.data.callDetails.arguments[3]}}</span>
</div>
<div class="details">
<div class="icon-question"
ng-click="onNodeDetailsClick(node)"
ng-if="node.data.type != 'script loaded' && node.data.type != 'jQuery loaded'"></div>
<div class="detailsOverlay" ng-show="node.data.showDetails">
<div class="closeBtn" ng-click="onNodeDetailsClick(node)"></div>
<div ng-if="node.data.callDetails.context.domElement">
<h4>Called on DOM element</h4>
<div>{{node.data.callDetails.context.domElement}}</div>
</div>
<div ng-if="node.data.callDetails.context.length == 1 && node.data.callDetails.context.firstElementPath">
<h4>Called on 1 jQuery element</h4>
<div>{{node.data.callDetails.context.firstElementPath}}</div>
</div>
<div ng-if="node.data.callDetails.context.length > 1">
<h4>Called on {{node.data.callDetails.context.length}} jQuery elements</h4>
<p class="advice" ng-if="node.data.callDetails.context.length > 5">The .bind() method attaches the event listener to each jQuery element one by one. Using the .on() method is preferred if available (from v1.7).</p>
<p ng-if="node.data.callDetails.context.firstElementPath"><b>First one is:</b> {{node.data.callDetails.context.firstElementPath}}</p>
</div>
<div ng-if="node.data.parsedBacktrace">
<h4>Backtrace</h4>
<div class="table">
<div ng-repeat="trace in node.data.parsedBacktrace track by $index">
<div>{{trace.fnName || '(anonymous)'}}</div>
<div class="trace"><a href="{{trace.filePath}}" title="{{trace.filePath}}" target="_blank">{{trace.fileName || 'HTML'}}</a>:{{trace.line}}</div>
</div>
<div ng-if="node.data.parsedBacktrace.length == 0 && node.data.type != 'script loaded'">
<div>can't find any backtrace :/</div>
</div>
</div>
</div>
<div ng-if="node.children.length > 0">
<h4>Sub processes</h4>
<div class="table">
<div class="headers">
<div><!-- index --></div>
<div>Type</div>
<div>Params</div>
<div>Duration</div>
</div>
<div ng-repeat="node in node.children">
<div class="index">{{$index}}</div>
<div class="type">{{node.data.type}}</div>
<div class="value">
{{node.data.callDetails.arguments[0]}}
<span ng-if="node.data.callDetails.arguments.length > 1"> : {{node.data.callDetails.arguments[1]}}</span>
<span ng-if="node.data.callDetails.arguments.length > 2"> : {{node.data.callDetails.arguments[2]}}</span>
<span ng-if="node.data.callDetails.arguments.length > 3"> : {{node.data.callDetails.arguments[3]}}</span>
</div>
<div class="duration" ng-if="node.data.time != undefined">{{node.data.time}} ms</div>
<div class="duration" ng-if="node.data.time == undefined"></div>
</div>
</div>
</div>
</div>
</div>
<div class="duration" ng-if="node.data.time != undefined">
{{node.data.time}} ms
<span ng-if="node.data.time > slowRequestsLimit" class="icon-warning" title="Slower than {{slowRequestsLimit}} ms"></span>
</div>
<div class="duration" ng-if="node.data.time == undefined"></div>
<div class="startTime" ng-class="{
domCreation: node.data.timestamp < phantomasResults.metrics.domInteractive,
domInteractive: node.data.timestamp >= phantomasResults.metrics.domInteractive
&& node.data.timestamp < phantomasResults.metrics.domContentLoaded,
domContentLoaded: node.data.timestamp >= phantomasResults.metrics.domContentLoaded
&& node.data.timestamp < phantomasResults.metrics.domContentLoadedEnd,
domContentLoadedEnd: node.data.timestamp >= phantomasResults.metrics.domContentLoadedEnd
&& node.data.timestamp < phantomasResults.metrics.domComplete,
domComplete: node.data.timestamp >= phantomasResults.metrics.domComplete
}">{{node.data.timestamp | number: 0}}</div>
</div>
</div>
</div>
<div ng-show="view == 'metrics' && !phantomasResults.error" class="metrics">
<h2>Metrics from Phantomas report</h2>
<p><a href="https://github.com/macbre/phantomas" target="_blank">Phantomas</a> is a web performance metrics collector. You can find here the (almost) entire list of metrics from Phantomas.</p>
<div ng-repeat="(moduleName, module) in metricsModule">
<h4>{{moduleName}}</h4>
<div ng-repeat="(metricName, metric) in module" ng-if="phantomasResults.metrics[metricName] >= 0" class="module" id="metric_{{metricName}}">
<div class="value">
{{metricName}}: {{phantomasResults.metrics[metricName] | number: 0}}
<span ng-if="metric.unit == 'ms' || metric.unit == 'bytes' || metric.unit == '%'">{{metric.unit}}</span>
</div>
<div class="legend">
{{metric.desc}}
<span ng-if="metric.unreliable">(unreliable)</span>
</div>
<div ng-if="phantomasResults.offenders[metricName]" class="offenders">
<div ng-if="!metric.showingOffenders" ng-click="metric.showingOffenders = true">Show offenders</div>
<div ng-if="metric.showingOffenders" ng-click="metric.showingOffenders = false">Hide offenders</div>
<ul ng-if="metric.showingOffenders">
<li ng-repeat="offender in phantomasResults.offenders[metricName] track by $index">
{{offender}}
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
<div class="footer">
<p><b>Yellow Lab Tools</b> is an open source project by <a href="http://www.gaelmetais.com" target="_blank">Gaël Métais</a>, based on <a href="https://github.com/macbre/phantomas" target="_blank">Phantomas</a>.<br>If you like it, <a href="https://github.com/gmetais/YellowLabTools" target="_blank" class="star">give it a <span>&#9733;</span> on GitHub</a>!</p>
</div>
<script>
var _phantomas_results = %%RESULTS%%;
var _phantomas_metadata = %%METADATA%%;
var GA_ID = '%%GA_ID%%';
if (GA_ID.length > 0 && window.location.host === 'yellowlab.tools') {
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', GA_ID, 'auto');
ga('send', 'pageview');
}
</script>
</body>
</html>